From 79374e4df2c809ce5a7ed83aef0a850ed0c14c70 Mon Sep 17 00:00:00 2001 From: wguanghao Date: Thu, 14 Dec 2023 16:28:59 +0800 Subject: [PATCH] Fix race of 'mdadm --add' and 'mdadm --incremental' --- ...e-of-mdadm-add-and-mdadm-incremental.patch | 133 ++++++++++++++++++ mdadm.spec | 6 +- 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 0035-Fix-race-of-mdadm-add-and-mdadm-incremental.patch diff --git a/0035-Fix-race-of-mdadm-add-and-mdadm-incremental.patch b/0035-Fix-race-of-mdadm-add-and-mdadm-incremental.patch new file mode 100644 index 0000000..4011087 --- /dev/null +++ b/0035-Fix-race-of-mdadm-add-and-mdadm-incremental.patch @@ -0,0 +1,133 @@ +From 190ed71d9e891e5cfb2f0248c90982cd53e5d72c Mon Sep 17 00:00:00 2001 +From: Li Xiao Keng +Date: Thu, 7 Sep 2023 19:37:44 +0800 +Subject: [PATCH] Fix race of "mdadm --add" and "mdadm --incremental" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There is a raid1 with sda and sdb. And we add sdc to this raid, +it may return -EBUSY. + +The main process of --add: +1. dev_open(sdc) in Manage_add +2. store_super1(st, di->fd) in write_init_super1 +3. fsync(fd) in store_super1 +4. close(di->fd) in write_init_super1 +5. ioctl(ADD_NEW_DISK) + +Step 2 and 3 will add sdc to metadata of raid1. There will be +udev(change of sdc) event after step4. Then "/usr/sbin/mdadm +--incremental --export $devnode --offroot $env{DEVLINKS}" +will be run, and the sdc will be added to the raid1. Then +step 5 will return -EBUSY because it checks if device isn't +claimed in md_import_device()->lock_rdev()->blkdev_get_by_dev() +->blkdev_get(). + +It will be confusing for users because sdc is added first time. +The "incremental" will get map_lock before add sdc to raid1. +So we add map_lock before write_init_super in "mdadm --add" +to fix the race of "add" and "incremental". + +Signed-off-by: Li Xiao Keng +Signed-off-by: Guanqin Miao +Reviewed-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + Manage.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/Manage.c b/Manage.c +index ffe55f8..7ffe890 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -721,6 +721,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + struct supertype *dev_st; + int j; + mdu_disk_info_t disc; ++ struct map_ent *map = NULL; + + if (!get_dev_size(tfd, dv->devname, &ldsize)) { + if (dv->disposition == 'M') +@@ -918,6 +919,9 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + disc.raid_disk = 0; + } + ++ if (map_lock(&map)) ++ pr_err("failed to get exclusive lock on mapfile when add disk\n"); ++ + if (array->not_persistent==0) { + int dfd; + if (dv->disposition == 'j') +@@ -929,9 +933,9 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT); + if (tst->ss->add_to_super(tst, &disc, dfd, + dv->devname, INVALID_SECTORS)) +- return -1; ++ goto unlock; + if (tst->ss->write_init_super(tst)) +- return -1; ++ goto unlock; + } else if (dv->disposition == 'A') { + /* this had better be raid1. + * As we are "--re-add"ing we must find a spare slot +@@ -989,7 +993,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + pr_err("add failed for %s: could not get exclusive access to container\n", + dv->devname); + tst->ss->free_super(tst); +- return -1; ++ goto unlock; + } + + Kill(dv->devname, NULL, 0, -1, 0); +@@ -1000,7 +1004,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + dv->devname, INVALID_SECTORS)) { + close(dfd); + close(container_fd); +- return -1; ++ goto unlock; + } + if (tst->update_tail) + flush_metadata_updates(tst); +@@ -1013,7 +1017,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + dv->devname); + close(container_fd); + tst->ss->free_super(tst); +- return -1; ++ goto unlock; + } + sra->array.level = LEVEL_CONTAINER; + /* Need to set data_offset and component_size */ +@@ -1028,7 +1032,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + pr_err("add new device to external metadata failed for %s\n", dv->devname); + close(container_fd); + sysfs_free(sra); +- return -1; ++ goto unlock; + } + ping_monitor(devnm); + sysfs_free(sra); +@@ -1042,7 +1046,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + else + pr_err("add new device failed for %s as %d: %s\n", + dv->devname, j, strerror(errno)); +- return -1; ++ goto unlock; + } + if (dv->disposition == 'j') { + pr_err("Journal added successfully, making %s read-write\n", devname); +@@ -1053,7 +1057,11 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + } + if (verbose >= 0) + pr_err("added %s\n", dv->devname); ++ map_unlock(&map); + return 1; ++unlock: ++ map_unlock(&map); ++ return -1; + } + + int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv, +-- +1.8.3.1 + diff --git a/mdadm.spec b/mdadm.spec index 5e3ae13..55f3e1c 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,6 +1,6 @@ Name: mdadm Version: 4.1 -Release: 11 +Release: 12 Summary: The software RAID arrays user manage tools License: GPLv2+ URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ @@ -44,6 +44,7 @@ Patch31: 0031-fix-NULL-dereference-in-super_by_fd.patch Patch32: 0032-Fix-memory-leak-after-mdadm-detail.patch Patch33: 0033-mdadm-block-creation-with-long-names.patch Patch34: 0034-Fix-null-pointer-for-incremental-in-mdadm.patch +Patch35: 0035-Fix-race-of-mdadm-add-and-mdadm-incremental.patch BuildRequires: systemd gcc binutils Requires(post): systemd coreutils @@ -109,6 +110,9 @@ install -d -m 710 %{buildroot}/var/run/mdadm/ %{_mandir}/man*/* %changelog +* Thu Dec 14 2023 wuguanghao - 4.1-12 +- Fix race of "mdadm --add" and "mdadm --incremental" + * Tue Sep 12 2023 miaoguanqin - 4.1-11 - fix null pointer for incremental in mdadm -- Gitee