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 <neilb@suse.de>
This commit is contained in:
NeilBrown 2012-10-03 17:07:13 +10:00
parent bf95d0f38c
commit 688e99a77d
3 changed files with 78 additions and 6 deletions

View 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

10
mdadm.c
View File

@ -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);
}

View File

@ -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;