Skip to content

Commit

Permalink
Incremental: support devnode in IncrementalRemove.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
mtkaczyk committed Sep 10, 2024
1 parent be1b4ff commit 9b8933b
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 23 deletions.
60 changes: 39 additions & 21 deletions Incremental.c
Original file line number Diff line number Diff line change
Expand Up @@ -1674,49 +1674,68 @@ 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) {
pr_err("Cannot read /proc/mdstat file, aborting\n");
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;
}

Expand Down Expand Up @@ -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)) {
Expand Down
5 changes: 5 additions & 0 deletions mdadm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
4 changes: 2 additions & 2 deletions udev-md-raid-assembly.rules
Original file line number Diff line number Diff line change
Expand Up @@ -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"

0 comments on commit 9b8933b

Please sign in to comment.