From f0819c18672a939ad2a6c00c6fa37f73be7a54f3 Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Tue, 15 May 2018 12:11:18 +0100 Subject: New upstream release. --- Detail.c | 446 +++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 249 insertions(+), 197 deletions(-) (limited to 'Detail.c') diff --git a/Detail.c b/Detail.c index 509b0d41..4dcf81dd 100644 --- a/Detail.c +++ b/Detail.c @@ -25,6 +25,7 @@ #include "mdadm.h" #include "md_p.h" #include "md_u.h" +#include #include static int cmpstringp(const void *p1, const void *p2) @@ -51,12 +52,9 @@ static int add_device(const char *dev, char ***p_devices, int Detail(char *dev, struct context *c) { /* - * Print out details for an md array by using - * GET_ARRAY_INFO and GET_DISK_INFO ioctl calls + * Print out details for an md array */ - int fd = open(dev, O_RDONLY); - int vers; mdu_array_info_t array; mdu_disk_info_t *disks; int next; @@ -67,8 +65,6 @@ int Detail(char *dev, struct context *c) int max_devices = 0, n_devices = 0; int spares = 0; struct stat stb; - int is_26 = get_linux_version() >= 2006000; - int is_rebuilding = 0; int failed = 0; struct supertype *st; char *subarray = NULL; @@ -84,41 +80,48 @@ int Detail(char *dev, struct context *c) char *avail = NULL; int external; int inactive; + int is_container = 0; if (fd < 0) { pr_err("cannot open %s: %s\n", dev, strerror(errno)); return rv; } - vers = md_get_version(fd); - if (vers < 0) { - pr_err("%s does not appear to be an md device\n", - dev); - close(fd); - return rv; - } - if (vers < 9000) { - pr_err("cannot get detail for md device %s: driver version too old.\n", - dev); - close(fd); - return rv; + sra = sysfs_read(fd, NULL, GET_VERSION | GET_DEVS | + GET_ARRAY_STATE | GET_STATE); + if (!sra) { + if (md_get_array_info(fd, &array)) { + pr_err("%s does not appear to be an md device\n", dev); + close(fd); + return rv; + } } - sra = sysfs_read(fd, NULL, GET_VERSION|GET_DEVS); - external = (sra != NULL && sra->array.major_version == -1 - && sra->array.minor_version == -2); + external = (sra != NULL && sra->array.major_version == -1 && + sra->array.minor_version == -2); + inactive = (sra != NULL && !md_array_is_active(sra)); st = super_by_fd(fd, &subarray); - if (ioctl(fd, GET_ARRAY_INFO, &array) == 0) { - inactive = 0; - } else if (errno == ENODEV && sra) { - array = sra->array; - inactive = 1; - } else { - pr_err("cannot get array detail for %s: %s\n", - dev, strerror(errno)); - close(fd); - return rv; + if (md_get_array_info(fd, &array)) { + if (errno == ENODEV) { + if (sra->array.major_version == -1 && + sra->array.minor_version == -1 && + sra->devs == NULL) { + pr_err("Array associated with md device %s does not exist.\n", + dev); + close(fd); + sysfs_free(sra); + return rv; + } + array = sra->array; + } else { + pr_err("cannot get array detail for %s: %s\n", + dev, strerror(errno)); + close(fd); + return rv; + } } + if (array.raid_disks == 0 && external) + is_container = 1; if (fstat(fd, &stb) != 0 && !S_ISBLK(stb.st_mode)) stb.st_rdev = 0; rv = 0; @@ -146,22 +149,23 @@ int Detail(char *dev, struct context *c) } /* try to load a superblock. Try sra->devs first, then try ioctl */ - if (st && !info) for (d = 0, subdev = sra ? sra->devs : NULL; - d < max_disks || subdev; - subdev ? (void)(subdev = subdev->next) : (void)(d++)){ + if (st && !info) + for (d = 0, subdev = sra ? sra->devs : NULL; + d < max_disks || subdev; + subdev ? (void)(subdev = subdev->next) : (void)(d++)){ mdu_disk_info_t disk; char *dv; int fd2; int err; + if (subdev) disk = subdev->disk; else { disk.number = d; - if (ioctl(fd, GET_DISK_INFO, &disk) < 0) + if (md_get_disk_info(fd, &disk) < 0) continue; if (d >= array.raid_disks && - disk.major == 0 && - disk.minor == 0) + disk.major == 0 && disk.minor == 0) continue; } @@ -227,7 +231,7 @@ int Detail(char *dev, struct context *c) printf("MD_LEVEL=%s\n", str); printf("MD_DEVICES=%d\n", array.raid_disks); } else { - if (!inactive) + if (is_container) printf("MD_LEVEL=container\n"); printf("MD_DEVICES=%d\n", array.nr_disks); } @@ -239,7 +243,8 @@ int Detail(char *dev, struct context *c) printf("MD_METADATA=%s\n", sra->text_version); else printf("MD_METADATA=%d.%d\n", - array.major_version, array.minor_version); + array.major_version, + array.minor_version); } if (st && st->sb && info) { @@ -247,12 +252,12 @@ int Detail(char *dev, struct context *c) struct map_ent *mp, *map = NULL; fname_from_uuid(st, info, nbuf, ':'); - printf("MD_UUID=%s\n", nbuf+5); + printf("MD_UUID=%s\n", nbuf + 5); mp = map_by_uuid(&map, info->uuid); if (mp && mp->path && strncmp(mp->path, "/dev/md/", 8) == 0) { printf("MD_DEVNAME="); - print_escape(mp->path+8); + print_escape(mp->path + 8); putchar('\n'); } @@ -276,20 +281,26 @@ int Detail(char *dev, struct context *c) if (sra) { struct mdinfo *mdi; for (mdi = sra->devs; mdi; mdi = mdi->next) { - char *path = - map_dev(mdi->disk.major, - mdi->disk.minor, 0); + char *path; + char *sysdev = xstrdup(mdi->sys_name + 1); + char *cp; + + path = map_dev(mdi->disk.major, + mdi->disk.minor, 0); + for (cp = sysdev; *cp; cp++) + if (!isalnum(*cp)) + *cp = '_'; if (mdi->disk.raid_disk >= 0) printf("MD_DEVICE_%s_ROLE=%d\n", - mdi->sys_name+4, + sysdev, mdi->disk.raid_disk); else printf("MD_DEVICE_%s_ROLE=spare\n", - mdi->sys_name+4); + sysdev); if (path) printf("MD_DEVICE_%s_DEV=%s\n", - mdi->sys_name+4, path); + sysdev, path); } } goto out; @@ -297,24 +308,23 @@ int Detail(char *dev, struct context *c) disks = xmalloc(max_disks * 2 * sizeof(mdu_disk_info_t)); for (d = 0; d < max_disks * 2; d++) { - disks[d].state = (1<devs; mdi; mdi = mdi->next) { - disks[next++] = mdi->disk; - disks[next-1].number = -1; - } + for (mdi = sra->devs; mdi; mdi = mdi->next) { + disks[next++] = mdi->disk; + disks[next - 1].number = -1; + } } else for (d = 0; d < max_disks; d++) { mdu_disk_info_t disk; disk.number = d; - if (ioctl(fd, GET_DISK_INFO, &disk) < 0) { + if (md_get_disk_info(fd, &disk) < 0) { if (d < array.raid_disks) pr_err("cannot get device detail for device %d: %s\n", d, strerror(errno)); @@ -322,21 +332,23 @@ int Detail(char *dev, struct context *c) } if (disk.major == 0 && disk.minor == 0) continue; - if (disk.raid_disk >= 0 && disk.raid_disk < array.raid_disks - && disks[disk.raid_disk*2].state == (1<= 0 && disk.raid_disk < array.raid_disks - && disks[disk.raid_disk*2+1].state == (1<= 0 && disk.raid_disk < array.raid_disks && + disks[disk.raid_disk * 2].state == (1 << MD_DISK_REMOVED) && + ((disk.state & (1 << MD_DISK_JOURNAL)) == 0)) + disks[disk.raid_disk * 2] = disk; + else if (disk.raid_disk >= 0 && + disk.raid_disk < array.raid_disks && + disks[disk.raid_disk * 2 + 1].state == + (1 << MD_DISK_REMOVED) && + !(disk.state & (1 << MD_DISK_JOURNAL))) + disks[disk.raid_disk * 2 + 1] = disk; + else if (next < max_disks * 2) disks[next++] = disk; } avail = xcalloc(array.raid_disks, 1); - for (d= 0; d < array.raid_disks; d++) { + for (d = 0; d < array.raid_disks; d++) { if ((disks[d*2].state & (1<brief) { mdu_bitmap_file_t bmf; - printf("%sARRAY %s", inactive ? "INACTIVE-":"", dev); + if (inactive && !is_container) + printf("INACTIVE-ARRAY %s", dev); + else + printf("ARRAY %s", dev); if (c->verbose > 0) { if (array.raid_disks) printf(" level=%s num-devices=%d", - str?str:"-unknown-", - array.raid_disks ); - else if (!inactive) + str ? str : "-unknown-", + array.raid_disks); + else if (is_container) printf(" level=container num-devices=%d", array.nr_disks); else @@ -367,14 +382,12 @@ int Detail(char *dev, struct context *c) if (sra && sra->array.major_version < 0) printf(" metadata=%s", sra->text_version); else - printf(" metadata=%d.%d", - array.major_version, array.minor_version); + printf(" metadata=%d.%d", array.major_version, + array.minor_version); } /* Only try GET_BITMAP_FILE for 0.90.01 and later */ - if (vers >= 9001 && - ioctl(fd, GET_BITMAP_FILE, &bmf) == 0 && - bmf.pathname[0]) { + if (ioctl(fd, GET_BITMAP_FILE, &bmf) == 0 && bmf.pathname[0]) { printf(" bitmap=%s", bmf.pathname); } } else { @@ -385,7 +398,7 @@ int Detail(char *dev, struct context *c) char *devnm; devnm = stat2devnm(&stb); - for (e=ms; e; e=e->next) + for (e = ms; e; e = e->next) if (strcmp(e->devnm, devnm) == 0) break; if (!get_dev_size(fd, NULL, &larray_size)) @@ -394,64 +407,69 @@ int Detail(char *dev, struct context *c) printf("%s:\n", dev); if (container) - printf(" Container : %s, member %s\n", container, member); + printf(" Container : %s, member %s\n", + container, member); else { - if (sra && sra->array.major_version < 0) - printf(" Version : %s\n", sra->text_version); - else - printf(" Version : %d.%d\n", - array.major_version, array.minor_version); + if (sra && sra->array.major_version < 0) + printf(" Version : %s\n", + sra->text_version); + else + printf(" Version : %d.%d\n", + array.major_version, + array.minor_version); } atime = array.ctime; if (atime) - printf(" Creation Time : %.24s\n", ctime(&atime)); - if (array.raid_disks == 0 && external) + printf(" Creation Time : %.24s\n", ctime(&atime)); + if (is_container) str = "container"; if (str) - printf(" Raid Level : %s\n", str); + printf(" Raid Level : %s\n", str); if (larray_size) - printf(" Array Size : %llu%s\n", (larray_size>>10), + printf(" Array Size : %llu%s\n", + (larray_size >> 10), human_size(larray_size)); if (array.level >= 1) { if (sra) array.major_version = sra->array.major_version; if (array.major_version != 0 && (larray_size >= 0xFFFFFFFFULL|| array.size == 0)) { - unsigned long long dsize = get_component_size(fd); + unsigned long long dsize; + + dsize = get_component_size(fd); if (dsize > 0) - printf(" Used Dev Size : %llu%s\n", + printf(" Used Dev Size : %llu%s\n", dsize/2, human_size((long long)dsize<<9)); else - printf(" Used Dev Size : unknown\n"); + printf(" Used Dev Size : unknown\n"); } else - printf(" Used Dev Size : %lu%s\n", + printf(" Used Dev Size : %lu%s\n", (unsigned long)array.size, - human_size((unsigned long long)array.size<<10)); + human_size((unsigned long long) + array.size << 10)); } if (array.raid_disks) - printf(" Raid Devices : %d\n", array.raid_disks); - printf(" Total Devices : %d\n", array.nr_disks); + printf(" Raid Devices : %d\n", array.raid_disks); + printf(" Total Devices : %d\n", array.nr_disks); if (!container && ((sra == NULL && array.major_version == 0) || (sra && sra->array.major_version == 0))) - printf("Preferred Minor : %d\n", array.md_minor); + printf(" Preferred Minor : %d\n", array.md_minor); if (sra == NULL || sra->array.major_version >= 0) - printf(" Persistence : Superblock is %spersistent\n", - array.not_persistent?"not ":""); + printf(" Persistence : Superblock is %spersistent\n", + array.not_persistent ? "not " : ""); printf("\n"); /* Only try GET_BITMAP_FILE for 0.90.01 and later */ - if (vers >= 9001 && - ioctl(fd, GET_BITMAP_FILE, &bmf) == 0 && - bmf.pathname[0]) { - printf(" Intent Bitmap : %s\n", bmf.pathname); + if (ioctl(fd, GET_BITMAP_FILE, &bmf) == 0 && bmf.pathname[0]) { + printf(" Intent Bitmap : %s\n", bmf.pathname); printf("\n"); } else if (array.state & (1<percent < 0 && e->percent != RESYNC_PENDING && - e->percent != RESYNC_DELAYED)) ? "" : sync_action[e->resync], + printf(" State : %s%s%s%s%s%s \n", + (array.state & (1 << MD_SB_CLEAN)) ? + "clean" : "active", st, + (!e || (e->percent < 0 && + e->percent != RESYNC_PENDING && + e->percent != RESYNC_DELAYED)) ? + "" : sync_action[e->resync], larray_size ? "": ", Not Started", - (e && e->percent == RESYNC_DELAYED) ? " (DELAYED)": "", - (e && e->percent == RESYNC_PENDING) ? " (PENDING)": ""); - } else if (inactive) { - printf(" State : inactive\n"); + (e && e->percent == RESYNC_DELAYED) ? + " (DELAYED)": "", + (e && e->percent == RESYNC_PENDING) ? + " (PENDING)": ""); + } else if (inactive && !is_container) { + printf(" State : inactive\n"); } if (array.raid_disks) - printf(" Active Devices : %d\n", array.active_disks); + printf(" Active Devices : %d\n", array.active_disks); if (array.working_disks > 0) - printf("Working Devices : %d\n", array.working_disks); + printf(" Working Devices : %d\n", + array.working_disks); if (array.raid_disks) { - printf(" Failed Devices : %d\n", array.failed_disks); - printf(" Spare Devices : %d\n", array.spare_disks); + printf(" Failed Devices : %d\n", array.failed_disks); + printf(" Spare Devices : %d\n", array.spare_disks); } printf("\n"); if (array.level == 5) { str = map_num(r5layout, array.layout); - printf(" Layout : %s\n", str?str:"-unknown-"); + printf(" Layout : %s\n", + str ? str : "-unknown-"); } if (array.level == 6) { str = map_num(r6layout, array.layout); - printf(" Layout : %s\n", str?str:"-unknown-"); + printf(" Layout : %s\n", + str ? str : "-unknown-"); } if (array.level == 10) { - printf(" Layout :"); + printf(" Layout :"); print_r10_layout(array.layout); printf("\n"); } @@ -504,96 +530,122 @@ int Detail(char *dev, struct context *c) case 10: case 6: if (array.chunk_size) - printf(" Chunk Size : %dK\n\n", + printf(" Chunk Size : %dK\n\n", array.chunk_size/1024); break; case -1: - printf(" Rounding : %dK\n\n", array.chunk_size/1024); + printf(" Rounding : %dK\n\n", + array.chunk_size/1024); + break; + default: break; - default: break; + } + + if (array.raid_disks) { + struct mdinfo *mdi; + + mdi = sysfs_read(fd, NULL, GET_CONSISTENCY_POLICY); + if (mdi) { + char *policy = map_num(consistency_policies, + mdi->consistency_policy); + sysfs_free(mdi); + if (policy) + printf("Consistency Policy : %s\n\n", + policy); + } } if (e && e->percent >= 0) { static char *sync_action[] = { - "Rebuild", "Resync", - "Reshape", "Check"}; - printf(" %7s Status : %d%% complete\n", sync_action[e->resync], e->percent); - is_rebuilding = 1; + "Rebuild", "Resync", "Reshape", "Check"}; + printf(" %7s Status : %d%% complete\n", + sync_action[e->resync], e->percent); } free_mdstat(ms); if ((st && st->sb) && (info && info->reshape_active)) { #if 0 This is pretty boring - printf(" Reshape pos'n : %llu%s\n", (unsigned long long) info->reshape_progress<<9, - human_size((unsigned long long)info->reshape_progress<<9)); + printf(" Reshape pos'n : %llu%s\n", + (unsigned long long) info->reshape_progress << 9, + human_size((unsigned long long) + info->reshape_progress << 9)); #endif if (info->delta_disks != 0) - printf(" Delta Devices : %d, (%d->%d)\n", + printf(" Delta Devices : %d, (%d->%d)\n", info->delta_disks, array.raid_disks - info->delta_disks, array.raid_disks); if (info->new_level != array.level) { str = map_num(pers, info->new_level); - printf(" New Level : %s\n", str?str:"-unknown-"); + printf(" New Level : %s\n", + str ? str : "-unknown-"); } if (info->new_level != array.level || info->new_layout != array.layout) { if (info->new_level == 5) { - str = map_num(r5layout, info->new_layout); - printf(" New Layout : %s\n", - str?str:"-unknown-"); + str = map_num(r5layout, + info->new_layout); + printf(" New Layout : %s\n", + str ? str : "-unknown-"); } if (info->new_level == 6) { - str = map_num(r6layout, info->new_layout); - printf(" New Layout : %s\n", - str?str:"-unknown-"); + str = map_num(r6layout, + info->new_layout); + printf(" New Layout : %s\n", + str ? str : "-unknown-"); } if (info->new_level == 10) { - printf(" New Layout : near=%d, %s=%d\n", - info->new_layout&255, - (info->new_layout&0x10000)?"offset":"far", - (info->new_layout>>8)&255); + printf(" New Layout : near=%d, %s=%d\n", + info->new_layout & 255, + (info->new_layout & 0x10000) ? + "offset" : "far", + (info->new_layout >> 8) & 255); } } if (info->new_chunk != array.chunk_size) - printf(" New Chunksize : %dK\n", info->new_chunk/1024); + printf(" New Chunksize : %dK\n", + info->new_chunk/1024); printf("\n"); } else if (e && e->percent >= 0) printf("\n"); if (st && st->sb) st->ss->detail_super(st, c->homehost); - if (array.raid_disks == 0 && sra && sra->array.major_version == -1 - && sra->array.minor_version == -2 && sra->text_version[0] != '/') { + if (array.raid_disks == 0 && sra && + sra->array.major_version == -1 && + sra->array.minor_version == -2 && + sra->text_version[0] != '/') { /* This looks like a container. Find any active arrays * That claim to be a member. */ DIR *dir = opendir("/sys/block"); struct dirent *de; - printf(" Member Arrays :"); + printf(" Member Arrays :"); while (dir && (de = readdir(dir)) != NULL) { - char path[200]; + char path[287]; char vbuf[1024]; int nlen = strlen(sra->sys_name); dev_t devid; if (de->d_name[0] == '.') continue; - sprintf(path, "/sys/block/%s/md/metadata_version", + sprintf(path, + "/sys/block/%s/md/metadata_version", de->d_name); if (load_sys(path, vbuf, sizeof(vbuf)) < 0) continue; - if (strncmp(vbuf, "external:", 9) != 0 || - !is_subarray(vbuf+9) || - strncmp(vbuf+10, sra->sys_name, nlen) != 0 || - vbuf[10+nlen] != '/') + if (strncmp(vbuf, "external:", 9) || + !is_subarray(vbuf + 9) || + strncmp(vbuf + 10, sra->sys_name, nlen) || + vbuf[10 + nlen] != '/') continue; devid = devnm2devid(de->d_name); - printf(" %s", map_dev_preferred( - major(devid), - minor(devid), 1, c->prefer)); + printf(" %s", + map_dev_preferred(major(devid), + minor(devid), 1, + c->prefer)); } if (dir) closedir(dir); @@ -607,24 +659,23 @@ This is pretty boring } free(info); - for (d= 0; d < max_disks * 2; d++) { + for (d = 0; d < max_disks * 2; d++) { char *dv; mdu_disk_info_t disk = disks[d]; - if (d >= array.raid_disks*2 && - disk.major == 0 && - disk.minor == 0) + if (d >= array.raid_disks * 2 && + disk.major == 0 && disk.minor == 0) continue; - if ((d & 1) && - disk.major == 0 && - disk.minor == 0) + if ((d & 1) && disk.major == 0 && disk.minor == 0) continue; if (!c->brief) { - if (d == array.raid_disks*2) printf("\n"); + if (d == array.raid_disks*2) + printf("\n"); if (disk.number < 0 && disk.raid_disk < 0) printf(" - %5d %5d - ", disk.major, disk.minor); - else if (disk.raid_disk < 0 || disk.state & (1<brief && array.raid_disks) { - - if (disk.state & (1<= 0) failed++; } - if (disk.state & (1<> 8) & 0xff; int copies = nc*fc; - if (fc == 1 && array.raid_disks % copies == 0 && copies <= 26) { - /* We can divide the devices into 'sets' */ - int set = disk.raid_disk % copies; + if (fc == 1 && + array.raid_disks % copies == 0 && + copies <= 26) { + /* We can divide the devices + into 'sets' */ + int set; + set = disk.raid_disk % copies; printf(" set-%c", set + 'A'); } } } - if (disk.state & (1<= 0) - printf(" rebuilding"); - } else if (is_rebuilding && failed) { - /* Taking a bit of a risk here, we remove the - * device from the array, and then put it back. - * If this fails, we are rebuilding - */ - int err = ioctl(fd, HOT_REMOVE_DISK, makedev(disk.major, disk.minor)); - if (err == 0) ioctl(fd, HOT_ADD_DISK, makedev(disk.major, disk.minor)); - if (err && errno == EBUSY) - printf(" rebuilding"); - } + if (disk.raid_disk < array.raid_disks && + disk.raid_disk >= 0) + printf(" rebuilding"); } } - if (disk.state == 0) spares++; - dv=map_dev_preferred(disk.major, disk.minor, 0, c->prefer); + if (disk.state == 0) + spares++; + dv = map_dev_preferred(disk.major, disk.minor, 0, c->prefer); if (dv != NULL) { if (c->brief) n_devices = add_device(dv, &devices, - &max_devices, - n_devices); + &max_devices, n_devices); else printf(" %s", dv); } - if (!c->brief) printf("\n"); + if (!c->brief) + printf("\n"); } - if (spares && c->brief && array.raid_disks) printf(" spares=%d", spares); + if (spares && c->brief && array.raid_disks) + printf(" spares=%d", spares); if (c->brief && st && st->sb) st->ss->brief_detail_super(st); if (st) @@ -707,8 +760,7 @@ This is pretty boring if (c->brief) printf("\n"); if (c->test && - !enough(array.level, array.raid_disks, array.layout, - 1, avail)) + !enough(array.level, array.raid_disks, array.layout, 1, avail)) rv = 2; free(disks); -- cgit v1.2.3