X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=Monitor.c;h=af531294cc53c908ea7a1b88f7a1e0870c5c62bf;hb=8844e291492b82f4bae6129673fb383a309514c0;hp=2f0fe0cc5353db7cf78c93f2ab7d841448b4b35d;hpb=89a10d84cb76492b7d8ea96d0a206b54702bcaff;p=thirdparty%2Fmdadm.git diff --git a/Monitor.c b/Monitor.c index 2f0fe0cc..af531294 100644 --- a/Monitor.c +++ b/Monitor.c @@ -165,7 +165,10 @@ int Monitor(mddev_dev_t devlist, 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); @@ -431,6 +434,8 @@ int Monitor(mddev_dev_t devlist, st->spare_group = NULL; st->expected_spares = -1; statelist = st; + if (test) + alert("TestMessage", st->devname, NULL, mailaddr, mailfrom, alert_cmd, dosyslog); alert("NewArray", st->devname, NULL, mailaddr, mailfrom, alert_cmd, dosyslog); new_found = 1; } @@ -602,10 +607,7 @@ int Wait(char *dev) strerror(errno)); return 2; } - if (major(stb.st_rdev) == MD_MAJOR) - devnum = minor(stb.st_rdev); - else - devnum = -1-(minor(stb.st_rdev)/64); + devnum = stat2devnum(&stb); while(1) { struct mdstat_ent *ms = mdstat_read(1, 0); @@ -616,6 +618,13 @@ int Wait(char *dev) break; if (!e || e->percent < 0) { + if (e && e->metadata_version && + strncmp(e->metadata_version, "external:", 9) == 0) { + if (is_subarray(&e->metadata_version[9])) + ping_monitor(&e->metadata_version[9]); + else + ping_monitor(devnum2devname(devnum)); + } free_mdstat(ms); return rv; } @@ -624,3 +633,107 @@ int Wait(char *dev) mdstat_wait(5); } } + +static char *clean_states[] = { + "clear", "inactive", "readonly", "read-auto", "clean", NULL }; + +int WaitClean(char *dev, int verbose) +{ + int fd; + struct mdinfo *mdi; + int rv = 1; + int devnum; + + fd = open(dev, O_RDONLY); + if (fd < 0) { + 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) { + if (verbose) + fprintf(stderr, Name ": Failed to read sysfs attributes for " + "%s\n", dev); + close(fd); + return 0; + } + + switch(mdi->array.level) { + case LEVEL_LINEAR: + case LEVEL_MULTIPATH: + case 0: + /* safemode delay is irrelevant for these levels */ + rv = 0; + + } + + /* for internal metadata the kernel handles the final clean + * transition, containers can never be dirty + */ + if (!is_subarray(mdi->text_version)) + rv = 0; + + /* safemode disabled ? */ + if (mdi->safe_mode_delay == 0) + rv = 0; + + if (rv) { + int state_fd = sysfs_open(fd2devnum(fd), NULL, "array_state"); + 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; + + /* give mdmon a chance to checkpoint resync */ + sysfs_set_str(mdi, NULL, "sync_action", "idle"); + + 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; + 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 (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 + */ + 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); + close(fd); + + return rv; +} + +