]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
MISC: Add --examine-badblocks option
authorNeilBrown <neilb@suse.de>
Wed, 5 Dec 2012 01:56:31 +0000 (12:56 +1100)
committerNeilBrown <neilb@suse.de>
Wed, 5 Dec 2012 01:56:31 +0000 (12:56 +1100)
This will list the contents of the bad-blocks log, if one is present.

Signed-off-by: NeilBrown <neilb@suse.de>
Examine.c
ReadMe.c
mdadm.8.in
mdadm.c
mdadm.h
super1.c

index a5b3229352603e9d5141406572354334e1a683cb..90b25ec4421bb03a41eeff62eea5d901362df918 100644 (file)
--- a/Examine.c
+++ b/Examine.c
@@ -187,3 +187,39 @@ int Examine(struct mddev_dev *devlist,
        }
        return rv;
 }
+
+int ExamineBadblocks(char *devname, int brief, struct supertype *forcest)
+{
+       int fd = dev_open(devname, O_RDONLY);
+       struct supertype *st = forcest;
+       int err = 1;
+
+       if (fd < 0) {
+               pr_err("cannot open %s: %s\n", devname, strerror(errno));
+               return 1;
+       }
+       if (!st)
+               st = guess_super(fd);
+       if (!st) {
+               if (!brief)
+                       pr_err("No md superblock detected on %s\n", devname);
+               goto out;
+       }
+       if (!st->ss->examine_badblocks) {
+               pr_err("%s metadata does not support badblocks\n", st->ss->name);
+               goto out;
+       }
+       err = st->ss->load_super(st, fd, brief ? NULL : devname);
+       if (err)
+               goto out;
+       err = st->ss->examine_badblocks(st, fd, devname);
+
+out:
+       if (fd >= 0)
+               close(fd);
+       if (st) {
+               st->ss->free_super(st);
+               free(st);
+       }
+       return err;
+}
index 0aa8cbd70be181aae9c36ad67c80bf5386bd381e..4214cb055f7826448cabfaa25cb7d8ea08e7bfce 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -95,6 +95,7 @@ struct option long_options[] = {
     {"update-subarray", 1, 0, UpdateSubarray},
     {"udev-rules", 2, 0, UdevRules},
     {"offroot", 0, 0, OffRootOpt},
+    {"examine-badblocks", 0, 0, ExamineBB},
 
     /* synonyms */
     {"monitor",   0, 0, 'F'},
@@ -251,6 +252,7 @@ char OptionHelp[] =
 "  --detail      -D   : Display details of an array\n"
 "  --examine     -E   : Examine superblock on an array component\n"
 "  --examine-bitmap -X: Display the detail of a bitmap file\n"
+"  --examine-badblocks: Display list of known bad blocks on device\n"
 "  --monitor     -F   : monitor (follow) some arrays\n"
 "  --grow        -G   : resize/ reshape and array\n"
 "  --incremental -I   : add/remove a single device to/from an array as appropriate\n"
@@ -490,6 +492,7 @@ char Help_misc[] =
 "  --detail-platform  : Display hardware/firmware details\n"
 "  --examine     -E   : Examine superblock on an array component\n"
 "  --examine-bitmap -X: Display contents of a bitmap file\n"
+"  --examine-badblocks: Display list of known bad blocks on device\n"
 "  --zero-superblock  : erase the MD superblock from a device.\n"
 "  --run         -R   : start a partially built array\n"
 "  --stop        -S   : deactivate array, releasing all resources\n"
index 535cc392001151bc364aa8adc8722b7fb198b830..c1881cd7a5df92b3626a79d5705f07ff63357774 100644 (file)
@@ -1426,6 +1426,13 @@ device (e.g.
 .BR /dev/md0 )
 does not report the bitmap for that array.
 
+.TP
+.B \-\-examine\-badblocks
+List the bad-blocks recorded for the device, if a bad-blocks list has
+been configured.  Currently only
+.B 1.x
+metadata supports bad-blocks lists.
+
 .TP
 .BR \-R ", " \-\-run
 start a partially assembled array.  If
diff --git a/mdadm.c b/mdadm.c
index 11016e7b911be9fd219a7cb717d92b34ac448a58..26e8ceca164097fe11ea2f3ce29b65c781d5b43a 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -232,6 +232,7 @@ int main(int argc, char *argv[])
                case 'E':
                case 'X':
                case 'Q':
+               case ExamineBB:
                        newmode = MISC;
                        break;
 
@@ -971,6 +972,7 @@ int main(int argc, char *argv[])
                case O(MISC,'R'):
                case O(MISC,'S'):
                case O(MISC,'X'):
+               case O(MISC, ExamineBB):
                case O(MISC,'o'):
                case O(MISC,'w'):
                case O(MISC,'W'):
@@ -1750,6 +1752,8 @@ static int misc_list(struct mddev_dev *devlist,
                        rv |= Query(dv->devname); continue;
                case 'X':
                        rv |= ExamineBitmap(dv->devname, c->brief, ss); continue;
+               case ExamineBB:
+                       rv |= ExamineBadblocks(dv->devname, c->brief, ss); continue;
                case 'W':
                case WaitOpt:
                        rv |= Wait(dv->devname); continue;
diff --git a/mdadm.h b/mdadm.h
index f1352e3704a357ca43d4d40ec8db67ce6b615670..7adf7d94deadd9d39b0d6fd36f050c152535c3cb 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -337,6 +337,7 @@ enum special_options {
        Prefer,
        KillOpt,
        DataOffset,
+       ExamineBB,
 };
 
 enum prefix_standard {
@@ -662,6 +663,7 @@ extern struct superswitch {
        void (*brief_examine_super)(struct supertype *st, int verbose);
        void (*brief_examine_subarrays)(struct supertype *st, int verbose);
        void (*export_examine_super)(struct supertype *st);
+       int (*examine_badblocks)(struct supertype *st, int fd, char *devname);
 
        /* Used to report details of an active array.
         * ->load_super was possibly given a 'component' string.
@@ -1145,6 +1147,7 @@ extern int Create(struct supertype *st, char *mddev,
 extern int Detail(char *dev, struct context *c);
 extern int Detail_Platform(struct superswitch *ss, int scan, int verbose, int export, char *controller_path);
 extern int Query(char *dev);
+extern int ExamineBadblocks(char *devname, int brief, struct supertype *forcest);
 extern int Examine(struct mddev_dev *devlist, struct context *c,
                   struct supertype *forcest);
 extern int Monitor(struct mddev_dev *devlist,
index 5bb1f0143790122dd208c4d2b4bc8db498e13ba9..3236a7e28b301f3ef481b50c6180b8473734133e 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -648,6 +648,59 @@ static void export_detail_super1(struct supertype *st)
                printf("MD_NAME=%.*s\n", len, sb->set_name);
 }
 
+static int examine_badblocks_super1(struct supertype *st, int fd, char *devname)
+{
+       struct mdp_superblock_1 *sb = st->sb;
+       unsigned long long offset;
+       int size;
+       __u64 *bbl, *bbp;
+       int i;
+
+       if  (!sb->bblog_size || __le32_to_cpu(sb->bblog_size) > 100
+            || !sb->bblog_offset){
+               printf("No bad-blocks list configured on %s\n", devname);
+               return 0;
+       }
+       if ((sb->feature_map & __cpu_to_le32(MD_FEATURE_BAD_BLOCKS))
+           == 0) {
+               printf("Bad-blocks list is empty in %s\n", devname);
+               return 0;
+       }
+
+       size = __le32_to_cpu(sb->bblog_size)* 512;
+       posix_memalign((void**)&bbl, 4096, size);
+       offset = __le64_to_cpu(sb->super_offset) +
+               (int)__le32_to_cpu(sb->bblog_offset);
+       offset <<= 9;
+       if (lseek64(fd, offset, 0) < 0) {
+               pr_err("Cannot seek to bad-blocks list\n");
+               return 1;
+       }
+       if (read(fd, bbl, size) != size) {
+               pr_err("Cannot read bad-blocks list\n");
+               return 1;
+       }
+       /* 64bits per entry. 10 bits is block-count, 54 bits is block
+        * offset.  Blocks are sectors unless bblog->shift makes them bigger
+        */
+       bbp = (__u64*)bbl;
+       printf("Bad-blocks on %s:\n", devname);
+       for (i = 0; i < size/8; i++, bbp++) {
+               __u64 bb = __le64_to_cpu(*bbp);
+               int count = bb & 0x3ff;
+               unsigned long long sector = bb >> 10;
+
+               if (bb + 1 == 0)
+                       break;
+
+               sector <<= sb->bblog_shift;
+               count <<= sb->bblog_shift;
+
+               printf("%20llu for %d sectors\n", sector, count);
+       }
+       return 0;
+}
+
 #endif
 
 static int match_home1(struct supertype *st, char *homehost)
@@ -2049,6 +2102,7 @@ struct superswitch super1 = {
        .write_init_super = write_init_super1,
        .validate_geometry = validate_geometry1,
        .add_to_super = add_to_super1,
+       .examine_badblocks = examine_badblocks_super1,
 #endif
        .match_home = match_home1,
        .uuid_from_super = uuid_from_super1,