diff --git a/Grow.c b/Grow.c index 1d0c7ce..0e20b24 100644 --- a/Grow.c +++ b/Grow.c @@ -626,13 +626,9 @@ static void wait_reshape(struct mdinfo *sra) if (fd < 0) return; - while (sysfs_fd_get_str(fd, action, 20) > 0 && - strncmp(action, "reshape", 7) == 0) { - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - select(fd+1, NULL, NULL, &rfds, NULL); - } + while (sysfs_fd_get_str(fd, action, 20) > 0 && + strncmp(action, "reshape", 7) == 0) + sysfs_wait(fd, NULL); close(fd); } @@ -3777,7 +3773,6 @@ int progress_reshape(struct mdinfo *info, struct reshape *reshape, * waiting forever on a dead array */ char action[20]; - fd_set rfds; if (sysfs_get_str(info, NULL, "sync_action", action, 20) <= 0 || strncmp(action, "reshape", 7) != 0) @@ -3793,9 +3788,7 @@ int progress_reshape(struct mdinfo *info, struct reshape *reshape, && info->reshape_progress < (info->component_size * reshape->after.data_disks)) break; - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - select(fd+1, NULL, NULL, &rfds, NULL); + sysfs_wait(fd, NULL); if (sysfs_fd_get_ll(fd, &completed) < 0) goto check_progress; } @@ -3840,15 +3833,10 @@ check_progress: /* The abort might only be temporary. Wait up to 10 * seconds for fd to contain a valid number again. */ - struct timeval tv; + int wait = 10000; int rv = -2; - tv.tv_sec = 10; - tv.tv_usec = 0; - while (fd >= 0 && rv < 0 && tv.tv_sec > 0) { - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - if (select(fd+1, NULL, NULL, &rfds, &tv) != 1) + while (fd >= 0 && rv < 0 && wait > 0) { + if (sysfs_wait(fd, &wait) != 1) break; switch (sysfs_fd_get_ll(fd, &completed)) { case 0: @@ -3856,7 +3844,7 @@ check_progress: rv = 1; break; case -2: /* read error - abort */ - tv.tv_sec = 0; + wait = 0; break; } } diff --git a/Monitor.c b/Monitor.c index 86df18c..c1a5d60 100644 --- a/Monitor.c +++ b/Monitor.c @@ -1050,17 +1050,12 @@ int WaitClean(char *dev, int sock, int verbose) if (rv) { int state_fd = sysfs_open(fd2devnm(fd), NULL, "array_state"); char buf[20]; - fd_set fds; - struct timeval tm; + int delay = 5000; /* minimize the safe_mode_delay and prepare to wait up to 5s * for writes to quiesce */ sysfs_set_safemode(mdi, 1); - tm.tv_sec = 5; - tm.tv_usec = 0; - - FD_ZERO(&fds); /* wait for array_state to be clean */ while (1) { @@ -1069,8 +1064,7 @@ int WaitClean(char *dev, int sock, int verbose) break; if (sysfs_match_word(buf, clean_states) <= 4) break; - FD_SET(state_fd, &fds); - rv = select(state_fd + 1, NULL, NULL, &fds, &tm); + rv = sysfs_wait(state_fd, &delay); if (rv < 0 && errno != EINTR) break; lseek(state_fd, 0, SEEK_SET); diff --git a/mdadm.h b/mdadm.h index 2633b89..13ea26a 100644 --- a/mdadm.h +++ b/mdadm.h @@ -549,6 +549,7 @@ extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume); extern int sysfs_disk_to_scsi_id(int fd, __u32 *id); extern int sysfs_unique_holder(char *devnm, long rdev); extern int sysfs_freeze_array(struct mdinfo *sra); +extern int sysfs_wait(int fd, int *msec); extern int load_sys(char *path, char *buf); extern int reshape_prepare_fdlist(char *devname, struct mdinfo *sra, diff --git a/super-intel.c b/super-intel.c index 7a4260c..27c725f 100644 --- a/super-intel.c +++ b/super-intel.c @@ -10163,10 +10163,7 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) do { char action[20]; - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - select(fd+1, &rfds, NULL, NULL, NULL); + sysfs_wait(fd, NULL); if (sysfs_get_str(sra, NULL, "sync_action", action, 20) > 0 && strncmp(action, "reshape", 7) != 0) diff --git a/sysfs.c b/sysfs.c index cde8f19..b7d41a5 100644 --- a/sysfs.c +++ b/sysfs.c @@ -844,3 +844,32 @@ int sysfs_freeze_array(struct mdinfo *sra) return 0; return 1; } + +int sysfs_wait(int fd, int *msec) +{ + /* Wait up to '*msec' for fd to have an exception condition. + * if msec == NULL, wait indefinitely. + */ + fd_set fds; + int n; + FD_ZERO(&fds); + FD_SET(fd, &fds); + if (msec == NULL) + n = select(fd+1, NULL, NULL, &fds, NULL); + else if (*msec < 0) + n = 0; + else { + struct timeval start, end, tv; + gettimeofday(&start, NULL); + if (*msec < 1000) + tv.tv_usec = (*msec)*1000; + else + tv.tv_sec = (*msec)/1000; + n = select(fd+1, NULL, NULL, &fds, &tv); + gettimeofday(&end, NULL); + end.tv_sec -= start.tv_sec; + *msec -= (end.tv_sec * 1000 + end.tv_usec/1000 + - start.tv_usec/100) + 1; + } + return n; +}