summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mdadm.8.in24
-rw-r--r--mdadm.c10
-rw-r--r--super1.c50
3 files changed, 78 insertions, 6 deletions
diff --git a/mdadm.8.in b/mdadm.8.in
index 1fe5583f..d9637757 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -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 3ee7ddba..0f7bed91 100644
--- 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);
}
diff --git a/super1.c b/super1.c
index c0e6cd79..4c29d6e1 100644
--- 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;