summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Incremental.c60
-rw-r--r--mdadm.h5
-rw-r--r--udev-md-raid-assembly.rules4
3 files changed, 46 insertions, 23 deletions
diff --git a/Incremental.c b/Incremental.c
index fc4e68ff..c1389a15 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -1674,33 +1674,52 @@ static void remove_from_member_array(struct mdstat_ent *memb,
}
}
-/*
- * 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.
+/**
+ * is_devnode_path() - check if the devname passed might be devnode path.
+ * @devnode: the path to check.
*
- * @devname - The device we want to remove
- * @id_path - name as found in /dev/disk/by-path for this device
+ * Devnode must be located directly in /dev directory. It is not checking existence of the file
+ * because the device might no longer exist during removal from raid array.
+ */
+static bool is_devnode_path(char *devnode)
+{
+ char *devnm = strrchr(devnode, '/');
+
+ if (!devnm || *(devnm + 1) == 0)
+ return false;
+
+ if (strncmp(devnode, DEV_DIR, DEV_DIR_LEN) == 0 && devnode + DEV_DIR_LEN - 1 == devnm)
+ return true;
+
+ return false;
+}
+
+/**
+ * IncrementalRemove() - Remove the device from all raid arrays.
+ * @devname: the device we want to remove, it could be kernel device name or devnode.
+ * @id_path: optional, /dev/disk/by-path path to save for bare scenarios support.
+ * @verbose: verbose flag.
*
- * Note: the device name must be a kernel name like "sda", so
- * that we can find it in /proc/mdstat
+ * First, fail the device (if needed) and then remove the device from native raid array or external
+ * container. If it is external container, the device is removed from each subarray first.
*/
int IncrementalRemove(char *devname, char *id_path, int verbose)
{
- struct mdstat_ent *ent = NULL;
+ char *devnm = basename(devname);
+ struct mddev_dev devlist = {0};
char buf[SYSFS_MAX_BUF_SIZE];
struct mdstat_ent *mdstat;
- struct mddev_dev devlist;
+ struct mdstat_ent *ent;
struct mdinfo mdi;
int rv = 1;
int mdfd;
- if (!id_path)
- dprintf("incremental removal without --path <id_path> lacks the possibility to re-add new device in this port\n");
-
- if (strchr(devname, '/')) {
- pr_err("incremental removal requires a kernel device name, not a file: %s\n", devname);
- return 1;
- }
+ if (strcmp(devnm, devname) != 0)
+ if (!is_devnode_path(devname)) {
+ pr_err("Cannot remove \"%s\", devnode path or kernel device name is allowed.\n",
+ devname);
+ return 1;
+ }
mdstat = mdstat_read(0, 0);
if (!mdstat) {
@@ -1708,15 +1727,15 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
return 1;
}
- ent = mdstat_find_by_member_name(mdstat, devname);
+ ent = mdstat_find_by_member_name(mdstat, devnm);
if (!ent) {
if (verbose >= 0)
- pr_err("%s does not appear to be a component of any array\n", devname);
+ pr_vrb("%s does not appear to be a component of any array\n", devnm);
goto out;
}
if (sysfs_init(&mdi, -1, ent->devnm)) {
- pr_err("unable to initialize sysfs for: %s\n", devname);
+ pr_err("unable to initialize sysfs for: %s\n", devnm);
goto out;
}
@@ -1746,8 +1765,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
map_free(map);
}
- memset(&devlist, 0, sizeof(devlist));
- devlist.devname = devname;
+ devlist.devname = devnm;
devlist.disposition = 'I';
/* for a container, we must fail each member array */
if (is_mdstat_ent_external(ent)) {
diff --git a/mdadm.h b/mdadm.h
index 5c3a9836..f3b9f54c 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -100,6 +100,11 @@ struct dlm_lksb {
#define DEFAULT_BITMAP_DELAY 5
#define DEFAULT_MAX_WRITE_BEHIND 256
+#ifndef DEV_DIR
+#define DEV_DIR "/dev/"
+#define DEV_DIR_LEN (sizeof(DEV_DIR) - 1)
+#endif /* DEV_DIR */
+
/* DEV_NUM_PREF is a subpath to numbered MD devices, e.g. /dev/md1 or directory name.
* DEV_NUM_PREF_LEN is a length with Null byte excluded.
*/
diff --git a/udev-md-raid-assembly.rules b/udev-md-raid-assembly.rules
index d4a7f0a5..4cd2c6f4 100644
--- a/udev-md-raid-assembly.rules
+++ b/udev-md-raid-assembly.rules
@@ -41,7 +41,7 @@ ACTION=="change", KERNEL!="dm-*|md*", GOTO="md_inc_end"
ACTION!="remove", IMPORT{program}="BINDIR/mdadm --incremental --export $devnode --offroot $env{DEVLINKS}"
ACTION!="remove", ENV{MD_STARTED}=="*unsafe*", ENV{MD_FOREIGN}=="no", ENV{SYSTEMD_WANTS}+="mdadm-last-resort@$env{MD_DEVICE}.timer"
-ACTION=="remove", ENV{ID_PATH}=="?*", RUN+="BINDIR/mdadm -If $name --path $env{ID_PATH}"
-ACTION=="remove", ENV{ID_PATH}!="?*", RUN+="BINDIR/mdadm -If $name"
+ACTION=="remove", ENV{ID_PATH}=="?*", RUN+="BINDIR/mdadm -If $devnode --path $env{ID_PATH}"
+ACTION=="remove", ENV{ID_PATH}!="?*", RUN+="BINDIR/mdadm -If $devnode"
LABEL="md_inc_end"