diff options
author | Dimitri John Ledkov <xnox@ubuntu.com> | 2019-01-15 18:40:20 +0000 |
---|---|---|
committer | Dimitri John Ledkov <xnox@ubuntu.com> | 2019-01-15 18:41:08 +0000 |
commit | ada795fa8e7b1e27c134fe7d5aedf4517cd082f5 (patch) | |
tree | 5717f98c75f6b1a9fbae50b88c35f13d07993226 /Incremental.c | |
parent | 88ee7cfa1e00aabcfc8f48b57f4b226e7b5c2158 (diff) |
New upstream release
* New upstream release
* Cherrypick patches from master up to 757e55435997e355ee9b03e5d913b5496a3c39a8.
Diffstat (limited to 'Incremental.c')
-rw-r--r-- | Incremental.c | 83 |
1 files changed, 56 insertions, 27 deletions
diff --git a/Incremental.c b/Incremental.c index 0c5698ee..d4d3c353 100644 --- a/Incremental.c +++ b/Incremental.c @@ -1080,6 +1080,7 @@ static int partition_try_spare(char *devname, int *dfdp, struct dev_policy *pol, struct supertype *st2 = NULL; char *devname = NULL; unsigned long long devsectors; + char *pathlist[2]; if (de->d_ino == 0 || de->d_name[0] == '.' || (de->d_type != DT_LNK && de->d_type != DT_UNKNOWN)) @@ -1094,7 +1095,9 @@ static int partition_try_spare(char *devname, int *dfdp, struct dev_policy *pol, /* This is a partition - skip it */ goto next; - pol2 = path_policy(de->d_name, type_disk); + pathlist[0] = de->d_name; + pathlist[1] = NULL; + pol2 = path_policy(pathlist, type_disk); domain_merge(&domlist, pol2, st ? st->ss->name : NULL); if (domain_test(domlist, pol, st ? st->ss->name : NULL) != 1) @@ -1683,6 +1686,44 @@ static void run_udisks(char *arg1, char *arg2) ; } +static int force_remove(char *devnm, int fd, struct mdinfo *mdi, int verbose) +{ + int rv; + int devid = devnm2devid(devnm); + + run_udisks("--unmount", map_dev(major(devid), minor(devid), 0)); + rv = Manage_stop(devnm, fd, verbose, 1); + if (rv) { + /* At least we can try to trigger a 'remove' */ + sysfs_uevent(mdi, "remove"); + if (verbose) + pr_err("Fail to stop %s too.\n", devnm); + } + return rv; +} + +static void remove_from_member_array(struct mdstat_ent *memb, + struct mddev_dev *devlist, int verbose) +{ + int rv; + struct mdinfo mmdi; + int subfd = open_dev(memb->devnm); + + if (subfd >= 0) { + rv = Manage_subdevs(memb->devnm, subfd, devlist, verbose, + 0, NULL, 0); + if (rv & 2) { + if (sysfs_init(&mmdi, -1, memb->devnm)) + pr_err("unable to initialize sysfs for: %s\n", + memb->devnm); + else + force_remove(memb->devnm, subfd, &mmdi, + verbose); + } + close(subfd); + } +} + /* * IncrementalRemove - Attempt to see if the passed in device belongs to any * raid arrays, and if so first fail (if needed) and then remove the device. @@ -1754,40 +1795,28 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) strncmp(ent->metadata_version, "external:", 9) == 0) { struct mdstat_ent *mdstat = mdstat_read(0, 0); struct mdstat_ent *memb; - for (memb = mdstat ; memb ; memb = memb->next) - if (is_container_member(memb, ent->devnm)) { - int subfd = open_dev(memb->devnm); - if (subfd >= 0) { - rv |= Manage_subdevs( - memb->devnm, subfd, - &devlist, verbose, 0, - NULL, 0); - close(subfd); - } - } + for (memb = mdstat ; memb ; memb = memb->next) { + if (is_container_member(memb, ent->devnm)) + remove_from_member_array(memb, + &devlist, verbose); + } free_mdstat(mdstat); - } else + } else { rv |= Manage_subdevs(ent->devnm, mdfd, &devlist, verbose, 0, NULL, 0); - if (rv & 2) { + if (rv & 2) { /* Failed due to EBUSY, try to stop the array. * Give udisks a chance to unmount it first. */ - int devid = devnm2devid(ent->devnm); - run_udisks("--unmount", map_dev(major(devid),minor(devid), 0)); - rv = Manage_stop(ent->devnm, mdfd, verbose, 1); - if (rv) - /* At least we can try to trigger a 'remove' */ - sysfs_uevent(&mdi, "remove"); - if (verbose) { - if (rv) - pr_err("Fail to stop %s too.\n", ent->devnm); + rv = force_remove(ent->devnm, mdfd, &mdi, verbose); + goto end; } - } else { - devlist.disposition = 'r'; - rv = Manage_subdevs(ent->devnm, mdfd, &devlist, - verbose, 0, NULL, 0); } + + devlist.disposition = 'r'; + rv = Manage_subdevs(ent->devnm, mdfd, &devlist, + verbose, 0, NULL, 0); +end: close(mdfd); free_mdstat(ent); return rv; |