struct state {
char *devname;
char devnm[32]; /* to sync with mdstat info */
- long utime;
+ unsigned int utime;
int err;
char *spare_group;
int active, working, failed, spare, raid;
int from_config;
+ int from_auto;
int expected_spares;
int devstate[MAX_DISKS];
dev_t devid[MAX_DISKS];
return rv;
}
- if (share)
+ if (share)
if (check_one_sharer(c->scan))
return 1;
}
}
-
while (! finished) {
int new_found = 0;
- struct state *st;
+ struct state *st, **stp;
int anydegraded = 0;
if (mdstat)
free_mdstat(mdstat);
mdstat = mdstat_read(oneshot?0:1, 0);
+ if (!mdstat)
+ mdstat_close();
for (st=statelist; st; st=st->next)
if (check_array(st, mdstat, c->test, &info,
increments, c->prefer))
anydegraded = 1;
-
+
/* now check if there are any new devices found in mdstat */
if (c->scan)
new_found = add_new_arrays(mdstat, &statelist, c->test,
mdstat_wait(c->delay);
}
c->test = 0;
+
+ for (stp = &statelist; (st = *stp) != NULL; ) {
+ if (st->from_auto && st->err > 5) {
+ *stp = st->next;
+ free(st->devname);
+ free(st->spare_group);
+ free(st);
+ } else
+ stp = &st->next;
+ }
}
for (st2 = statelist; st2; st2 = statelist) {
statelist = st2->next;
rv = stat(dir, &buf);
if (rv != -1) {
if (scan) {
- pr_err("Only one "
- "autorebuild process allowed"
- " in scan mode, aborting\n");
+ pr_err("Only one autorebuild process allowed in scan mode, aborting\n");
fclose(fp);
return 1;
} else {
- pr_err("Warning: One"
- " autorebuild process already"
- " running.\n");
+ pr_err("Warning: One autorebuild process already running.\n");
}
}
fclose(fp);
if (scan) {
if (mkdir(MDMON_DIR, S_IRWXU) < 0 &&
errno != EEXIST) {
- pr_err("Can't create "
- "autorebuild.pid file\n");
+ pr_err("Can't create autorebuild.pid file\n");
} else {
fp = fopen(path, "w");
if (!fp)
- pr_err("Cannot create"
- " autorebuild.pid"
- "file\n");
+ pr_err("Cannot create autorebuild.pidfile\n");
else {
pid = getpid();
fprintf(fp, "%d\n", pid);
if (info->mailfrom)
fprintf(mp, "From: %s\n", info->mailfrom);
else
- fprintf(mp, "From: " Name " monitoring <root>\n");
+ fprintf(mp, "From: %s monitoring <root>\n", Name);
fprintf(mp, "To: %s\n", info->mailaddr);
fprintf(mp, "Subject: %s event on %s:%s\n\n",
event, dev, hname);
fprintf(mp,
- "This is an automatically generated"
- " mail message from " Name "\n");
+ "This is an automatically generated mail message from %s\n", Name);
fprintf(mp, "running on %s\n\n", hname);
fprintf(mp,
- "A %s event had been detected on"
- " md device %s.\n\n", event, dev);
+ "A %s event had been detected on md device %s.\n\n", event, dev);
if (disc && disc[0] != ' ')
fprintf(mp,
- "It could be related to"
- " component device %s.\n\n", disc);
+ "It could be related to component device %s.\n\n", disc);
if (disc && disc[0] == ' ')
fprintf(mp, "Extra information:%s.\n\n", disc);
char buf[8192];
int n;
fprintf(mp,
- "\nP.S. The /proc/mdstat file"
- " currently contains the following:\n\n");
+ "\nP.S. The /proc/mdstat file currently contains the following:\n\n");
while ( (n=fread(buf, 1, sizeof(buf), mdstat)) > 0)
n=fwrite(buf, 1, n, mp);
fclose(mdstat);
else
priority = LOG_INFO;
- if (disc)
+ if (disc && disc[0] != ' ')
+ syslog(priority,
+ "%s event detected on md device %s, component device %s", event, dev, disc);
+ else if (disc)
syslog(priority,
- "%s event detected on md device %s,"
- " component device %s", event, dev, disc);
+ "%s event detected on md device %s: %s",
+ event, dev, disc);
else
syslog(priority,
"%s event detected on md device %s",
mdu_array_info_t array;
struct mdstat_ent *mse = NULL, *mse2;
char *dev = st->devname;
- int fd;
+ int fd = -1;
int i;
int remaining_disks;
int last_disk;
if (test)
alert("TestMessage", dev, NULL, ainfo);
+ if (st->devnm[0])
+ fd = open("/sys/block", O_RDONLY|O_DIRECTORY);
+ if (fd >= 0) {
+ /* Don't open the device unless it is present and
+ * active in sysfs.
+ */
+ char buf[10];
+ close(fd);
+ fd = sysfs_open(st->devnm, NULL, "array_state");
+ if (fd < 0 ||
+ read(fd, buf, 10) < 5 ||
+ strncmp(buf,"clear",5) == 0 ||
+ strncmp(buf,"inact",5) == 0) {
+ if (fd >= 0)
+ close(fd);
+ fd = sysfs_open(st->devnm, NULL, "level");
+ if (fd < 0 || read(fd, buf, 10) != 0) {
+ if (fd >= 0)
+ close(fd);
+ if (!st->err)
+ alert("DeviceDisappeared", dev, NULL, ainfo);
+ st->err++;
+ return 0;
+ }
+ }
+ close(fd);
+ }
fd = open(dev, O_RDONLY);
if (fd < 0) {
if (!st->err)
alert("DeviceDisappeared", dev, NULL, ainfo);
- st->err=1;
+ st->err++;
return 0;
}
fcntl(fd, F_SETFD, FD_CLOEXEC);
- if (ioctl(fd, GET_ARRAY_INFO, &array)<0) {
+ if (md_get_array_info(fd, &array) < 0) {
if (!st->err)
alert("DeviceDisappeared", dev, NULL, ainfo);
- st->err=1;
+ st->err++;
close(fd);
return 0;
}
*/
if (array.level == 0 || array.level == -1) {
if (!st->err && !st->from_config)
- alert("DeviceDisappeared", dev, "Wrong-Level", ainfo);
- st->err = 1;
+ alert("DeviceDisappeared", dev, " Wrong-Level", ainfo);
+ st->err++;
close(fd);
return 0;
}
if (!mse) {
/* duplicated array in statelist
* or re-created after reading mdstat*/
- st->err = 1;
+ st->err++;
close(fd);
return 0;
}
array.utime = st->utime + 1;;
if (st->err) {
- /* New array appeared where previously had and error */
+ /* New array appeared where previously had an error */
st->err = 0;
st->percent = RESYNC_NONE;
new_array = 1;
} else
alert("RebuildFinished", dev, NULL, ainfo);
if (sra)
- free(sra);
+ sysfs_free(sra);
}
st->percent = mse->percent;
i++) {
mdu_disk_info_t disc;
disc.number = i;
- if (ioctl(fd, GET_DISK_INFO, &disc) >= 0) {
+ if (md_get_disk_info(fd, &disc) >= 0) {
info[i].state = disc.state;
info[i].major = disc.major;
info[i].minor = disc.minor;
{
struct mdstat_ent *mse;
int new_found = 0;
+ char *name;
for (mse=mdstat; mse; mse=mse->next)
if (mse->devnm[0] &&
struct state *st = xcalloc(1, sizeof *st);
mdu_array_info_t array;
int fd;
- st->devname = xstrdup(get_md_name(mse->devnm));
+
+ name = get_md_name(mse->devnm);
+ if (!name) {
+ free(st);
+ continue;
+ }
+
+ st->devname = xstrdup(name);
if ((fd = open(st->devname, O_RDONLY)) < 0 ||
- ioctl(fd, GET_ARRAY_INFO, &array)< 0) {
+ md_get_array_info(fd, &array) < 0) {
/* no such array */
- if (fd >=0) close(fd);
+ if (fd >= 0)
+ close(fd);
put_md_name(st->devname);
free(st->devname);
if (st->metadata) {
close(fd);
st->next = *statelist;
st->err = 1;
+ st->from_auto = 1;
strcpy(st->devnm, mse->devnm);
st->percent = RESYNC_UNKNOWN;
st->expected_spares = -1;
close(fd);
return 0;
}
-
+
err = st->ss->load_container(st, fd, NULL);
close(fd);
if (err)
return 0;
-
+
if (from == to) {
/* We must check if number of active disks has not increased
* since ioctl in main loop. mdmon may have added spare
return dev;
}
-
static void try_spare_migration(struct state *statelist, struct alert_info *info)
{
struct state *from;
/* subarray monitored without parent container
* we can't move spares here */
continue;
-
+
if (to->parent)
/* member of a container */
to = to->parent;
{
struct stat stb;
char devnm[32];
+ char *tmp;
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));
+ tmp = stat2devnm(&stb);
+ if (!tmp) {
+ pr_err("%s is not a block device.\n", dev);
+ return 2;
+ }
+ strcpy(devnm, tmp);
while(1) {
struct mdstat_ent *ms = mdstat_read(1, 0);
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];
+
+ if (sysfs_init(&mdi, -1, devnm))
+ return 2;
+ 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) {
}
}
-#ifndef MDASSEMBLE
-
static char *clean_states[] = {
"clear", "inactive", "readonly", "read-auto", "clean", NULL };
mdi = sysfs_read(fd, devnm, GET_VERSION|GET_LEVEL|GET_SAFEMODE);
if (!mdi) {
if (verbose)
- pr_err("Failed to read sysfs attributes for "
- "%s\n", dev);
+ pr_err("Failed to read sysfs attributes for %s\n", dev);
close(fd);
return 0;
}
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) {
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);
return rv;
}
-#endif /* MDASSEMBLE */