]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
imsm: don't skip resync when an invalid ppl header is found
authorArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Thu, 28 Sep 2017 12:41:14 +0000 (14:41 +0200)
committerJes Sorensen <jsorensen@fb.com>
Mon, 2 Oct 2017 20:13:56 +0000 (16:13 -0400)
If validate_ppl_imsm() detects an invalid ppl header it will be
overwritten with a valid, empty ppl header. But if we are assembling an
array after unclean shutdown this will cause the kernel to skip resync
after ppl recovery. We don't want that because if there was an invalid
ppl it's best to assume that the ppl recovery is not enough to make the
array consistent and a full resync should be performed. So when
overwriting the invalid ppl add one ppl_header_entry with a wrong
checksum. This will prevent the kernel from skipping resync after ppl
recovery.

Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
super-intel.c

index 630fb6e1f44f346eae33228f64fa097f2d5c8870..7b2327bac3cf43e8d8211b8432416b5b2de3ad68 100644 (file)
@@ -6080,6 +6080,16 @@ static int write_init_ppl_imsm(struct supertype *st, struct mdinfo *info, int fd
        ppl_hdr = buf;
        memset(ppl_hdr->reserved, 0xff, PPL_HDR_RESERVED);
        ppl_hdr->signature = __cpu_to_le32(super->anchor->orig_family_num);
+
+       if (info->mismatch_cnt) {
+               /*
+                * We are overwriting an invalid ppl. Make one entry with wrong
+                * checksum to prevent the kernel from skipping resync.
+                */
+               ppl_hdr->entries_count = __cpu_to_le32(1);
+               ppl_hdr->entries[0].checksum = ~0;
+       }
+
        ppl_hdr->checksum = __cpu_to_le32(~crc32c_le(~0, buf, PPL_HEADER_SIZE));
 
        if (lseek64(fd, info->ppl_sector * 512, SEEK_SET) < 0) {
@@ -6214,8 +6224,12 @@ out:
                }
        }
 
-       if (ret == 1 && map->map_state == IMSM_T_STATE_UNINITIALIZED)
-               return st->ss->write_init_ppl(st, info, d->fd);
+       if (ret == 1) {
+               if (map->map_state == IMSM_T_STATE_UNINITIALIZED)
+                       ret = st->ss->write_init_ppl(st, info, d->fd);
+               else
+                       info->mismatch_cnt++;
+       }
 
        return ret;
 }