summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Incremental.c37
-rw-r--r--Manage.c10
2 files changed, 38 insertions, 9 deletions
diff --git a/Incremental.c b/Incremental.c
index 36f79ef5..1b7ebfaf 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -1578,9 +1578,11 @@ static int Incremental_container(struct supertype *st, char *devname,
int IncrementalRemove(char *devname, char *id_path, int verbose)
{
int mdfd;
- int rv;
+ int rv = 0;
struct mdstat_ent *ent;
struct mddev_dev devlist;
+ struct mdinfo mdi;
+ char buf[32];
if (!id_path)
dprintf(Name ": incremental removal without --path <id_path> "
@@ -1598,6 +1600,14 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
"of any array\n", devname);
return 1;
}
+ sysfs_init(&mdi, -1, ent->devnm);
+ if (sysfs_get_str(&mdi, NULL, "array_state",
+ buf, sizeof(buf)) > 0) {
+ if (strncmp(buf, "active", 6) == 0 ||
+ strncmp(buf, "clean", 5) == 0)
+ sysfs_set_str(&mdi, NULL,
+ "array_state", "read-auto");
+ }
mdfd = open_dev(ent->devnm);
if (mdfd < 0) {
pr_err("Cannot open array %s!!\n", ent->dev);
@@ -1625,17 +1635,30 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
if (is_container_member(memb, ent->dev)) {
int subfd = open_dev(memb->devnm);
if (subfd >= 0) {
- Manage_subdevs(memb->dev, subfd,
- &devlist, verbose, 0,
- NULL, 0);
+ rv |= Manage_subdevs(
+ memb->dev, subfd,
+ &devlist, verbose, 0,
+ NULL, 0);
close(subfd);
}
}
free_mdstat(mdstat);
} else
- Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL, 0);
- devlist.disposition = 'r';
- rv = Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL, 0);
+ rv |= Manage_subdevs(ent->dev, mdfd, &devlist,
+ verbose, 0, NULL, 0);
+ if (rv & 2) {
+ /* Failed due to EBUSY, try to stop the array
+ */
+ rv = Manage_runstop(ent->dev, mdfd, -1,
+ verbose, 1);
+ if (rv)
+ /* At least we can try to trigger a 'remove' */
+ sysfs_uevent(&mdi, "remove");
+ } else {
+ devlist.disposition = 'r';
+ rv = Manage_subdevs(ent->dev, mdfd, &devlist,
+ verbose, 0, NULL, 0);
+ }
close(mdfd);
free_mdstat(ent);
return rv;
diff --git a/Manage.c b/Manage.c
index 6267c0ca..c7738e1e 100644
--- a/Manage.c
+++ b/Manage.c
@@ -222,7 +222,10 @@ int Manage_runstop(char *devname, int fd, int runstop,
* to stop is probably a bad idea.
*/
close(fd);
- fd = open(devname, O_RDONLY|O_EXCL);
+ if (devnm[0] == '/')
+ fd = open(devname, O_RDONLY|O_EXCL);
+ else
+ fd = open_dev_flags(devnm, O_RDONLY|O_EXCL);
if (fd < 0 || strcmp(fd2devnm(fd), devnm) != 0) {
if (fd >= 0)
close(fd);
@@ -1100,6 +1103,7 @@ int Manage_subdevs(char *devname, int fd,
int count = 0; /* number of actions taken */
struct mdinfo info;
int frozen = 0;
+ int busy = 0;
if (ioctl(fd, GET_ARRAY_INFO, &array)) {
pr_err("Cannot get array info for %s\n",
@@ -1320,6 +1324,8 @@ int Manage_subdevs(char *devname, int fd,
if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
(sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
(unsigned long) stb.st_rdev))) {
+ if (errno == EBUSY)
+ busy = 1;
pr_err("set device faulty failed for %s: %s\n",
dv->devname, strerror(errno));
if (sysfd >= 0)
@@ -1377,7 +1383,7 @@ int Manage_subdevs(char *devname, int fd,
abort:
if (frozen > 0)
sysfs_set_str(&info, NULL, "sync_action","idle");
- return 1;
+ return !test && busy ? 2 : 1;
}
int autodetect(void)