if (devlist == NULL) {
mddev_ident_t mdlist = conf_get_ident(NULL);
for (; mdlist; mdlist=mdlist->next) {
- struct state *st = malloc(sizeof *st);
+ struct state *st;
+ if (mdlist->devname == NULL)
+ continue;
+ st = malloc(sizeof *st);
if (st == NULL)
continue;
st->devname = strdup(mdlist->devname);
static char *clean_states[] = {
"clear", "inactive", "readonly", "read-auto", "clean", NULL };
-int WaitClean(char *dev)
+int WaitClean(char *dev, int verbose)
{
int fd;
struct mdinfo *mdi;
fd = open(dev, O_RDONLY);
if (fd < 0) {
- fprintf(stderr, Name ": Couldn't open %s: %s\n", dev, strerror(errno));
+ if (verbose)
+ fprintf(stderr, Name ": Couldn't open %s: %s\n", dev, strerror(errno));
return 1;
}
devnum = fd2devnum(fd);
mdi = sysfs_read(fd, devnum, GET_VERSION|GET_LEVEL|GET_SAFEMODE);
if (!mdi) {
- fprintf(stderr, Name ": Failed to read sysfs attributes for "
- "%s\n", dev);
+ if (verbose)
+ fprintf(stderr, Name ": Failed to read sysfs attributes for "
+ "%s\n", dev);
close(fd);
return 0;
}
if (rv) {
int state_fd = sysfs_open(fd2devnum(fd), NULL, "array_state");
- unsigned long secs;
char buf[20];
+ fd_set fds;
+ struct timeval tm;
+
+ /* 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;
- secs = mdi->safe_mode_delay / 1000;
- if (mdi->safe_mode_delay - secs * 1000)
- secs++;
- secs *= 2;
+ /* give mdmon a chance to checkpoint resync */
+ sysfs_set_str(mdi, NULL, "sync_action", "idle");
- for (; secs; secs--) {
+ FD_ZERO(&fds);
+
+ /* wait for array_state to be clean */
+ while (1) {
rv = read(state_fd, buf, sizeof(buf));
if (rv < 0)
break;
if (sysfs_match_word(buf, clean_states) <= 4)
break;
- sleep(1);
+ FD_SET(state_fd, &fds);
+ rv = select(state_fd + 1, &fds, NULL, NULL, &tm);
+ if (rv < 0 && errno != EINTR)
+ break;
lseek(state_fd, 0, SEEK_SET);
}
if (rv < 0)
rv = 1;
- else if (secs) {
+ else if (ping_monitor(mdi->text_version) == 0) {
/* we need to ping to close the window between array
* state transitioning to clean and the metadata being
* marked clean
*/
- if (ping_monitor(mdi->text_version) == 0)
- rv = 0;
- }
- if (rv)
+ rv = 0;
+ } else
+ rv = 1;
+ if (rv && verbose)
fprintf(stderr, Name ": Error waiting for %s to be clean\n",
dev);
+ /* restore the original safe_mode_delay */
+ sysfs_set_safemode(mdi, mdi->safe_mode_delay);
close(state_fd);
}
- sysfs_free(mdi);
+ sysfs_free(mdi);
close(fd);
return rv;