/* Not really Monitor but ... */ int Wait(char *dev) { struct stat stb; char devnm[32]; int rv = 1; int frozen_remaining = 3; if (stat(dev, &stb) != 0) { pr_err("Cannot find %s: %s\n", dev, strerror(errno)); return 2; } strcpy(devnm, stat2devnm(&stb)); while(1) { struct mdstat_ent *ms = mdstat_read(1, 0); struct mdstat_ent *e; for (e=ms ; e; e=e->next) if (strcmp(e->devnm, devnm) == 0) break; if (e && e->percent == RESYNC_NONE) { /* We could be in the brief pause before something * starts. /proc/mdstat doesn't show that, but * sync_action does. */ struct mdinfo mdi; char buf[21]; sysfs_init(&mdi, -1, devnm); if (sysfs_get_str(&mdi, NULL, "sync_action", buf, 20) > 0 && strcmp(buf,"idle\n") != 0) { e->percent = RESYNC_UNKNOWN; if (strcmp(buf, "frozen\n") == 0) { if (frozen_remaining == 0) e->percent = RESYNC_NONE; else frozen_remaining -= 1; } } } if (!e || e->percent == RESYNC_NONE) { 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(devnm); } free_mdstat(ms); return rv; } free_mdstat(ms); rv = 0; mdstat_wait(5); } }
int main(int argc, char *argv[]) { char *container_name = NULL; char *devnm = NULL; int status = 0; int opt; int all = 0; int takeover = 0; int dofork = 1; static struct option options[] = { {"all", 0, NULL, 'a'}, {"takeover", 0, NULL, 't'}, {"help", 0, NULL, 'h'}, {"offroot", 0, NULL, OffRootOpt}, {"foreground", 0, NULL, 'F'}, {NULL, 0, NULL, 0} }; if (in_initrd()) { /* * set first char of argv[0] to @. This is used by * systemd to signal that the task was launched from * initrd/initramfs and should be preserved during shutdown */ argv[0][0] = '@'; } while ((opt = getopt_long(argc, argv, "thaF", options, NULL)) != -1) { switch (opt) { case 'a': container_name = argv[optind-1]; all = 1; break; case 't': takeover = 1; break; case 'F': dofork = 0; break; case OffRootOpt: argv[0][0] = '@'; break; case 'h': default: usage(); break; } } if (all == 0 && container_name == NULL) { if (argv[optind]) container_name = argv[optind]; } if (container_name == NULL) usage(); if (argc - optind > 1) usage(); if (strcmp(container_name, "/proc/mdstat") == 0) all = 1; if (all) { struct mdstat_ent *mdstat, *e; int container_len = strlen(container_name); /* launch an mdmon instance for each container found */ mdstat = mdstat_read(0, 0); for (e = mdstat; e; e = e->next) { if (e->metadata_version && strncmp(e->metadata_version, "external:", 9) == 0 && !is_subarray(&e->metadata_version[9])) { /* update cmdline so this mdmon instance can be * distinguished from others in a call to ps(1) */ if (strlen(e->devnm) <= (unsigned)container_len) { memset(container_name, 0, container_len); sprintf(container_name, "%s", e->devnm); } status |= mdmon(e->devnm, 1, takeover); } } free_mdstat(mdstat); return status; } else if (strncmp(container_name, "md", 2) == 0) { int id = devnm2devid(container_name); if (id) devnm = container_name; } else { struct stat st; if (stat(container_name, &st) == 0) devnm = xstrdup(stat2devnm(&st)); } if (!devnm) { pr_err("%s is not a valid md device name\n", container_name); exit(1); } return mdmon(devnm, dofork && do_fork(), takeover); }