diff -urN -X /home/mkp/bin/dontdiff lsscsi-0.21/lsscsi.8 lsscsi-0.21-dif/lsscsi.8 --- lsscsi-0.21/lsscsi.8 2008-07-09 15:01:44.000000000 -0400 +++ lsscsi-0.21-dif/lsscsi.8 2008-10-17 14:17:53.000000000 -0400 @@ -5,8 +5,8 @@ .B lsscsi [\fI\-\-classic\fR] [\fI\-\-device\fR] [\fI\-\-generic\fR] [\fI\-\-help\fR] [\fI\-\-hosts\fR] [\fI\-\-kname\fR] [\fI\-\-list\fR] [\fI\-\-long\fR] -[\fI\-\-transport\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] -[\fIH:C:T:L\fR] +[\fI\-\-protection\fR] [\fI\-\-transport\fR] [\fI\-\-verbose\fR] +[\fI\-\-version\fR] [\fIH:C:T:L\fR] .SH DESCRIPTION .\" Add any additional description here .PP @@ -75,6 +75,9 @@ outputs SCSI device (host) attributes one per line; preceded by two spaces; in the form "=". .TP +\fB\-p\fR, \fB\-\-protection\fR +Output additional data integrity (protection) information +.TP \fB\-t\fR, \fB\-\-transport\fR Output transport information. This will be a target related information or, if \fI\-\-hosts\fR is given, initiator related information. When used without diff -urN -X /home/mkp/bin/dontdiff lsscsi-0.21/lsscsi.c lsscsi-0.21-dif/lsscsi.c --- lsscsi-0.21/lsscsi.c 2008-07-10 00:14:05.000000000 -0400 +++ lsscsi-0.21-dif/lsscsi.c 2008-10-17 14:24:17.000000000 -0400 @@ -83,6 +83,7 @@ int kname; int transport; int verbose; + int protection; /* data integrity */ }; @@ -139,6 +140,7 @@ {"transport", 0, 0, 't'}, {"verbose", 0, 0, 'v'}, {"version", 0, 0, 'V'}, + {"protection", 0, 0, 'p'}, {0, 0, 0, 0} }; @@ -160,15 +162,17 @@ }; static struct dev_node_list* dev_node_listhead = NULL; -struct sg_item_t { +struct item_t { char name[NAME_LEN_MAX]; int ft; int d_type; }; -static struct sg_item_t non_sg; -static struct sg_item_t aa_sg; -static struct sg_item_t aa_first; +static struct item_t non_sg; +static struct item_t aa_sg; +static struct item_t aa_first; +static struct item_t aa_sd; +static struct item_t aa_block; static char sas_low_phy[NAME_LEN_MAX]; static char sas_hold_end_device[NAME_LEN_MAX]; @@ -231,6 +235,8 @@ fprintf(stderr, " attribute=value per line\n"); fprintf(stderr, " --long|-l additional information " "output\n"); + fprintf(stderr, " --protection|-p show data integrity (protection) " + "information\n"); fprintf(stderr, " --transport|-t transport information for " "target or, if '--hosts'\n" " given, for initiator\n"); @@ -257,6 +263,77 @@ return 1; } +static int +block_scandir_select(const struct dirent * s) +{ + if ((DT_LNK != s->d_type) && + ((DT_DIR != s->d_type) || ('.' == s->d_name[0]))) + return 0; + if (strstr(s->d_name, "block")){ + strncpy(aa_block.name, s->d_name, NAME_LEN_MAX); + aa_block.ft = FT_CHAR; /* dummy */ + aa_block.d_type = s->d_type; + } + return 1; +} + +/* scan for scsi_disk directory in /sys/bus/scsi/devices/ */ +static int +block_scan(const char * dir_name, const struct lsscsi_opt_coll * opts) +{ + char name[NAME_LEN_MAX]; + struct dirent ** namelist; + int num, k; + + num = scandir(dir_name, &namelist, block_scandir_select, NULL); + if (num < 0) { + if (opts->verbose > 0) { + snprintf(name, NAME_LEN_MAX, "scandir: %s", dir_name); + perror(name); + } + return -1; + } + for (k = 0; k < num; ++k) + free(namelist[k]); + free(namelist); + return num; +} + +static int +sd_scandir_select(const struct dirent * s) +{ + if ((DT_LNK != s->d_type) && + ((DT_DIR != s->d_type) || ('.' == s->d_name[0]))) + return 0; + if (strstr(s->d_name, "scsi_disk")){ + strncpy(aa_sd.name, s->d_name, NAME_LEN_MAX); + aa_sd.ft = FT_CHAR; /* dummy */ + aa_sd.d_type = s->d_type; + } + return 1; +} + +static int +sd_scan(const char * dir_name, const struct lsscsi_opt_coll * opts) +{ + char name[NAME_LEN_MAX]; + struct dirent ** namelist; + int num, k; + + num = scandir(dir_name, &namelist, sd_scandir_select, NULL); + if (num < 0) { + if (opts->verbose > 0) { + snprintf(name, NAME_LEN_MAX, "scandir: %s", dir_name); + perror(name); + } + return -1; + } + for (k = 0; k < num; ++k) + free(namelist[k]); + free(namelist); + return num; +} + /* scan for directory entry that is either a symlink or a directory */ static int scan_for_first(const char * dir_name, const struct lsscsi_opt_coll * opts) @@ -1670,7 +1747,7 @@ else if (!get_dev_node(wd, dev_node, typ)) snprintf(dev_node, NAME_MAX, "- "); - printf("%s", dev_node); + printf("%-9s", dev_node); if (opts->dev_maj_min) { if (get_value(wd, "dev", value, NAME_LEN_MAX)) printf("[%s]", value); @@ -1679,7 +1756,7 @@ } } } else - printf("- "); + printf("- "); if (opts->generic) { if (if_directory_ch2generic(buff)) { @@ -1709,6 +1786,60 @@ else printf(" -"); } + + if (opts->protection) { + int kernel_dif_support = 0; + if (sd_scan(buff,opts)) { + if (if_directory_chdir(buff,aa_sd.name)) { + char value[NAME_LEN_MAX]; + char sddir[NAME_LEN_MAX]; + strncpy(sddir,buff,NAME_LEN_MAX); + strcat(sddir,"/"); + strcat(sddir,aa_sd.name); + if (!get_value(sddir, "protection_type", value, + NAME_LEN_MAX)) { + /* kernel < 2.6.27 */ + if (opts->verbose) + printf(" No Data Integrity " + "Support\n"); + } else { + kernel_dif_support = 1; + if (strncmp(value, "0", 1)) + printf(" DIF/Type%1s ",value); + else + printf(" - "); + } + } else { + printf(" - "); + } + } + + if (kernel_dif_support && block_scan(buff,opts)) { + if (if_directory_chdir(buff,aa_block.name)) { + char value[NAME_LEN_MAX]; + char blkdir[NAME_LEN_MAX]; + strncpy(blkdir,buff,NAME_LEN_MAX); + strcat(blkdir,"/"); + strcat(blkdir,aa_block.name); + if (if_directory_chdir(blkdir,"integrity")) { + if (!get_value(".", "format", value, + NAME_LEN_MAX)) { + if (opts->verbose) + printf(" No Data " + "Integrity " + "Support\n"); + } else { + printf(" %-17s",value); + } + } else { + printf(" -"); + } + } + } else { + printf(" -"); + } + } + printf("\n"); if (opts->long_opt > 0) longer_d_entry(buff, devname, opts); @@ -2148,7 +2279,7 @@ while (1) { int option_index = 0; - c = getopt_long(argc, argv, "cdghHklLtvV", long_options, + c = getopt_long(argc, argv, "cdghHklLtvVp", long_options, &option_index); if (c == -1) break; @@ -2184,6 +2315,9 @@ case 'v': ++opts.verbose; break; + case 'p': + ++opts.protection; + break; case 'V': fprintf(stderr, "version: %s\n", version_str); return 0;