You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
5.3 KiB
152 lines
5.3 KiB
From 9b8933bb6dbfcae1bd5a2f933c87684de99412de Mon Sep 17 00:00:00 2001
|
|
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
|
Date: Tue, 25 Jun 2024 12:53:46 +0200
|
|
Subject: [PATCH 171/201] Incremental: support devnode in IncrementalRemove.
|
|
|
|
There are no reasons to keep this interface different than others.
|
|
Allow to use devnode but keep old way for backward compatibility.
|
|
Method is added to verify that only devnode or kernel name is used.
|
|
|
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
|
---
|
|
Incremental.c | 60 ++++++++++++++++++++++++-------------
|
|
mdadm.h | 5 ++++
|
|
udev-md-raid-assembly.rules | 4 +--
|
|
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"
|
|
--
|
|
2.41.0
|
|
|