]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Bad block log devel-3.3
authorNeilBrown <neilb@suse.de>
Wed, 27 Jul 2011 04:08:10 +0000 (14:08 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 27 Jul 2011 04:08:10 +0000 (14:08 +1000)
super1.c

index 09be351edbfb64875c3d47a298a8f6326b911830..f911593d43c74d05e916e356ab41ebe298fbab31 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -70,7 +70,12 @@ struct mdp_superblock_1 {
        __u8    device_uuid[16]; /* user-space setable, ignored by kernel */
         __u8    devflags;        /* per-device flags.  Only one defined...*/
 #define WriteMostly1    1        /* mask for writemostly flag in above */
-       __u8    pad2[64-57];    /* set to 0 when writing */
+       /* bad block log.  If there are any bad blocks the feature flag is set.
+        * if offset and size are non-zero, that space is reserved and available.
+        */
+       __u8    bblog_shift;    /* shift from sectors to block size for badblocklist */
+       __u16   bblog_size;     /* number of sectors reserved for badblocklist */
+       __u32   bblog_offset;   /* sector offset from superblock to bblog, signed */
 
        /* array state information - 64 bytes */
        __u64   utime;          /* 40 bits second, 24 btes microseconds */
@@ -99,8 +104,9 @@ struct misc_dev_info {
                                           * must be honoured
                                           */
 #define        MD_FEATURE_RESHAPE_ACTIVE       4
+#define        MD_FEATURE_BAD_BLOCKS           8 /* badblock list is not empty */
 
-#define        MD_FEATURE_ALL                  (1|2|4)
+#define        MD_FEATURE_ALL                  (1|2|4|8)
 
 #ifndef offsetof
 #define offsetof(t,f) ((size_t)&(((t*)0)->f))
@@ -278,7 +284,7 @@ static void examine_super1(struct supertype *st, char *homehost)
                printf("Internal Bitmap : %ld sectors from superblock\n",
                       (long)(int32_t)__le32_to_cpu(sb->bitmap_offset));
        }
-       if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) {
+       if (sb->feature_map & __cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE)) {
                printf("  Reshape pos'n : %llu%s\n", (unsigned long long)__le64_to_cpu(sb->reshape_position)/2,
                       human_size(__le64_to_cpu(sb->reshape_position)<<9));
                if (__le32_to_cpu(sb->delta_disks)) {
@@ -322,6 +328,17 @@ static void examine_super1(struct supertype *st, char *homehost)
        atime = __le64_to_cpu(sb->utime) & 0xFFFFFFFFFFULL;
        printf("    Update Time : %.24s\n", ctime(&atime));
 
+       if (sb->bblog_size && sb->bblog_offset) {
+               printf("  Bad Block Log : %d entries available at offset %ld sectors",
+                      __le16_to_cpu(sb->bblog_size)*512/8,
+                      (long)__le32_to_cpu(sb->bblog_offset));
+               if (sb->feature_map &
+                   __cpu_to_le32(MD_FEATURE_BAD_BLOCKS))
+                       printf(" - bad blocks present.");
+               printf("\n");
+       }
+
+
        if (calc_sb_1_csum(sb) == sb->sb_csum)
                printf("       Checksum : %x - correct\n", __le32_to_cpu(sb->sb_csum));
        else
@@ -1105,10 +1122,12 @@ static int write_init_super1(struct supertype *st)
                 * 2: 4K from start of device.
                 * Depending on the array size, we might leave extra space
                 * for a bitmap.
+                * Also leave 4K for bad-block log.
                 */
                array_size = __le64_to_cpu(sb->size);
-               /* work out how much space we left for a bitmap */
-               bm_space = choose_bm_space(array_size);
+               /* work out how much space we left for a bitmap,
+                * Add 8 sectors for bad block log */
+               bm_space = choose_bm_space(array_size) + 8;
 
                switch(st->minor_version) {
                case 0:
@@ -1120,6 +1139,10 @@ static int write_init_super1(struct supertype *st)
                        if (sb_offset < array_size + bm_space)
                                bm_space = sb_offset - array_size;
                        sb->data_size = __cpu_to_le64(sb_offset - bm_space);
+                       if (bm_space >= 8) {
+                               sb->bblog_size = __cpu_to_le16(8);
+                               sb->bblog_offset = __cpu_to_le32((unsigned)-8);
+                       }
                        break;
                case 1:
                        sb->super_offset = __cpu_to_le64(0);
@@ -1134,6 +1157,10 @@ static int write_init_super1(struct supertype *st)
 
                        sb->data_offset = __cpu_to_le64(reserved);
                        sb->data_size = __cpu_to_le64(dsize - reserved);
+                       if (reserved >= 16) {
+                               sb->bblog_size = __cpu_to_le16(8);
+                               sb->bblog_offset = __cpu_to_le32(reserved-8);
+                       }
                        break;
                case 2:
                        sb_offset = 4*2;
@@ -1154,6 +1181,10 @@ static int write_init_super1(struct supertype *st)
 
                        sb->data_offset = __cpu_to_le64(reserved);
                        sb->data_size = __cpu_to_le64(dsize - reserved);
+                       if (reserved >= 16+16) {
+                               sb->bblog_size = __cpu_to_le16(8);
+                               sb->bblog_offset = __cpu_to_le32(reserved-8-8);
+                       }
                        break;
                default:
                        return -EINVAL;