summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2015-07-16 11:25:40 +1000
committerNeilBrown <neilb@suse.de>2015-07-16 11:25:40 +1000
commit76cd79d3d19917a3d1b08310b7351f22c16e42ab (patch)
tree6ee0010a6f20419d33daeaeed795136ad5ab338c
parent0832fb09d91515ced206f5459f0015492b4cc10c (diff)
downloadmdadm-76cd79d3d19917a3d1b08310b7351f22c16e42ab.tar.gz
raid6check: get device ordering correct for syndrome calculation.
The order of devices used for the syndrome calculation is not the same as the order of data in the array. The D block immediately after Q is first, then they continue cyclicly in raid-disk order, skipping over the P disk if it is seen. This gets the 'check' right for all layouts other than DDF, which is quite different. I haven't confirmed that this does't break repair. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--raid6check.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/raid6check.c b/raid6check.c
index 86a45b6..a78ac5c 100644
--- a/raid6check.c
+++ b/raid6check.c
@@ -338,7 +338,7 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets,
sighandler_t *sig = xmalloc(3 * sizeof(sighandler_t));
int i, j;
- int diskP, diskQ;
+ int diskP, diskQ, diskD;
int data_disks = raid_disks - 2;
int err = 0;
@@ -377,15 +377,24 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets,
}
}
+ diskP = geo_map(-1, start, raid_disks, level, layout);
+ diskQ = geo_map(-2, start, raid_disks, level, layout);
+ /* The syndrome-order if disks starts immediately after 'Q',
+ * but skips P */
+ diskD = diskQ;
for (i = 0 ; i < data_disks ; i++) {
- int disk = geo_map(i, start, raid_disks, level, layout);
- blocks[i] = stripes[disk];
- block_index_for_slot[disk] = i;
+ diskD = diskD + 1;
+ if (diskD > raid_disks)
+ diskD = 0;
+ if (diskD == diskP)
+ diskD += 1;
+ if (diskD > raid_disks)
+ diskD = 0;
+ blocks[i] = stripes[diskD];
+ block_index_for_slot[diskD] = i;
}
qsyndrome(p, q, (uint8_t**)blocks, data_disks, chunk_size);
- diskP = geo_map(-1, start, raid_disks, level, layout);
- diskQ = geo_map(-2, start, raid_disks, level, layout);
blocks[data_disks] = stripes[diskP];
block_index_for_slot[diskP] = data_disks;
blocks[data_disks+1] = stripes[diskQ];