summaryrefslogtreecommitdiffstats
path: root/Incremental.c
diff options
context:
space:
mode:
authorMariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>2024-07-05 10:49:27 +0200
committerMariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>2024-07-30 16:00:37 +0200
commit4b3644ab4ce6df8c7f64c189c12b66627ff3e027 (patch)
treefe1a8996f70da8f1f8f3680c3fc5b7c4c6978402 /Incremental.c
parentreview.yml: fix typo in DEBIAN compiler flag (diff)
downloadmdadm-4b3644ab4ce6df8c7f64c189c12b66627ff3e027.tar.xz
mdadm-4b3644ab4ce6df8c7f64c189c12b66627ff3e027.zip
mdstat: Rework mdstat external arrays handling
To avoid repeating mdstat_read() in IncrementalRemove(), new function mdstat_find_by_member_name() has been proposed. With that, IncrementalRemove() handles own copy of mdstat content and there is no need to repeat reading for external stop. Additionally, It proposed few helper to avoid repeating mdstat_ent->metadata_version checks across code. Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Diffstat (limited to 'Incremental.c')
-rw-r--r--Incremental.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/Incremental.c b/Incremental.c
index 83db0712..abc7721b 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -1686,12 +1686,13 @@ static void remove_from_member_array(struct mdstat_ent *memb,
*/
int IncrementalRemove(char *devname, char *id_path, int verbose)
{
- int mdfd;
- int rv = 0;
- struct mdstat_ent *ent;
+ struct mdstat_ent *ent = NULL;
+ char buf[SYSFS_MAX_BUF_SIZE];
+ struct mdstat_ent *mdstat;
struct mddev_dev devlist;
struct mdinfo mdi;
- char buf[SYSFS_MAX_BUF_SIZE];
+ 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");
@@ -1700,16 +1701,25 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
pr_err("incremental removal requires a kernel device name, not a file: %s\n", devname);
return 1;
}
- ent = mdstat_by_component(devname);
+
+ 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);
if (!ent) {
if (verbose >= 0)
pr_err("%s does not appear to be a component of any array\n", devname);
- return 1;
+ goto out;
}
+
if (sysfs_init(&mdi, -1, ent->devnm)) {
pr_err("unable to initialize sysfs for: %s\n", devname);
- return 1;
+ goto out;
}
+
mdfd = open_dev_excl(ent->devnm);
if (is_fd_valid(mdfd)) {
close_fd(&mdfd);
@@ -1725,8 +1735,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
if (mdfd < 0) {
if (verbose >= 0)
pr_err("Cannot open array %s!!\n", ent->devnm);
- free_mdstat(ent);
- return 1;
+ goto out;
}
if (id_path) {
@@ -1741,16 +1750,13 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
devlist.devname = devname;
devlist.disposition = 'I';
/* for a container, we must fail each member array */
- if (ent->metadata_version &&
- strncmp(ent->metadata_version, "external:", 9) == 0) {
- struct mdstat_ent *mdstat = mdstat_read(0, 0);
+ if (is_mdstat_ent_external(ent)) {
struct mdstat_ent *memb;
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 {
/*
* This 'I' incremental remove is a try-best effort,
@@ -1765,7 +1771,8 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
rv = Manage_subdevs(ent->devnm, mdfd, &devlist,
verbose, 0, UOPT_UNDEFINED, 0);
- close(mdfd);
- free_mdstat(ent);
+ close_fd(&mdfd);
+out:
+ free_mdstat(mdstat);
return rv;
}