summaryrefslogtreecommitdiff
path: root/super1.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-10-03 17:07:13 +1000
committerNeilBrown <neilb@suse.de>2012-10-03 17:07:13 +1000
commit688e99a77d04d1581850074ff11491acf5fb57c5 (patch)
treef2e558a67a50592ceb74afaf682b3658ba0c8efe /super1.c
parentbf95d0f38cd35c01a258771bcc9e55b078e0726c (diff)
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>
Diffstat (limited to 'super1.c')
-rw-r--r--super1.c50
1 files changed, 50 insertions, 0 deletions
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;