diff options
-rw-r--r-- | mdadm.8.in | 24 | ||||
-rw-r--r-- | mdadm.c | 10 | ||||
-rw-r--r-- | super1.c | 50 |
3 files changed, 78 insertions, 6 deletions
@@ -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 @@ -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); } @@ -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; |