From 688e99a77d04d1581850074ff11491acf5fb57c5 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 3 Oct 2012 17:07:13 +1000 Subject: [PATCH] Allow --update to add or remove space for a bad block list. --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 --- mdadm.8.in | 24 ++++++++++++++++++++---- mdadm.c | 10 ++++++++-- super1.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 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; -- 2.39.2