commit b0a1b4203e231ca2b6ec3ab5a88efda868349631 from: Benjamin Stürz date: Mon May 15 14:43:34 2023 UTC Show RAID disks commit - 0c422a5b7d0b4f4ddf3f70089c95d9ae2d2baf06 commit + b0a1b4203e231ca2b6ec3ab5a88efda868349631 blob - faadd5ac7957d4c3cc3487fa9e3610d40587a282 blob + 4eb647aabbd55b501e8ff215a50ac233388b669c --- ChangeLog.md +++ ChangeLog.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http ## [1.2] - TBD ### Added - Accept "disk" arguments. +- Show RAID disks - Options: - `-a` print all fields - `-i` don't print fancy unicode characters blob - 4141794cedcce65dbb0f62e3ccbddd8735e1e870 blob + 9c892b22b21731c19c377f1438944009c056a939 --- lsblk.c +++ lsblk.c @@ -17,6 +17,7 @@ #define _BSD_SOURCE 1 #define DKTYPENAMES #include +#include #include #include #include @@ -134,6 +135,8 @@ enum { OPT_NOUNICODE = 0x02, }; +struct my_diskinfo; + struct my_partinfo { char letter; uint64_t size; @@ -141,6 +144,7 @@ struct my_partinfo { uint64_t free; const char *fstype; const char *mount; + const struct my_diskinfo *sub; }; struct my_diskinfo { @@ -149,15 +153,15 @@ struct my_diskinfo { char name[4]; uint64_t size; uint64_t used; - uint8_t num_parts; u_char duid[8]; + uint8_t num_parts; struct my_partinfo parts[MAXPARTITIONS]; }; static void print_header (int fields) { if (fields & FIELD_NAME) - printf ("%-6s ", "NAME"); + printf ("%-7s ", "NAME"); if (fields & FIELD_DUID) printf ("%-18s ", "DUID"); @@ -187,6 +191,7 @@ static void print_duid (const u_char *duid) } } +static void print_disk (const struct my_diskinfo *disk, int fields, int options, bool sub); static void print_part ( const struct my_diskinfo *disk, const struct my_partinfo *part, @@ -196,7 +201,7 @@ static void print_part ( ) { if (fields & FIELD_NAME) { const char *prefix = (options & OPT_NOUNICODE) ? " " : (last ? "└─" : "├─"); - printf ("%s%s%c ", prefix, disk->name, part->letter); + printf ("%s%s%c ", prefix, disk->name, part->letter); } if (fields & FIELD_DUID) { @@ -230,12 +235,20 @@ static void print_part ( printf ("%s ", part->mount); putchar ('\n'); + + if (part->sub) { + printf ("│ └─"); + print_disk (part->sub, fields, options, true); + } } -static void print_disk (const struct my_diskinfo *disk, int fields, int options) +static void print_disk (const struct my_diskinfo *disk, int fields, int options, bool sub) { - if (fields & FIELD_NAME) - printf ("%s ", disk->name); + if (fields & FIELD_NAME) { + printf ("%s ", disk->name); + if (!sub) + printf (" "); + } if (fields & FIELD_DUID) { print_duid (disk->duid); @@ -260,8 +273,10 @@ static void print_disk (const struct my_diskinfo *disk putchar ('\n'); - for (uint8_t i = 0; i < disk->num_parts; ++i) - print_part (disk, &disk->parts[i], fields, options, i == (disk->num_parts - 1)); + if (!sub) { + for (uint8_t i = 0; i < disk->num_parts; ++i) + print_part (disk, &disk->parts[i], fields, options, i == (disk->num_parts - 1)); + } } static const struct statfs *find_mount (const char *dev) @@ -348,6 +363,66 @@ static struct my_diskinfo read_disk (const char *name) return disk; } +static void read_raid ( + const struct my_diskinfo *disk, + struct my_diskinfo *disks, + size_t num_disks +) { + struct bioc_inq bi; + int fd; + + fd = opendev (disk->name, O_RDONLY, OPENDEV_PART | OPENDEV_BLCK, NULL); + if (fd < 0) { + warn ("read_raid(): opendev(%s)", disk->name); + return; + } + + bzero (&bi, sizeof bi); + + if (ioctl (fd, BIOCINQ, &bi) == -1) + goto ret; + + for (int i = 0; i < bi.bi_nodisk; ++i) { + struct bioc_disk bd; + const char *vendor; + size_t len_vendor; + char letter; + + bzero (&bd, sizeof bd); + memcpy (&bd.bd_bio, &bi.bi_bio, sizeof bi.bi_bio); + bd.bd_volid = 0; + bd.bd_diskid = i; + + if (ioctl (fd, BIOCDISK, &bd) == -1) { + warn ("read_raid(%s): BIOCDISK(%d)", disk->name, i); + continue; + } + + vendor = bd.bd_vendor; + len_vendor = strlen (vendor); + if (len_vendor != 4) { + warnx ("read_raid(%s): unexpected vendor string: '%.32s'", disk->name, vendor); + continue; + } + letter = vendor[len_vendor - 1]; + + for (size_t j = 0; j < num_disks; ++j) { + if (!memcmp (vendor, disks[j].name, 3)) { + for (size_t k = 0; k < disks[j].num_parts; ++k) { + if (letter == disks[j].parts[k].letter) { + disks[j].parts[k].sub = disk; + goto found; + } + } + } + } + found:; + } + +ret: + close (fd); +} + static int usage (void) { fputs ("Usage: lsblk [-ainUuV] [disk...]\n", stderr); @@ -430,11 +505,15 @@ int main (int argc, char *argv[]) free (names); + for (size_t i = 0; i < num_disks; ++i) { + read_raid (&disks[i], disks, num_disks); + } + if (!(options & OPT_NOHEADER)) print_header (fields); for (size_t i = 0; i < num_disks; ++i) { - print_disk (&disks[i], fields, options); + print_disk (&disks[i], fields, options, false); } return 0;