[PATCH] Incremental: remove external arrays and devices correctly

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Kernel returns EBUSY when device fail invokes array fail.
In external metadata if kernel returns it, mdadm doesn't stop member
arrays but it will try to stop container directly. It fails because
container still has working arrays, so udev remove is triggered.

Try to set faulty state on device in member arrays first. If kernel
returns EBUSY, stop this array. After that remove the device from
container.

In external metadata mdmon has to remove faulty devices from degraded
arrays, just remove device from container.

Raid5 array doesn't return EBUSY, it allows to remove every device.
Mdadm shouldn't block it.

Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@xxxxxxxxx>
---
 Incremental.c | 78 +++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 52 insertions(+), 26 deletions(-)

diff --git a/Incremental.c b/Incremental.c
index 0c5698e..a4ff7d4 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -1683,6 +1683,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 +1792,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;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux