--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>
.BR byteorder ,
.BR devicesize ,
.BR no\-bitmap ,
+.BR bbl ,
+.BR no-\bbl ,
or
.BR super\-minor .
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.
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
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"
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);
}
}
} 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;