From 48924014b02dd0e8046f58a4c6c9a2903a9b1dbd Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 12 Apr 2009 00:58:28 -0700 Subject: [PATCH] Grow: fix hang when reshape completes too fast For short reshapes the kernel may be done before mdadm can check that progress has passed the critical section. Signed-off-by: Dan Williams --- Grow.c | 8 ++++++++ mdadm.h | 2 ++ sysfs.c | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/Grow.c b/Grow.c index 14e48f5..7083c18 100644 --- a/Grow.c +++ b/Grow.c @@ -809,12 +809,20 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, /* wait for reshape to pass the critical region */ while(1) { unsigned long long comp; + char a[20]; + if (sysfs_get_ll(sra, NULL, "sync_completed", &comp)<0) { sleep(5); break; } if (comp >= nstripe) break; + + /* perhaps the entire reshape has completed */ + if (comp == 0 && + sysfs_get_str(sra, NULL, "sync_action", a, sizeof(a)) == 0 && + strncmp(a, "idle", 4) == 0) + break; sleep(1); } diff --git a/mdadm.h b/mdadm.h index c33ec24..82c7ded 100644 --- a/mdadm.h +++ b/mdadm.h @@ -372,6 +372,8 @@ extern int sysfs_set_num(struct mdinfo *sra, struct mdinfo *dev, extern int sysfs_uevent(struct mdinfo *sra, char *event); extern int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev, char *name, unsigned long long *val); +extern int sysfs_get_str(struct mdinfo *sra, struct mdinfo *dev, + char *name, char *buf, int buf_len); extern int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms); extern int sysfs_set_array(struct mdinfo *info, int vers); extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd); diff --git a/sysfs.c b/sysfs.c index 48d1f54..31c92f7 100644 --- a/sysfs.c +++ b/sysfs.c @@ -466,6 +466,26 @@ int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev, return 0; } +int sysfs_get_str(struct mdinfo *sra, struct mdinfo *dev, + char *name, char *buf, int buf_len) +{ + char fname[50]; + int n; + int fd; + + sprintf(fname, "/sys/block/%s/md/%s/%s", + sra->sys_name, dev?dev->sys_name:"", name); + fd = open(fname, O_RDONLY); + if (fd < 0) + return -1; + n = read(fd, buf, buf_len); + close(fd); + if (n <= 0) + return -1; + buf[n] = 0; + return 0; +} + int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms) { unsigned long sec;