X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=Detail.c;h=94156288a19fc50be64fd1c881cf6371c64bfdb7;hb=ff63406404b1a715282180570af7a4f1afabe634;hp=0d6bcf5ee7909ce1d1fb31e165076b7553c3c19c;hpb=78fbcc10312649f2f4f88283e3f19dce9b205733;p=thirdparty%2Fmdadm.git diff --git a/Detail.c b/Detail.c index 0d6bcf5e..94156288 100644 --- a/Detail.c +++ b/Detail.c @@ -1,7 +1,7 @@ /* * mdadm - manage Linux "md" devices aka RAID arrays. * - * Copyright (C) 2001-2006 Neil Brown + * Copyright (C) 2001-2009 Neil Brown * * * This program is free software; you can redistribute it and/or modify @@ -19,12 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Neil Brown - * Email: - * Paper: Neil Brown - * School of Computer Science and Engineering - * The University of New South Wales - * Sydney, 2052 - * Australia + * Email: */ #include "mdadm.h" @@ -53,9 +48,10 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) int is_26 = get_linux_version() >= 2006000; int is_rebuilding = 0; int failed = 0; - struct supertype *st = NULL; + struct supertype *st; + char *subarray = NULL; int max_disks = MD_SB_DISKS; /* just a default */ - struct mdinfo info; + struct mdinfo *info = NULL; struct mdinfo *sra; char *member = NULL; char *container = NULL; @@ -93,7 +89,7 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) return rv; } sra = sysfs_read(fd, 0, GET_VERSION); - st = super_by_fd(fd); + st = super_by_fd(fd, &subarray); if (fstat(fd, &stb) != 0 && !S_ISBLK(stb.st_mode)) stb.st_rdev = 0; @@ -102,23 +98,22 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) if (st) max_disks = st->max_devs; - if (sra && is_subarray(sra->text_version) && - strchr(sra->text_version+1, '/')) { + if (subarray) { /* This is a subarray of some container. * We want the name of the container, and the member */ - char *s = strchr(sra->text_version+1, '/'); - int dn; - *s++ = '\0'; - member = s; - dn = devname2devnum(sra->text_version+1); + int dn = st->container_dev; + + member = subarray; container = map_dev(dev2major(dn), dev2minor(dn), 1); } /* try to load a superblock */ - for (d= 0; dsb) && - (array.raid_disks == 0 || - (disk.state & (1<=0 && st && - st->ss->load_super(st, fd2, NULL) == 0) { - st->ss->getinfo_super(st, &info); - if (array.raid_disks != 0 && /* container */ - (info.array.ctime != array.ctime || - info.array.level != array.level)) - st->ss->free_super(st); - } - if (fd2 >= 0) close(fd2); - } + + if (array.raid_disks > 0 && + (disk.state & (1 << MD_DISK_ACTIVE)) == 0) + continue; + + dv = map_dev(disk.major, disk.minor, 1); + if (!dv) + continue; + + fd2 = dev_open(dv, O_RDONLY); + if (fd2 < 0) + continue; + + if (st->sb) + st->ss->free_super(st); + + err = st->ss->load_super(st, fd2, NULL); + close(fd2); + if (err) + continue; + if (info) + free(info); + if (subarray) + info = st->ss->container_content(st, subarray); + else { + info = malloc(sizeof(*info)); + st->ss->getinfo_super(st, info, NULL); } + if (!info) + continue; + + if (array.raid_disks != 0 && /* container */ + (info->array.ctime != array.ctime || + info->array.level != array.level)) { + st->ss->free_super(st); + continue; + } + /* some formats (imsm) have free-floating-spares + * with a uuid of uuid_match_any, they don't + * have very good info about the rest of the + * container, so keep searching when + * encountering such a device. Otherwise, stop + * after the first successful call to + * ->load_super. + */ + if (memcmp(uuid_match_any, + info->uuid, + sizeof(uuid_match_any)) == 0) { + st->ss->free_super(st); + continue; + } + break; } /* Ok, we have some info to print... */ @@ -166,18 +194,17 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) if (sra && sra->array.major_version < 0) printf("MD_METADATA=%s\n", sra->text_version); else - printf("MD_METADATA=%d.%02d\n", + printf("MD_METADATA=%d.%d\n", array.major_version, array.minor_version); } - if (st && st->sb) { - struct mdinfo info; + if (st && st->sb && info) { char nbuf[64]; struct map_ent *mp, *map = NULL; - st->ss->getinfo_super(st, &info); - fname_from_uuid(st, &info, nbuf, ':'); + + fname_from_uuid(st, info, nbuf, ':'); printf("MD_UUID=%s\n", nbuf+5); - mp = map_by_uuid(&map, info.uuid); + mp = map_by_uuid(&map, info->uuid); if (mp && mp->path && strncmp(mp->path, "/dev/md/", 8) == 0) printf("MD_DEVNAME=%s\n", mp->path+8); @@ -186,7 +213,12 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) st->ss->export_detail_super(st); } else { struct map_ent *mp, *map = NULL; + char nbuf[64]; mp = map_by_devnum(&map, fd2devnum(fd)); + if (mp) { + __fname_from_uuid(mp->uuid, 0, nbuf, ':'); + printf("MD_UUID=%s\n", nbuf+5); + } if (mp && mp->path && strncmp(mp->path, "/dev/md/", 8) == 0) printf("MD_DEVNAME=%s\n", mp->path+8); @@ -194,16 +226,54 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) goto out; } + disks = malloc(max_disks * sizeof(mdu_disk_info_t)); + for (d=0; d= 0 && disk.raid_disk < array.raid_disks) + disks[disk.raid_disk] = disk; + else if (next < max_disks) + disks[next++] = disk; + } + + avail = calloc(array.raid_disks, 1); + + for (d= 0; d < array.raid_disks; d++) { + mdu_disk_info_t disk = disks[d]; + + if ((disk.state & (1< 1) { + if (array.raid_disks) + printf(" level=%s num-devices=%d", + c?c:"-unknown-", + array.raid_disks ); + else + printf(" level=container num-devices=%d", + array.nr_disks); + } if (container) { printf(" container=%s", container); printf(" member=%s", member); @@ -211,7 +281,7 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) if (sra && sra->array.major_version < 0) printf(" metadata=%s", sra->text_version); else - printf(" metadata=%d.%02d", + printf(" metadata=%d.%d", array.major_version, array.minor_version); } @@ -227,7 +297,7 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) struct mdstat_ent *ms = mdstat_read(0, 0); struct mdstat_ent *e; int devnum = array.md_minor; - if (major(stb.st_rdev) == get_mdp_major()) + if (major(stb.st_rdev) == (unsigned)get_mdp_major()) devnum = -1 - devnum; for (e=ms; e; e=e->next) @@ -244,7 +314,7 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) if (sra && sra->array.major_version < 0) printf(" Version : %s\n", sra->text_version); else - printf(" Version : %d.%02d\n", + printf(" Version : %d.%d\n", array.major_version, array.minor_version); } @@ -261,8 +331,8 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) unsigned long long dsize = get_component_size(fd); if (dsize > 0) printf(" Used Dev Size : %llu%s\n", - dsize, - human_size((long long)dsize<<10)); + dsize/2, + human_size((long long)dsize<<9)); else printf(" Used Dev Size : unknown\n"); } else @@ -291,13 +361,23 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) atime = array.utime; if (atime) printf(" Update Time : %.24s\n", ctime(&atime)); - if (array.raid_disks) + if (array.raid_disks) { + static char *sync_action[] = {", recovering",", resyncing",", reshaping",", checking"}; + char *st; + if (avail_disks == array.raid_disks) + st = ""; + else if (!enough(array.level, array.raid_disks, + array.layout, 1, avail, avail_disks)) + st = ", FAILED"; + else + st = ", degraded"; + printf(" State : %s%s%s%s\n", (array.state&(1<percent < 0) ? "" : - (e->resync) ? ", resyncing": ", recovering", + st, + (!e || e->percent < 0) ? "" : sync_action[e->resync], larray_size ? "": ", Not Started"); + } if (array.raid_disks) printf(" Active Devices : %d\n", array.active_disks); printf("Working Devices : %d\n", array.working_disks); @@ -310,6 +390,10 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) c = map_num(r5layout, array.layout); printf(" Layout : %s\n", c?c:"-unknown-"); } + if (array.level == 6) { + c = map_num(r6layout, array.layout); + printf(" Layout : %s\n", c?c:"-unknown-"); + } if (array.level == 10) { printf(" Layout :"); print_r10_layout(array.layout); @@ -333,45 +417,50 @@ int Detail(char *dev, int brief, int export, int test, char *homehost) if (e && e->percent >= 0) { printf(" Re%s Status : %d%% complete\n", - (st && st->sb && info.reshape_active)? + (st && st->sb && info->reshape_active)? "shape":"build", e->percent); is_rebuilding = 1; } free_mdstat(ms); - if (st->sb && info.reshape_active) { + if (st->sb && 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(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) + if (info->delta_disks > 0) printf(" Delta Devices : %d, (%d->%d)\n", - info.delta_disks, array.raid_disks - info.delta_disks, array.raid_disks); - if (info.delta_disks < 0) + info->delta_disks, array.raid_disks - info->delta_disks, array.raid_disks); + if (info->delta_disks < 0) printf(" Delta Devices : %d, (%d->%d)\n", - info.delta_disks, array.raid_disks, array.raid_disks + info.delta_disks); - if (info.new_level != array.level) { - char *c = map_num(pers, info.new_level); + info->delta_disks, array.raid_disks, array.raid_disks + info->delta_disks); + if (info->new_level != array.level) { + char *c = map_num(pers, info->new_level); printf(" New Level : %s\n", c?c:"-unknown-"); } - if (info.new_level != array.level || - info.new_layout != array.layout) { - if (info.new_level == 5) { - char *c = map_num(r5layout, info.new_layout); + if (info->new_level != array.level || + info->new_layout != array.layout) { + if (info->new_level == 5) { + char *c = map_num(r5layout, info->new_layout); printf(" New Layout : %s\n", c?c:"-unknown-"); } - if (info.new_level == 10) { + if (info->new_level == 6) { + char *c = map_num(r6layout, info->new_layout); + printf(" New Layout : %s\n", + c?c:"-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); + 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); + if (info->new_chunk != array.chunk_size) + printf(" New Chunksize : %dK\n", info->new_chunk/1024); printf("\n"); } else if (e && e->percent >= 0) printf("\n"); @@ -418,32 +507,8 @@ This is pretty boring else printf(" Number Major Minor RaidDevice\n"); } - disks = malloc(max_disks * sizeof(mdu_disk_info_t)); - for (d=0; d= 0 && disk.raid_disk < array.raid_disks) - disks[disk.raid_disk] = disk; - else if (next < max_disks) - disks[next++] = disk; - } - - avail = calloc(array.raid_disks, 1); for (d= 0; d < max_disks; d++) { char *dv; mdu_disk_info_t disk = disks[d]; @@ -496,11 +561,6 @@ This is pretty boring if (test && d < array.raid_disks && !(disk.state & (1<detail_platform) - err = ss->detail_platform(verbose); + err = ss->detail_platform(verbose, 0); else if (ss) { if (verbose) fprintf(stderr, Name ": %s metadata is platform independent\n", @@ -566,7 +628,7 @@ int Detail_Platform(struct superswitch *ss, int scan, int verbose) fprintf(stderr, Name ": %s metadata is platform independent\n", meta->name ? : "[no name]"); } else - err |= meta->detail_platform(verbose); + err |= meta->detail_platform(verbose, 0); } return err;