cdf21d08ef
After updating to latest upstream, bug2163711 can be fixed. We don't use rhel only udev rule anymore and we use the udev rules from upstream. So we don't need to modify our rhel only udev rule again. Resolves: bz#2163711 Signed-off-by: Xiao Ni <xni@redhat.com>
163 lines
5.1 KiB
Diff
163 lines
5.1 KiB
Diff
From 27ad4900501c615b7c6b266bf23948e5606dba53 Mon Sep 17 00:00:00 2001
|
|
From: Logan Gunthorpe <logang@deltatee.com>
|
|
Date: Wed, 27 Jul 2022 15:52:46 -0600
|
|
Subject: [PATCH 50/83] mdadm: Don't open md device for CREATE and ASSEMBLE
|
|
|
|
The mdadm command tries to open the md device for most modes, first
|
|
thing, no matter what. When running to create or assemble an array,
|
|
in most cases, the md device will not exist, the open call will fail
|
|
and everything will proceed correctly.
|
|
|
|
However, when running tests, a create or assembly command may be run
|
|
shortly after stopping an array and the old md device file may still
|
|
be around. Then, if create_on_open is set in the kernel, a new md
|
|
device will be created when mdadm does its initial open.
|
|
|
|
When mdadm gets around to creating the new device with the new_array
|
|
parameter it issues this error:
|
|
|
|
mdadm: Fail to create md0 when using
|
|
/sys/module/md_mod/parameters/new_array, fallback to creation via node
|
|
|
|
This is because an mddev was already created by the kernel with the
|
|
earlier open() call and thus the new one being created will fail with
|
|
EEXIST. The mdadm command will still successfully be created due to
|
|
falling back to the node creation method. However, the error message
|
|
itself will fail any test that's running it.
|
|
|
|
This issue is a race condition that is very rare, but a recent change
|
|
in the kernel caused this to happen more frequently: about 1 in 50
|
|
times.
|
|
|
|
To fix this, don't bother trying to open the md device for CREATE,
|
|
ASSEMBLE and BUILD commands, as the file descriptor will never be used
|
|
anyway even if it is successfully openned. The mdfd has not been used
|
|
for these commands since:
|
|
|
|
7f91af49ad09 ("Delay creation of array devices for assemble/build/create")
|
|
|
|
The checks that were done on the open device can be changed to being
|
|
done with stat.
|
|
|
|
Side note: it would be nice to disable create_on_open as well to help
|
|
solve this, but it seems the work for this was never finished. By default,
|
|
mdadm will create using the old node interface when a name is specified
|
|
unless the user specifically puts names=yes in a config file, which
|
|
doesn't seem to be common or desirable to require this..
|
|
|
|
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
|
|
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
|
|
---
|
|
lib.c | 12 ++++++++++++
|
|
mdadm.c | 40 ++++++++++++++++++++--------------------
|
|
mdadm.h | 1 +
|
|
3 files changed, 33 insertions(+), 20 deletions(-)
|
|
|
|
diff --git a/lib.c b/lib.c
|
|
index 7e3e3d47..e395b28d 100644
|
|
--- a/lib.c
|
|
+++ b/lib.c
|
|
@@ -164,6 +164,18 @@ char *stat2devnm(struct stat *st)
|
|
return devid2devnm(st->st_rdev);
|
|
}
|
|
|
|
+bool stat_is_md_dev(struct stat *st)
|
|
+{
|
|
+ if ((S_IFMT & st->st_mode) != S_IFBLK)
|
|
+ return false;
|
|
+ if (major(st->st_rdev) == MD_MAJOR)
|
|
+ return true;
|
|
+ if (major(st->st_rdev) == (unsigned)get_mdp_major())
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
char *fd2devnm(int fd)
|
|
{
|
|
struct stat stb;
|
|
diff --git a/mdadm.c b/mdadm.c
|
|
index 845e4466..972adb52 100644
|
|
--- a/mdadm.c
|
|
+++ b/mdadm.c
|
|
@@ -1329,6 +1329,9 @@ int main(int argc, char *argv[])
|
|
|
|
if (mode == MANAGE || mode == BUILD || mode == CREATE ||
|
|
mode == GROW || (mode == ASSEMBLE && ! c.scan)) {
|
|
+ struct stat stb;
|
|
+ int ret;
|
|
+
|
|
if (devs_found < 1) {
|
|
pr_err("an md device must be given in this mode\n");
|
|
exit(2);
|
|
@@ -1341,6 +1344,12 @@ int main(int argc, char *argv[])
|
|
mdfd = open_mddev(devlist->devname, 1);
|
|
if (mdfd < 0)
|
|
exit(1);
|
|
+
|
|
+ ret = fstat(mdfd, &stb);
|
|
+ if (ret) {
|
|
+ pr_err("fstat failed on %s.\n", devlist->devname);
|
|
+ exit(1);
|
|
+ }
|
|
} else {
|
|
char *bname = basename(devlist->devname);
|
|
|
|
@@ -1348,30 +1357,21 @@ int main(int argc, char *argv[])
|
|
pr_err("Name %s is too long.\n", devlist->devname);
|
|
exit(1);
|
|
}
|
|
- /* non-existent device is OK */
|
|
- mdfd = open_mddev(devlist->devname, 0);
|
|
- }
|
|
- if (mdfd == -2) {
|
|
- pr_err("device %s exists but is not an md array.\n", devlist->devname);
|
|
- exit(1);
|
|
- }
|
|
- if ((int)ident.super_minor == -2) {
|
|
- struct stat stb;
|
|
- if (mdfd < 0) {
|
|
+
|
|
+ ret = stat(devlist->devname, &stb);
|
|
+ if (ident.super_minor == -2 && ret != 0) {
|
|
pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n",
|
|
- devlist->devname);
|
|
+ devlist->devname);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ if (!ret && !stat_is_md_dev(&stb)) {
|
|
+ pr_err("device %s exists but is not an md array.\n", devlist->devname);
|
|
exit(1);
|
|
}
|
|
- fstat(mdfd, &stb);
|
|
- ident.super_minor = minor(stb.st_rdev);
|
|
- }
|
|
- if (mdfd >= 0 && mode != MANAGE && mode != GROW) {
|
|
- /* We don't really want this open yet, we just might
|
|
- * have wanted to check some things
|
|
- */
|
|
- close(mdfd);
|
|
- mdfd = -1;
|
|
}
|
|
+ if (ident.super_minor == -2)
|
|
+ ident.super_minor = minor(stb.st_rdev);
|
|
}
|
|
|
|
if (s.raiddisks) {
|
|
diff --git a/mdadm.h b/mdadm.h
|
|
index adb7cdaa..8208b81e 100644
|
|
--- a/mdadm.h
|
|
+++ b/mdadm.h
|
|
@@ -1672,6 +1672,7 @@ void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0
|
|
extern char *stat2kname(struct stat *st);
|
|
extern char *fd2kname(int fd);
|
|
extern char *stat2devnm(struct stat *st);
|
|
+bool stat_is_md_dev(struct stat *st);
|
|
extern char *fd2devnm(int fd);
|
|
extern void udev_block(char *devnm);
|
|
extern void udev_unblock(void);
|
|
--
|
|
2.38.1
|
|
|