]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Allow --update to add or remove space for a bad block list.
authorNeilBrown <neilb@suse.de>
Wed, 3 Oct 2012 07:07:13 +0000 (17:07 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 3 Oct 2012 07:07:13 +0000 (17:07 +1000)
--update=bbl will add a bad block list to each device.
--update=no-bblk will remove the bad block list providing that it
is empty.

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

index 1fe5583f53f457965c80cc9a23da484022b36171..d963775746f5353a643c366cd9aeb3914fa99f4e 100644 (file)
@@ -1060,6 +1060,8 @@ argument given to this flag can be one of
 .BR byteorder ,
 .BR devicesize ,
 .BR no\-bitmap ,
+.BR bbl ,
+.BR no-\bbl ,
 or
 .BR super\-minor .
 
@@ -1162,6 +1164,18 @@ option can be used when an array has an internal bitmap which is
 corrupt in some way so that assembling the array normally fails.  It
 will cause any internal bitmap to be ignored.
 
+The
+.B bbl
+option will reserve space in each device for a bad block list.  This
+will be 4K in size and positioned near the end of any free space
+between the superblock and the data.
+
+The
+.B no\-bbl
+option will cause any reservation of space for a bad block list to be
+removed.  If the bad block list contains entries, this will fail, as
+removing the list could cause data corruption.
+
 .TP
 .BR \-\-freeze\-reshape
 Option is intended to be used in start-up scripts during initrd boot phase.
@@ -1221,12 +1235,14 @@ When used on an array that has no metadata (i.e. it was built with
 it will be assumed that bitmap-based recovery is enough to make the
 device fully consistent with the array.
 
-When
+When used with v1.x metadata,
 .B \-\-re\-add
 can be accompanied by
-.BR \-\-update=devicesize .
-See the description of this option when used in Assemble mode for an
-explanation of its use.
+.BR \-\-update=devicesize ,
+.BR \-\-update=bbl ", or"
+.BR \-\-update=no\-bbl .
+See the description of these option when used in Assemble mode for an
+explanation of their use.
 
 If the device name given is
 .B missing
diff --git a/mdadm.c b/mdadm.c
index 3ee7ddbaf17be98d7a59253c0ff6f762449c2031..0f7bed91cf67466298c6ecd5adec4b1c3093dff0 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -713,6 +713,10 @@ int main(int argc, char *argv[])
                                continue;
                        if (strcmp(c.update, "no-bitmap")==0)
                                continue;
+                       if (strcmp(c.update, "bbl") == 0)
+                               continue;
+                       if (strcmp(c.update, "no-bbl") == 0)
+                               continue;
                        if (strcmp(c.update, "byteorder")==0) {
                                if (ss) {
                                        pr_err("must not set metadata"
@@ -760,8 +764,10 @@ int main(int argc, char *argv[])
                                exit(2);
                        }
                        c.update = optarg;
-                       if (strcmp(c.update, "devicesize") != 0) {
-                               pr_err("only 'devicesize' can be"
+                       if (strcmp(c.update, "devicesize") != 0 &&
+                           strcmp(c.update, "bbl") != 0 &&
+                           strcmp(c.update, "no-bbl") != 0) {
+                               pr_err("only 'devicesize', 'bbl' and 'no-bbl' can be"
                                        " updated with --re-add\n");
                                exit(2);
                        }
index c0e6cd79328c04fad95905579a7b1eabbf085195..4c29d6e1281bad504d64af911421c1bc2d9f9818 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -850,6 +850,56 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                }
        } else if (strcmp(update, "no-bitmap") == 0) {
                sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
+       } else if (strcmp(update, "bbl") == 0) {
+               /* only possible if there is room after the bitmap, or if
+                * there is no bitmap
+                */
+               unsigned long long sb_offset = __le64_to_cpu(sb->super_offset);
+               unsigned long long data_offset = __le64_to_cpu(sb->data_offset);
+               long bitmap_offset = (long)__le64_to_cpu(sb->bitmap_offset);
+               long bm_sectors = 0;
+               long space;
+
+               if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
+                       struct bitmap_super_s *bsb;
+                       bsb = (struct bitmap_super_s *)(((char*)sb)+MAX_SB_SIZE);
+                       bm_sectors = bitmap_sectors(bsb);
+               }
+
+               if (sb_offset < data_offset) {
+                       /* 1.1 or 1.2.  Put bbl just before data
+                        */
+                       long bb_offset;
+                       space = data_offset - sb_offset;
+                       bb_offset = space - 8;
+                       if (bm_sectors && bitmap_offset > 0)
+                               space -= (bitmap_offset + bm_sectors);
+                       else
+                               space -= 8; /* The superblock */
+                       if (space >= 8) {
+                               sb->bblog_size = __cpu_to_le16(8);
+                               sb->bblog_offset = __cpu_to_le32(bb_offset);
+                       }
+               } else {
+                       /* 1.0 - Put bbl just before super block */
+                       if (bm_sectors && bitmap_offset < 0)
+                               space = -bitmap_offset - bm_sectors;
+                       else
+                               space = sb_offset - data_offset -
+                                       __le64_to_cpu(sb->data_size);
+                       if (space >= 8) {
+                               sb->bblog_size = __cpu_to_le16(8);
+                               sb->bblog_offset = __cpu_to_le32((unsigned)-8);
+                       }
+               }
+       } else if (strcmp(update, "no-bbl") == 0) {
+               if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BAD_BLOCKS))
+                       pr_err("Cannot remove active bbl from %s\n",devname);
+               else {
+                       sb->bblog_size = 0;
+                       sb->bblog_shift = 0;
+                       sb->bblog_offset = 0;
+               }
        } else if (strcmp(update, "homehost") == 0 &&
                   homehost) {
                char *c;