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 <dan.j.williams@intel.com>
This commit is contained in:
Dan Williams 2009-04-12 00:58:28 -07:00
parent 506ffd1e0b
commit 48924014b0
3 changed files with 30 additions and 0 deletions

8
Grow.c
View File

@ -809,12 +809,20 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
/* wait for reshape to pass the critical region */ /* wait for reshape to pass the critical region */
while(1) { while(1) {
unsigned long long comp; unsigned long long comp;
char a[20];
if (sysfs_get_ll(sra, NULL, "sync_completed", &comp)<0) { if (sysfs_get_ll(sra, NULL, "sync_completed", &comp)<0) {
sleep(5); sleep(5);
break; break;
} }
if (comp >= nstripe) if (comp >= nstripe)
break; 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); sleep(1);
} }

View File

@ -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_uevent(struct mdinfo *sra, char *event);
extern int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev, extern int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev,
char *name, unsigned long long *val); 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_safemode(struct mdinfo *sra, unsigned long ms);
extern int sysfs_set_array(struct mdinfo *info, int vers); extern int sysfs_set_array(struct mdinfo *info, int vers);
extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd); extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd);

20
sysfs.c
View File

@ -466,6 +466,26 @@ int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev,
return 0; 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) int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms)
{ {
unsigned long sec; unsigned long sec;