summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-11-06 13:56:05 +1100
committerNeilBrown <neilb@suse.de>2009-11-06 13:56:05 +1100
commitd44453876eefa0aa4c6d2dc224cde3f501b051ff (patch)
tree5410ee26bfc0bf5b97719a9ef3155f21aafa980d
parent92dcdf7c01f142aec85deff9f002e59951952978 (diff)
downloadmdadm-d44453876eefa0aa4c6d2dc224cde3f501b051ff.tar.gz
Grow: handle array going degraded during reshape.
If an array goes degraded during reshape, we need to adjust the devices we read from so as not to back up stale data. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--Grow.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/Grow.c b/Grow.c
index deff0e0..31007ae 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1205,7 +1205,7 @@ int grow_backup(struct mdinfo *sra,
int *sources, unsigned long long *offsets,
int disks, int chunk, int level, int layout,
int dests, int *destfd, unsigned long long *destoffsets,
- int part,
+ int part, int *degraded,
char *buf)
{
/* Backup 'blocks' sectors at 'offset' on each device of the array,
@@ -1217,12 +1217,38 @@ int grow_backup(struct mdinfo *sra,
int odata = disks;
int rv = 0;
int i;
+ unsigned long long new_degraded;
//printf("offset %llu\n", offset);
if (level >= 4)
odata--;
if (level == 6)
odata--;
sysfs_set_num(sra, NULL, "suspend_hi", (offset + stripes * chunk/512) * odata);
+ /* Check that array hasn't become degraded, else we might backup the wrong data */
+ sysfs_get_ll(sra, NULL, "degraded", &new_degraded);
+ if (new_degraded != *degraded) {
+ /* check each device to ensure it is still working */
+ struct mdinfo *sd;
+ for (sd = sra->devs ; sd ; sd = sd->next) {
+ if (sd->disk.state & (1<<MD_DISK_FAULTY))
+ continue;
+ if (sd->disk.state & (1<<MD_DISK_SYNC)) {
+ char sbuf[20];
+ if (sysfs_get_str(sra, sd, "state", sbuf, 20) < 0 ||
+ strstr(sbuf, "faulty") ||
+ strstr(sbuf, "in_sync") == NULL) {
+ /* this device is dead */
+ sd->disk.state = (1<<MD_DISK_FAULTY);
+ if (sd->disk.raid_disk >= 0 &&
+ sources[sd->disk.raid_disk] >= 0) {
+ close(sources[sd->disk.raid_disk]);
+ sources[sd->disk.raid_disk] = -1;
+ }
+ }
+ }
+ }
+ *degraded = new_degraded;
+ }
if (part) {
bsb.arraystart2 = __cpu_to_le64(offset * odata);
bsb.length2 = __cpu_to_le64(stripes * chunk/512 * odata);
@@ -1422,6 +1448,7 @@ static int child_grow(int afd, struct mdinfo *sra, unsigned long stripes,
int dests, int *destfd, unsigned long long *destoffsets)
{
char *buf;
+ int degraded = 0;
posix_memalign((void**)&buf, 4096, disks * chunk);
sysfs_set_num(sra, NULL, "suspend_hi", 0);
@@ -1429,7 +1456,7 @@ static int child_grow(int afd, struct mdinfo *sra, unsigned long stripes,
grow_backup(sra, 0, stripes,
fds, offsets, disks, chunk, level, layout,
dests, destfd, destoffsets,
- 0, buf);
+ 0, &degraded, buf);
validate(afd, destfd[0], destoffsets[0]);
wait_backup(sra, 0, stripes * chunk / 512, stripes * chunk / 512,
dests, destfd, destoffsets,
@@ -1449,6 +1476,7 @@ static int child_shrink(int afd, struct mdinfo *sra, unsigned long stripes,
char *buf;
unsigned long long start;
int rv;
+ int degraded = 0;
posix_memalign((void**)&buf, 4096, disks * chunk);
start = sra->component_size - stripes * chunk/512;
@@ -1464,7 +1492,7 @@ static int child_shrink(int afd, struct mdinfo *sra, unsigned long stripes,
fds, offsets,
disks, chunk, level, layout,
dests, destfd, destoffsets,
- 0, buf);
+ 0, &degraded, buf);
validate(afd, destfd[0], destoffsets[0]);
wait_backup(sra, start, stripes*chunk/512, 0,
dests, destfd, destoffsets, 0);
@@ -1486,6 +1514,7 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
int part;
char *buf;
unsigned long long speed;
+ int degraded = 0;
posix_memalign((void**)&buf, 4096, disks * chunk);
@@ -1500,12 +1529,12 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
fds, offsets,
disks, chunk, level, layout,
dests, destfd, destoffsets,
- 0, buf);
+ 0, &degraded, buf);
grow_backup(sra, (start + stripes) * chunk/512, stripes,
fds, offsets,
disks, chunk, level, layout,
dests, destfd, destoffsets,
- 1, buf);
+ 1, &degraded, buf);
validate(afd, destfd[0], destoffsets[0]);
part = 0;
start += stripes * 2; /* where to read next */
@@ -1524,7 +1553,7 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long stripes,
fds, offsets,
disks, chunk, level, layout,
dests, destfd, destoffsets,
- part, buf);
+ part, &degraded, buf);
start += stripes;
part = 1 - part;
validate(afd, destfd[0], destoffsets[0]);