📄 lsraid.c
字号:
fprintf(stderr, "lsraid: md device [dev %d, %d] %s is offline: Please specify a disk to query\n", MD_MAJOR, array->minor, array->name ? array->name : "(unknown)"); continue; } list_for_each(dpos, &array->disks) { disk = list_entry(dpos, LSRDisk, d_array); if (!disk->major || !disk->sb.md_magic) continue; if (ctxt->flags & LSR_DISK_LONG) dump_disk_long(disk); else dump_disk_short(disk); } } list_for_each(dpos, &ctxt->o_disks) { dent = list_entry(dpos, LSRNamEnt, list); disk = dent->u.disk; if (!disk) continue; if (!disk->major || !disk->sb.md_magic) continue; /* Was it seen in the loop over &ctxt->o_arrays */ if (disk->array) { /* Can you smell the O(n^2)? Please make it better */ exists = 0; list_for_each(apos, &ctxt->o_arrays) { aent = list_entry(apos, LSRNamEnt, list); array = aent->u.array; if (!array) continue; if (disk->array == array) { exists = 1; break; } } if (exists) continue; } if (ctxt->flags & LSR_DISK_LONG) dump_disk_long(disk); else dump_disk_short(disk); }} /* dump_disks() */static void dump_raidtab_array_online(LSRArray *array){ int i, n, s, numdisks, failedstart; LSRDisk *disk; struct list_head *pos; char **diskinfo; char *tmp, *type; if (!array) return; if (!array->name) { /* FIXME: probably should bleat here */ return; } /* * raid_disks slots for good disks * spare_disks slots for good disks * raid_disks slots for failed/missing disks, * * This attempts to follow the order of raidtab rules, rather * than any current order. (eg, spare-disks should come after * raid-disks in the raidtab, even if the first disk in the * online array is a spare-disk). * * A good disk is placed in its raid_disk location in the first * raid_disks slots. A spare disk is placed sequentially in the * spare_disks slots. A failed or missing disk is placed in its * raid_disk location in the last raid_disks slots. If more than * one failed disk exists for a given raid_disk slot, the first is * given only. * * Eg, a raid5 array, where there are three disks in the array plus * one spare. The second disk has failed: * * diskinfo[0] = good disk 0 = disk0 * diskinfo[1] = good disk 1 = NULL * diskinfo[2] = good disk 2 = disk2 * diskinfo[3] = spare disk 0 = disk3 * diskinfo[4] = failed disk 0 = NULL * diskinfo[5] = failed disk 1 = disk1 * diskinfo[6] = failed disk 2 = NULL */ numdisks = array->info.raid_disks + array->info.spare_disks + array->info.raid_disks; failedstart = array->info.raid_disks + array->info.spare_disks; diskinfo = (char **)malloc(sizeof(char *) * numdisks); if (!diskinfo) { fprintf(stderr, "lsraid: Unable to allocate memory while creating raidtab entry for md device\n" "[dev %d, %d] %s: %s\n", MD_MAJOR, array->minor, array->name ? array->name : "(unknown)", strerror(errno)); return; } memset(diskinfo, 0, sizeof(char *) * numdisks); /* diskinfo [i]ndex, type [n]umber, [s]pare number */ i = n = s = 0; list_for_each(pos, &array->disks) { disk = list_entry(pos, LSRDisk, d_array); tmp = (char *)malloc(sizeof(char) * MAX_LINE_LENGTH); if (!tmp) continue; tmp[0] = '\0'; if (disk->info.state & (1<<MD_DISK_ACTIVE)) { type = "raid-disk"; i = n = disk->info.raid_disk; } else if (disk->info.state & (1<<MD_DISK_FAULTY)) { type = "failed-disk"; n = disk->info.raid_disk; i = failedstart + disk->info.raid_disk; } else if (disk->info.state == 0) { type = "spare-disk"; n = s++; i = n + array->info.raid_disks; } else { type = "error"; n = 0; i = numdisks; /* out of bounds */ } sprintf(tmp, "\tdevice\t\t%s\n" "\t%s\t\t%d\n", disk->name ? disk->name : "(unknown)", type, n); if ((i < numdisks) && !diskinfo[i]) diskinfo[i] = tmp; else free(tmp); } /* Scan for missing disks */ for (i = 0; i < array->info.raid_disks; i++) { if (!diskinfo[i] && !diskinfo[failedstart + i]) { tmp = (char *)malloc(sizeof(char) * MAX_LINE_LENGTH); if (!tmp) continue; tmp[0] = '\0'; sprintf(tmp, "\tdevice\t\t/dev/null\n" "\tfailed-disk\t\t%d\n", i); if ((failedstart + i) < numdisks) diskinfo[failedstart + i] = tmp; else free(tmp); } } fprintf(stdout, "# md device [dev %d, %d] %s queried online\n" "raiddev %s\n" "\traid-level\t\t%d\n" "\tnr-raid-disks\t\t%d\n" "\tnr-spare-disks\t\t%d\n" "\tpersistent-superblock\t%d\n" "\tchunk-size\t\t%d\n", MD_MAJOR, array->minor, array->name, array->name, array->info.level, array->info.raid_disks, array->info.spare_disks, array->info.not_persistent ? 0 : 1, /* raid docs are wrong. raidtab chunk size is in K */ array->info.chunk_size / 1024); fprintf(stdout, "\n"); for (i = 0; i < numdisks; i++) if (diskinfo[i]) fprintf(stdout, "%s", diskinfo[i]); fprintf(stdout, "\n");/* out_free: */ for (i = 0; i < numdisks; i++) if (diskinfo[i]) free(diskinfo[i]); free(diskinfo);} /* dump_raidtab_array_online() */static void dump_raidtab_array_offline(LSRArray *array){ int j, i, n, s, numdisks, failedstart; LSRDisk *disk, *a_disk; struct list_head *pos; char **diskinfo; char *tmp, *type, *name; if (!array) return; if (!array->name) { /* FIXME: probably should bleat here */ return; } if (list_empty(&array->disks)) { /* * We really shouldn't be able to get here, as an offline array * is discovered from its disks */ fprintf(stderr, "lsraid: device [dev %d, %d] %s has no disks\n", MD_MAJOR, array->minor, array->name ? array->name : "(Unknown)"); return; } a_disk = list_entry(array->disks.next, LSRDisk, d_array); /* * raid_disks slots for good disks * spare_disks slots for good disks * raid_disks slots for failed/missing disks, * * This attempts to follow the order of raidtab rules, rather * than any current order. (eg, spare-disks should come after * raid-disks in the raidtab, even if the first disk in the * online array is a spare-disk. * * A good disk is placed in its raid_disk location in the first * raid_disks slots. A spare disk is placed sequentially in the * spare_disks slots. A failed or missing disk is placed in its * raid_disk location in the last raid_disks slots. If more than * one failed disk exists for a given raid_disk, only the first is * given. * * Eg, a raid5 array, where there are three disks in the array plus * one spare. The second disk has failed: * * diskinfo[0] = good disk 0 = disk0 * diskinfo[1] = good disk 1 = NULL * diskinfo[2] = good disk 2 = disk2 * diskinfo[3] = spare disk 0 = disk3 * diskinfo[4] = failed disk 0 = NULL * diskinfo[5] = failed disk 1 = disk1 * diskinfo[6] = failed disk 2 = NULL */ numdisks = a_disk->sb.raid_disks + a_disk->sb.spare_disks + a_disk->sb.raid_disks; failedstart = a_disk->sb.raid_disks + a_disk->sb.spare_disks; diskinfo = (char **)malloc(sizeof(char *) * numdisks); if (!diskinfo) { fprintf(stderr, "lsraid: Unable to allocate memory while creating raidtab entry for md device\n" "[dev %d, %d] %s: %s\n", MD_MAJOR, array->minor, array->name ? array->name : "(unknown)", strerror(errno)); return; } memset(diskinfo, 0, sizeof(char *) * numdisks); /* diskinfo [i]ndex, location [n]umber, [s]pare number */ i = n = s = 0; for (j = 0; (j < numdisks) && (j < MD_SB_DISKS); j++) { if (!a_disk->sb.disks[j].major) continue; tmp = (char *)malloc(sizeof(char) * MAX_LINE_LENGTH); if (!tmp) continue; tmp[0] = '\0'; if (a_disk->sb.disks[j].state & (1<<MD_DISK_ACTIVE)) { type = "raid-disk"; i = n = a_disk->sb.disks[j].raid_disk; } else if (a_disk->sb.disks[j].state & (1<<MD_DISK_FAULTY)) { type = "failed-disk"; n = a_disk->sb.disks[j].raid_disk; i = failedstart + a_disk->sb.disks[j].raid_disk;; } else if (a_disk->sb.disks[j].state == 0) { type = "spare-disk"; n = s++; i = n + a_disk->sb.raid_disks; } else { type = "error"; n = 0; i = numdisks; /* out of bounds */ } /* Oh, my, this is inefficient */ name = "(unknown)"; list_for_each(pos, &array->disks) { disk = list_entry(pos, LSRDisk, d_array); if ((disk->major == a_disk->sb.disks[j].major) && (disk->minor == a_disk->sb.disks[j].minor)) { if (disk->name) name = disk->name; break; } } sprintf(tmp, "\tdevice\t\t%s\n" "\t%s\t\t%d\n", name, type, n); if ((i < numdisks) && !diskinfo[i]) diskinfo[i] = tmp; else free(tmp); } /* Scan for missing disks */ for (i = 0; i < a_disk->sb.raid_disks; i++) { if (!diskinfo[i] && !diskinfo[failedstart + i]) { tmp = (char *)malloc(sizeof(char) * MAX_LINE_LENGTH); if (!tmp) continue; tmp[0] = '\0'; sprintf(tmp, "\tdevice\t\t/dev/null\n" "\tfailed-disk\t\t%d\n", i); if ((failedstart + i) < numdisks) diskinfo[failedstart + i] = tmp; else free(tmp); } } fprintf(stdout, "# md device [dev %d, %d] %s queried offline\n" "# Authoritative device is [dev %d, %d] %s\n" "raiddev %s\n" "\traid-level\t\t%d\n" "\tnr-raid-disks\t\t%d\n" "\tnr-spare-disks\t\t%d\n" "\tpersistent-superblock\t%d\n" "\tchunk-size\t\t%d\n", MD_MAJOR, array->minor, array->name, a_disk->major, a_disk->minor, a_disk->name ? a_disk->name : "(unknown)", array->name, a_disk->sb.level, a_disk->sb.raid_disks, a_disk->sb.spare_disks, a_disk->sb.not_persistent ? 0 : 1, /* raid docs are wrong. raidtab chunk size is in K */ a_disk->sb.chunk_size / 1024); fprintf(stdout, "\n"); for (i = 0; i < numdisks; i++) if (diskinfo[i]) fprintf(stdout, "%s", diskinfo[i]); fprintf(stdout, "\n");/* out_free: */ for (i = 0; i < numdisks; i++) if (diskinfo[i]) free(diskinfo[i]); free(diskinfo);} /* dump_raidtab_array_offline() */static void dump_raidtab_array(LSRArray *array){ if (array->info.major_version || array->info.minor_version) dump_raidtab_array_online(array); else dump_raidtab_array_offline(array);} /* dump_raidtab_array() */static void dump_raidtab(LSRContext *ctxt){ LSRArray *array; LSRNamEnt *ent; struct list_head *pos; fprintf(stdout, "# This raidtab was generated by lsraid version %s.\n" "# It was created from a query on the following devices:\n", LSRAID_VERSION); list_for_each(pos, &ctxt->o_arrays) { ent = list_entry(pos, LSRNamEnt, list); fprintf(stdout, "#\t%s\n", ent->name); } list_for_each(pos, &ctxt->o_disks) { ent = list_entry(pos, LSRNamEnt, list); fprintf(stdout, "#\t%s\n", ent->name); } fprintf(stdout, "\n"); /* * Grr, ignores the issue of raid 1+0. The admin should be * bright enough... */ list_for_each(pos, &ctxt->arrays) { array = list_entry(pos, LSRArray, a_list); dump_raidtab_array(array); }} /* dump_raidtab() *//* * The link_arrays(), link_array(), link_array_online(), and * link_array_offline() functions handle matching disks with their * arrays. * * The easy case: The md device is online. * o The array must have array->info. * o The disks must have disk->info. * o Scan ctxt->disks. Every disk that is free, has disk->info, and * matches disk->sb.md_minor with array->minor gets selected. Set * array->uuid* from the first disk and verify they all match. * * The harder case: The md device is offline. * o First pass, scan all disks that are free and have disk->sb.md_minor * matching array->minor. The disk with the most recent * disk->sb.utime is authoritative for the array. Add it to th
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -