linux-raid.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/1] md: generate CHANGE uevents for md device
@ 2024-05-22  7:33 Kinga Stefaniuk
  2024-05-22  7:33 ` [PATCH v6 1/1] " Kinga Stefaniuk
  0 siblings, 1 reply; 7+ messages in thread
From: Kinga Stefaniuk @ 2024-05-22  7:33 UTC (permalink / raw)
  To: linux-raid; +Cc: song

Patch is caused by changes in mdadm - now mdmonitor is relying on udev
events instead of pooling changes on /proc/mdstat file. This change 
gave possibility to send events to the userspace.
Now, more events will be read by mdmonitor, but mechanism of getting
details of the event will remain the same - all devices have to be
scanned on new event and their parameters read. It can be changed by
adding environmental data, which will fully describe this uevent,
as Kuai suggested. This change needs to be analyzed and planned,
because it requires a lot of work in md and design changes in
mdmonitor - to stop scanning all of the devices on new event and read
uevent details directly from udev. Mariusz will take care of this topic,
and follow up on this later.
Paul, the test suite which was used is internal and checks if mdmonitor
has noticed expected events. For now there is no plan for adding test,
which checking events to mdadm.

Kinga Stefaniuk (1):
  md: generate CHANGE uevents for md device

 drivers/md/md.c     | 47 ++++++++++++++++++++++++++++++---------------
 drivers/md/md.h     |  2 +-
 drivers/md/raid10.c |  2 +-
 drivers/md/raid5.c  |  2 +-
 4 files changed, 35 insertions(+), 18 deletions(-)

-- 
2.35.3


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v6 1/1] md: generate CHANGE uevents for md device
  2024-05-22  7:33 [PATCH v6 0/1] md: generate CHANGE uevents for md device Kinga Stefaniuk
@ 2024-05-22  7:33 ` Kinga Stefaniuk
  2024-05-28  8:51   ` kernel test robot
                     ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Kinga Stefaniuk @ 2024-05-22  7:33 UTC (permalink / raw)
  To: linux-raid; +Cc: song

In mdadm commit 49b69533e8 ("mdmonitor: check if udev has finished
events processing") mdmonitor has been learnt to wait for udev to finish
processing, and later in commit 9935cf0f64f3 ("Mdmonitor: Improve udev
event handling") pooling for MD events on /proc/mdstat file has been
deprecated because relying on udev events is more reliable and less bug
prone (we are not competing with udev).

After those changes we are still observing missing mdmonitor events in
some scenarios, especially SpareEvent is likely to be missed. With this
patch MD will be able to generate more change uevents and wakeup
mdmonitor more frequently to give it possibility to notice events.
MD has md_new_event() functionality to trigger events and with this
patch this function is extended to generate udev CHANGE uevents. It
cannot be done directly for md_error because this function is called on
interrupts context, so appropriate workqueue is used. Uevents are less time
critical, it is safe to use workqueue. It is limited to CHANGE event as
there is no need to generate other uevents for now.
With this change, mdmonitor events are less likely to be missed. Our
internal tests suite confirms that, mdmonitor reliability is (again)
improved.

Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>

---

v6: use another workqueue and only on md_error, make configurable
    if kobject_uevent is run immediately on event or queued
v5: fix flush_work missing and commit message fixes
v4: add more detailed commit message
v3: fix problems with calling function from interrupt context,
    add work_queue and queue events notification
v2: resolve merge conflicts with applying the patch
Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
---
 drivers/md/md.c     | 47 ++++++++++++++++++++++++++++++---------------
 drivers/md/md.h     |  2 +-
 drivers/md/raid10.c |  2 +-
 drivers/md/raid5.c  |  2 +-
 4 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index aff9118ff697..2ec696e17f3d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -313,6 +313,16 @@ static int start_readonly;
  */
 static bool create_on_open = true;
 
+/*
+ * Send every new event to the userspace.
+ */
+static void trigger_kobject_uevent(struct work_struct *work)
+{
+	struct mddev *mddev = container_of(work, struct mddev, event_work);
+
+	kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
+}
+
 /*
  * We have a system wide 'event count' that is incremented
  * on any 'interesting' event, and readers of /proc/mdstat
@@ -325,10 +335,15 @@ static bool create_on_open = true;
  */
 static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
 static atomic_t md_event_count;
-void md_new_event(void)
+void md_new_event(struct mddev *mddev, bool trigger_event)
 {
 	atomic_inc(&md_event_count);
 	wake_up(&md_event_waiters);
+
+	if (trigger_event)
+		kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
+	else
+		schedule_work(&mddev->event_work);
 }
 EXPORT_SYMBOL_GPL(md_new_event);
 
@@ -863,6 +878,7 @@ static void mddev_free(struct mddev *mddev)
 	list_del(&mddev->all_mddevs);
 	spin_unlock(&all_mddevs_lock);
 
+	cancel_work_sync(&mddev->event_work);
 	mddev_destroy(mddev);
 	kfree(mddev);
 }
@@ -2940,7 +2956,7 @@ static int add_bound_rdev(struct md_rdev *rdev)
 	if (mddev->degraded)
 		set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-	md_new_event();
+	md_new_event(mddev, true);
 	return 0;
 }
 
@@ -3057,7 +3073,7 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
 				md_kick_rdev_from_array(rdev);
 				if (mddev->pers)
 					set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
-				md_new_event();
+				md_new_event(mddev, true);
 			}
 		}
 	} else if (cmd_match(buf, "writemostly")) {
@@ -4173,7 +4189,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
 	if (!mddev->thread)
 		md_update_sb(mddev, 1);
 	sysfs_notify_dirent_safe(mddev->sysfs_level);
-	md_new_event();
+	md_new_event(mddev, true);
 	rv = len;
 out_unlock:
 	mddev_unlock_and_resume(mddev);
@@ -4700,7 +4716,7 @@ new_dev_store(struct mddev *mddev, const char *buf, size_t len)
 		export_rdev(rdev, mddev);
 	mddev_unlock_and_resume(mddev);
 	if (!err)
-		md_new_event();
+		md_new_event(mddev, true);
 	return err ? err : len;
 }
 
@@ -5902,6 +5918,7 @@ struct mddev *md_alloc(dev_t dev, char *name)
 		return ERR_PTR(error);
 	}
 
+	INIT_WORK(&mddev->event_work, trigger_kobject_uevent);
 	kobject_uevent(&mddev->kobj, KOBJ_ADD);
 	mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state");
 	mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level");
@@ -6244,7 +6261,7 @@ int md_run(struct mddev *mddev)
 	if (mddev->sb_flags)
 		md_update_sb(mddev, 0);
 
-	md_new_event();
+	md_new_event(mddev, true);
 	return 0;
 
 bitmap_abort:
@@ -6603,7 +6620,7 @@ static int do_md_stop(struct mddev *mddev, int mode)
 		if (mddev->hold_active == UNTIL_STOP)
 			mddev->hold_active = 0;
 	}
-	md_new_event();
+	md_new_event(mddev, true);
 	sysfs_notify_dirent_safe(mddev->sysfs_state);
 	return 0;
 }
@@ -7099,7 +7116,7 @@ static int hot_remove_disk(struct mddev *mddev, dev_t dev)
 	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 	if (!mddev->thread)
 		md_update_sb(mddev, 1);
-	md_new_event();
+	md_new_event(mddev, true);
 
 	return 0;
 busy:
@@ -7179,7 +7196,7 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
 	 * array immediately.
 	 */
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-	md_new_event();
+	md_new_event(mddev, true);
 	return 0;
 
 abort_export:
@@ -8159,7 +8176,7 @@ void md_error(struct mddev *mddev, struct md_rdev *rdev)
 	}
 	if (mddev->event_work.func)
 		queue_work(md_misc_wq, &mddev->event_work);
-	md_new_event();
+	md_new_event(mddev, false);
 }
 EXPORT_SYMBOL(md_error);
 
@@ -9049,7 +9066,7 @@ void md_do_sync(struct md_thread *thread)
 		mddev->curr_resync = MD_RESYNC_ACTIVE; /* no longer delayed */
 	mddev->curr_resync_completed = j;
 	sysfs_notify_dirent_safe(mddev->sysfs_completed);
-	md_new_event();
+	md_new_event(mddev, true);
 	update_time = jiffies;
 
 	blk_start_plug(&plug);
@@ -9120,7 +9137,7 @@ void md_do_sync(struct md_thread *thread)
 			/* this is the earliest that rebuild will be
 			 * visible in /proc/mdstat
 			 */
-			md_new_event();
+			md_new_event(mddev, true);
 
 		if (last_check + window > io_sectors || j == max_sectors)
 			continue;
@@ -9386,7 +9403,7 @@ static int remove_and_add_spares(struct mddev *mddev,
 			sysfs_link_rdev(mddev, rdev);
 			if (!test_bit(Journal, &rdev->flags))
 				spares++;
-			md_new_event();
+			md_new_event(mddev, true);
 			set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		}
 	}
@@ -9505,7 +9522,7 @@ static void md_start_sync(struct work_struct *ws)
 		__mddev_resume(mddev, false);
 	md_wakeup_thread(mddev->sync_thread);
 	sysfs_notify_dirent_safe(mddev->sysfs_action);
-	md_new_event();
+	md_new_event(mddev, true);
 	return;
 
 not_running:
@@ -9757,7 +9774,7 @@ void md_reap_sync_thread(struct mddev *mddev)
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	sysfs_notify_dirent_safe(mddev->sysfs_completed);
 	sysfs_notify_dirent_safe(mddev->sysfs_action);
-	md_new_event();
+	md_new_event(mddev, true);
 	if (mddev->event_work.func)
 		queue_work(md_misc_wq, &mddev->event_work);
 	wake_up(&resync_wait);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index ca085ecad504..6c0a45d4613e 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -803,7 +803,7 @@ extern int md_super_wait(struct mddev *mddev);
 extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
 		struct page *page, blk_opf_t opf, bool metadata_op);
 extern void md_do_sync(struct md_thread *thread);
-extern void md_new_event(void);
+extern void md_new_event(struct mddev *mddev, bool trigger_event);
 extern void md_allow_write(struct mddev *mddev);
 extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
 extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index a4556d2e46bf..4f4adbe5da95 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -4545,7 +4545,7 @@ static int raid10_start_reshape(struct mddev *mddev)
 	set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	conf->reshape_checkpoint = jiffies;
-	md_new_event();
+	md_new_event(mddev, true);
 	return 0;
 
 abort:
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 2bd1ce9b3922..085206f1cdcc 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -8503,7 +8503,7 @@ static int raid5_start_reshape(struct mddev *mddev)
 	set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	conf->reshape_checkpoint = jiffies;
-	md_new_event();
+	md_new_event(mddev, true);
 	return 0;
 }
 
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v6 1/1] md: generate CHANGE uevents for md device
  2024-05-22  7:33 ` [PATCH v6 1/1] " Kinga Stefaniuk
@ 2024-05-28  8:51   ` kernel test robot
  2024-06-10 18:03   ` Song Liu
  2024-06-11  8:56   ` Yu Kuai
  2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2024-05-28  8:51 UTC (permalink / raw)
  To: Kinga Stefaniuk
  Cc: oe-lkp, lkp, Mateusz Grzonka, linux-raid, song, oliver.sang

[-- Attachment #1: Type: text/plain, Size: 2573 bytes --]



Hello,

kernel test robot noticed "mdadm-selftests.07revert-inplace.fail" on:

commit: 14a629abdd2e5e55a5122a59e338d9b6570c2c81 ("[PATCH v6 1/1] md: generate CHANGE uevents for md device")
url: https://github.com/intel-lab-lkp/linux/commits/Kinga-Stefaniuk/md-generate-CHANGE-uevents-for-md-device/20240522-153509
base: v6.9
patch link: https://lore.kernel.org/all/20240522073310.8014-2-kinga.stefaniuk@intel.com/
patch subject: [PATCH v6 1/1] md: generate CHANGE uevents for md device

in testcase: mdadm-selftests
version: mdadm-selftests-x86_64-5f41845-1_20240412
with following parameters:

	disk: 1HDD
	test_prefix: 07revert-inplace



compiler: gcc-13
test machine: 8 threads 1 sockets Intel(R) Core(TM) i7-4790T CPU @ 2.70GHz (Haswell) with 16G memory

(please refer to attached dmesg/kmsg for entire log/backtrace)




If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202405281639.be74a40e-oliver.sang@intel.com

2024-05-26 00:53:50 mkdir -p /var/tmp
2024-05-26 00:53:50 mke2fs -t ext3 -b 4096 -J size=4 -q /dev/sdb1
2024-05-26 00:54:20 mount -t ext3 /dev/sdb1 /var/tmp
sed -e 's/{DEFAULT_METADATA}/1.2/g' \
-e 's,{MAP_PATH},/run/mdadm/map,g'  mdadm.8.in > mdadm.8
/usr/bin/install -D -m 644 mdadm.8 /usr/share/man/man8/mdadm.8
/usr/bin/install -D -m 644 mdmon.8 /usr/share/man/man8/mdmon.8
/usr/bin/install -D -m 644 md.4 /usr/share/man/man4/md.4
/usr/bin/install -D -m 644 mdadm.conf.5 /usr/share/man/man5/mdadm.conf.5
/usr/bin/install -D -m 644 udev-md-raid-creating.rules /lib/udev/rules.d/01-md-raid-creating.rules
/usr/bin/install -D -m 644 udev-md-raid-arrays.rules /lib/udev/rules.d/63-md-raid-arrays.rules
/usr/bin/install -D -m 644 udev-md-raid-assembly.rules /lib/udev/rules.d/64-md-raid-assembly.rules
/usr/bin/install -D -m 644 udev-md-clustered-confirm-device.rules /lib/udev/rules.d/69-md-clustered-confirm-device.rules
/usr/bin/install -D  -m 755 mdadm /sbin/mdadm
/usr/bin/install -D  -m 755 mdmon /sbin/mdmon
Testing on linux-6.9.0-00001-g14a629abdd2e kernel
/lkp/benchmarks/mdadm-selftests/tests/07revert-inplace... FAILED - see /var/tmp/07revert-inplace.log and /var/tmp/fail07revert-inplace.log for details


(log is attached)



The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20240528/202405281639.be74a40e-oliver.sang@intel.com



-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


[-- Attachment #2: log --]
[-- Type: text/plain, Size: 5159 bytes --]

+ . /lkp/benchmarks/mdadm-selftests/tests/07revert-inplace
++ set -e -x
++ mdadm -CR --assume-clean /dev/md0 -l5 -n4 -x1 /dev/loop0 /dev/loop1 /dev/loop2 /dev/loop3 /dev/loop4
++ rm -f /var/tmp/stderr
++ case $* in
++ case $* in
++ for args in $*
++ [[ -CR =~ /dev/ ]]
++ for args in $*
++ [[ --assume-clean =~ /dev/ ]]
++ for args in $*
++ [[ /dev/md0 =~ /dev/ ]]
++ [[ /dev/md0 =~ md ]]
++ for args in $*
++ [[ -l5 =~ /dev/ ]]
++ for args in $*
++ [[ -n4 =~ /dev/ ]]
++ for args in $*
++ [[ -x1 =~ /dev/ ]]
++ for args in $*
++ [[ /dev/loop0 =~ /dev/ ]]
++ [[ /dev/loop0 =~ md ]]
++ /lkp/benchmarks/mdadm-selftests/mdadm --zero /dev/loop0
mdadm: Unrecognised md component device - /dev/loop0
++ for args in $*
++ [[ /dev/loop1 =~ /dev/ ]]
++ [[ /dev/loop1 =~ md ]]
++ /lkp/benchmarks/mdadm-selftests/mdadm --zero /dev/loop1
mdadm: Unrecognised md component device - /dev/loop1
++ for args in $*
++ [[ /dev/loop2 =~ /dev/ ]]
++ [[ /dev/loop2 =~ md ]]
++ /lkp/benchmarks/mdadm-selftests/mdadm --zero /dev/loop2
mdadm: Unrecognised md component device - /dev/loop2
++ for args in $*
++ [[ /dev/loop3 =~ /dev/ ]]
++ [[ /dev/loop3 =~ md ]]
++ /lkp/benchmarks/mdadm-selftests/mdadm --zero /dev/loop3
mdadm: Unrecognised md component device - /dev/loop3
++ for args in $*
++ [[ /dev/loop4 =~ /dev/ ]]
++ [[ /dev/loop4 =~ md ]]
++ /lkp/benchmarks/mdadm-selftests/mdadm --zero /dev/loop4
mdadm: Unrecognised md component device - /dev/loop4
++ /lkp/benchmarks/mdadm-selftests/mdadm --quiet -CR --assume-clean /dev/md0 -l5 -n4 -x1 /dev/loop0 /dev/loop1 /dev/loop2 /dev/loop3 /dev/loop4 --auto=yes
++ rv=0
++ case $* in
++ cat /var/tmp/stderr
++ return 0
++ check raid5
++ case $1 in
++ grep -sq 'active raid5 ' /proc/mdstat
++ testdev /dev/md0 3 19992 512
++ '[' -b /dev/md0 ']'
++ '[' loop == disk ']'
++ udevadm settle
++ dev=/dev/md0
++ cnt=3
++ dvsize=19992
++ chunk=512
++ '[' -z '' ']'
++ mkfs.ext3 -F -j /dev/md0
++ fsck -fn /dev/md0
fsck from util-linux 2.38.1
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/md0: 11/13440 files (0.0% non-contiguous), 8346/53760 blocks
++ dsize=39
++ dsize=19968
++ rasize=119808
++ '[' -n '' ']'
+++ /sbin/blockdev --getsize /dev/md0
++ '[' 107520 -eq 0 ']'
+++ /sbin/blockdev --getsize /dev/md0
++ _sz=107520
++ '[' 119808 -lt 107520 -o 95846 -gt 107520 ']'
++ return 0
++ mdadm -G /dev/md0 -l 6
++ rm -f /var/tmp/stderr
++ case $* in
++ case $* in
++ /lkp/benchmarks/mdadm-selftests/mdadm --quiet -G /dev/md0 -l 6
++ rv=0
++ case $* in
++ cat /var/tmp/stderr
++ return 0
++ sleep 2
++ mdadm -S /dev/md0
++ rm -f /var/tmp/stderr
++ case $* in
++ udevadm settle
+++ cat /proc/sys/dev/raid/speed_limit_max
++ p=2000
++ echo 20000
++ case $* in
++ /lkp/benchmarks/mdadm-selftests/mdadm --quiet -S /dev/md0
++ rv=0
++ case $* in
++ udevadm settle
++ echo 2000
++ cat /var/tmp/stderr
++ return 0
++ mdadm -A /dev/md0 --update=revert-reshape /dev/loop0 /dev/loop1 /dev/loop2 /dev/loop3 /dev/loop4 --backup-file=/tmp/md-backup
++ rm -f /var/tmp/stderr
++ case $* in
++ case $* in
++ /lkp/benchmarks/mdadm-selftests/mdadm --quiet -A /dev/md0 --update=revert-reshape /dev/loop0 /dev/loop1 /dev/loop2 /dev/loop3 /dev/loop4 --backup-file=/tmp/md-backup
++ rv=1
++ case $* in
++ cat /var/tmp/stderr
mdadm: No active reshape to revert on /dev/loop0
++ return 1
++ check wait
++ case $1 in
+++ cat /proc/sys/dev/raid/speed_limit_max
++ p=2000
++ echo 2000000
++ sleep 0.1
++ grep -Eq '(resync|recovery|reshape|check|repair) *=' /proc/mdstat
++ grep -v idle '/sys/block/md*/md/sync_action'
grep: /sys/block/md*/md/sync_action: No such file or directory
++ echo 2000
++ check raid6
++ case $1 in
++ grep -sq 'active raid6 ' /proc/mdstat
++ die 'active raid6 not found'
++ echo -e '\n\tERROR: active raid6 not found \n'

	ERROR: active raid6 not found 

++ save_log fail
++ status=fail
++ logfile=fail07revert-inplace.log
++ cat /var/tmp/stderr
++ cp /var/tmp/log /var/tmp/07revert-inplace.log
++ echo '## lkp-hsw-d05: saving dmesg.'
++ dmesg -c
++ echo '## lkp-hsw-d05: saving proc mdstat.'
++ cat /proc/mdstat
++ array=($(mdadm -Ds | cut -d' ' -f2))
+++ mdadm -Ds
+++ rm -f /var/tmp/stderr
+++ cut '-d ' -f2
+++ case $* in
+++ case $* in
+++ /lkp/benchmarks/mdadm-selftests/mdadm --quiet -Ds
+++ rv=0
+++ case $* in
+++ cat /var/tmp/stderr
+++ return 0
++ '[' fail == fail ']'
++ echo 'FAILED - see /var/tmp/07revert-inplace.log and /var/tmp/fail07revert-inplace.log for details'
FAILED - see /var/tmp/07revert-inplace.log and /var/tmp/fail07revert-inplace.log for details
++ '[' loop == lvm ']'
++ '[' loop == loop -o loop == disk ']'
++ '[' '!' -z /dev/md127 -a 1 -ge 1 ']'
++ echo '## lkp-hsw-d05: mdadm -D /dev/md127'
++ /lkp/benchmarks/mdadm-selftests/mdadm -D /dev/md127
++ cat /proc/mdstat
++ grep -q 'linear\|external'
++ md_disks=($($mdadm -D -Y ${array[@]} | grep "/dev/" | cut -d'=' -f2))
+++ /lkp/benchmarks/mdadm-selftests/mdadm -D -Y /dev/md127
+++ grep /dev/
+++ cut -d= -f2
++ cat /proc/mdstat
++ grep -q bitmap
++ '[' 1 -eq 0 ']'
++ exit 2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v6 1/1] md: generate CHANGE uevents for md device
  2024-05-22  7:33 ` [PATCH v6 1/1] " Kinga Stefaniuk
  2024-05-28  8:51   ` kernel test robot
@ 2024-06-10 18:03   ` Song Liu
  2024-07-04  9:43     ` Kinga Stefaniuk
  2024-06-11  8:56   ` Yu Kuai
  2 siblings, 1 reply; 7+ messages in thread
From: Song Liu @ 2024-06-10 18:03 UTC (permalink / raw)
  To: Kinga Stefaniuk; +Cc: linux-raid

On Wed, May 22, 2024 at 12:32 AM Kinga Stefaniuk
<kinga.stefaniuk@intel.com> wrote:
>
[...]

> ---
>  drivers/md/md.c     | 47 ++++++++++++++++++++++++++++++---------------
>  drivers/md/md.h     |  2 +-
>  drivers/md/raid10.c |  2 +-
>  drivers/md/raid5.c  |  2 +-
>  4 files changed, 35 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index aff9118ff697..2ec696e17f3d 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -313,6 +313,16 @@ static int start_readonly;
>   */
>  static bool create_on_open = true;
>
> +/*
> + * Send every new event to the userspace.
> + */
> +static void trigger_kobject_uevent(struct work_struct *work)
> +{
> +       struct mddev *mddev = container_of(work, struct mddev, event_work);
> +
> +       kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
> +}
> +
>  /*
>   * We have a system wide 'event count' that is incremented
>   * on any 'interesting' event, and readers of /proc/mdstat
> @@ -325,10 +335,15 @@ static bool create_on_open = true;
>   */
>  static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
>  static atomic_t md_event_count;
> -void md_new_event(void)
> +void md_new_event(struct mddev *mddev, bool trigger_event)
>  {
>         atomic_inc(&md_event_count);
>         wake_up(&md_event_waiters);
> +
> +       if (trigger_event)
> +               kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
> +       else
> +               schedule_work(&mddev->event_work);

event_work is also used by dmraid. Will this cause an issue with dmraid?

Thanks,
Song

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v6 1/1] md: generate CHANGE uevents for md device
  2024-05-22  7:33 ` [PATCH v6 1/1] " Kinga Stefaniuk
  2024-05-28  8:51   ` kernel test robot
  2024-06-10 18:03   ` Song Liu
@ 2024-06-11  8:56   ` Yu Kuai
  2024-06-11  9:01     ` Yu Kuai
  2 siblings, 1 reply; 7+ messages in thread
From: Yu Kuai @ 2024-06-11  8:56 UTC (permalink / raw)
  To: Kinga Stefaniuk, linux-raid; +Cc: song, yukuai (C)

Hi,

Please CC me in the next version. Some nits below.

在 2024/05/22 15:33, Kinga Stefaniuk 写道:
> In mdadm commit 49b69533e8 ("mdmonitor: check if udev has finished
> events processing") mdmonitor has been learnt to wait for udev to finish
> processing, and later in commit 9935cf0f64f3 ("Mdmonitor: Improve udev
> event handling") pooling for MD events on /proc/mdstat file has been
> deprecated because relying on udev events is more reliable and less bug
> prone (we are not competing with udev).
> 
> After those changes we are still observing missing mdmonitor events in
> some scenarios, especially SpareEvent is likely to be missed. With this
> patch MD will be able to generate more change uevents and wakeup
> mdmonitor more frequently to give it possibility to notice events.
> MD has md_new_event() functionality to trigger events and with this
> patch this function is extended to generate udev CHANGE uevents. It
> cannot be done directly for md_error because this function is called on
> interrupts context, so appropriate workqueue is used. Uevents are less time
> critical, it is safe to use workqueue. It is limited to CHANGE event as
> there is no need to generate other uevents for now.
> With this change, mdmonitor events are less likely to be missed. Our
> internal tests suite confirms that, mdmonitor reliability is (again)
> improved.
> 
> Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
> Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
> 
> ---
> 
> v6: use another workqueue and only on md_error, make configurable
>      if kobject_uevent is run immediately on event or queued
> v5: fix flush_work missing and commit message fixes
> v4: add more detailed commit message
> v3: fix problems with calling function from interrupt context,
>      add work_queue and queue events notification
> v2: resolve merge conflicts with applying the patch
> Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
> ---
>   drivers/md/md.c     | 47 ++++++++++++++++++++++++++++++---------------
>   drivers/md/md.h     |  2 +-
>   drivers/md/raid10.c |  2 +-
>   drivers/md/raid5.c  |  2 +-
>   4 files changed, 35 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index aff9118ff697..2ec696e17f3d 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -313,6 +313,16 @@ static int start_readonly;
>    */
>   static bool create_on_open = true;
>   
> +/*
> + * Send every new event to the userspace.
> + */
> +static void trigger_kobject_uevent(struct work_struct *work)

I'll prefer the name md_kobject_uevent_fn().
> +{
> +	struct mddev *mddev = container_of(work, struct mddev, event_work);
> +
> +	kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
> +}
> +
>   /*
>    * We have a system wide 'event count' that is incremented
>    * on any 'interesting' event, and readers of /proc/mdstat
> @@ -325,10 +335,15 @@ static bool create_on_open = true;
>    */
>   static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
>   static atomic_t md_event_count;
> -void md_new_event(void)
> +void md_new_event(struct mddev *mddev, bool trigger_event)

You're going to send uevent anyway, the differece is sync/asyn, hence
I'll use the name 'bool sync' instead.
>   {
>   	atomic_inc(&md_event_count);
>   	wake_up(&md_event_waiters);
> +
> +	if (trigger_event)
> +		kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
> +	else
> +		schedule_work(&mddev->event_work);

As I said in the last version, please use the workqueue md_misc_wq
that is allocated by raid.
>   }
>   EXPORT_SYMBOL_GPL(md_new_event);
>   
> @@ -863,6 +878,7 @@ static void mddev_free(struct mddev *mddev)
>   	list_del(&mddev->all_mddevs);
>   	spin_unlock(&all_mddevs_lock);
>   
> +	cancel_work_sync(&mddev->event_work);

This is too late, you must cancel the work before deleting the mddev
kobject in mddev_delayed_delete().

BTW, I think is reasonable to add a kobject_del() here as well.
>   	mddev_destroy(mddev);
>   	kfree(mddev);
>   }
> @@ -2940,7 +2956,7 @@ static int add_bound_rdev(struct md_rdev *rdev)
>   	if (mddev->degraded)
>   		set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
>   	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
> -	md_new_event();
> +	md_new_event(mddev, true);
>   	return 0;
>   }
>   
> @@ -3057,7 +3073,7 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
>   				md_kick_rdev_from_array(rdev);
>   				if (mddev->pers)
>   					set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
> -				md_new_event();
> +				md_new_event(mddev, true);
>   			}
>   		}
>   	} else if (cmd_match(buf, "writemostly")) {
> @@ -4173,7 +4189,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
>   	if (!mddev->thread)
>   		md_update_sb(mddev, 1);
>   	sysfs_notify_dirent_safe(mddev->sysfs_level);
> -	md_new_event();
> +	md_new_event(mddev, true);
>   	rv = len;
>   out_unlock:
>   	mddev_unlock_and_resume(mddev);
> @@ -4700,7 +4716,7 @@ new_dev_store(struct mddev *mddev, const char *buf, size_t len)
>   		export_rdev(rdev, mddev);
>   	mddev_unlock_and_resume(mddev);
>   	if (!err)
> -		md_new_event();
> +		md_new_event(mddev, true);
>   	return err ? err : len;
>   }
>   
> @@ -5902,6 +5918,7 @@ struct mddev *md_alloc(dev_t dev, char *name)
>   		return ERR_PTR(error);
>   	}
>   
> +	INIT_WORK(&mddev->event_work, trigger_kobject_uevent);

Please add a new work struct, and add INIT_WORK() in mddev_init() with
other works.
>   	kobject_uevent(&mddev->kobj, KOBJ_ADD);
>   	mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state");
>   	mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level");
> @@ -6244,7 +6261,7 @@ int md_run(struct mddev *mddev)
>   	if (mddev->sb_flags)
>   		md_update_sb(mddev, 0);
>   
> -	md_new_event();
> +	md_new_event(mddev, true);
>   	return 0;
>   
>   bitmap_abort:
> @@ -6603,7 +6620,7 @@ static int do_md_stop(struct mddev *mddev, int mode)
>   		if (mddev->hold_active == UNTIL_STOP)
>   			mddev->hold_active = 0;
>   	}
> -	md_new_event();
> +	md_new_event(mddev, true);
>   	sysfs_notify_dirent_safe(mddev->sysfs_state);
>   	return 0;
>   }
> @@ -7099,7 +7116,7 @@ static int hot_remove_disk(struct mddev *mddev, dev_t dev)
>   	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
>   	if (!mddev->thread)
>   		md_update_sb(mddev, 1);
> -	md_new_event();
> +	md_new_event(mddev, true);
>   
>   	return 0;
>   busy:
> @@ -7179,7 +7196,7 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
>   	 * array immediately.
>   	 */
>   	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
> -	md_new_event();
> +	md_new_event(mddev, true);
>   	return 0;
>   
>   abort_export:
> @@ -8159,7 +8176,7 @@ void md_error(struct mddev *mddev, struct md_rdev *rdev)
>   	}
>   	if (mddev->event_work.func)
>   		queue_work(md_misc_wq, &mddev->event_work);
> -	md_new_event();
> +	md_new_event(mddev, false);

md_error() has lots of callers, and I'm not quite sure yet if this can
concurent with deleting mddev. Otherwise you must check if 'MD_DELETED'
is not set before queuing the new work.

Thanks,
Kuai


>   }
>   EXPORT_SYMBOL(md_error);
>   
> @@ -9049,7 +9066,7 @@ void md_do_sync(struct md_thread *thread)
>   		mddev->curr_resync = MD_RESYNC_ACTIVE; /* no longer delayed */
>   	mddev->curr_resync_completed = j;
>   	sysfs_notify_dirent_safe(mddev->sysfs_completed);
> -	md_new_event();
> +	md_new_event(mddev, true);
>   	update_time = jiffies;
>   
>   	blk_start_plug(&plug);
> @@ -9120,7 +9137,7 @@ void md_do_sync(struct md_thread *thread)
>   			/* this is the earliest that rebuild will be
>   			 * visible in /proc/mdstat
>   			 */
> -			md_new_event();
> +			md_new_event(mddev, true);
>   
>   		if (last_check + window > io_sectors || j == max_sectors)
>   			continue;
> @@ -9386,7 +9403,7 @@ static int remove_and_add_spares(struct mddev *mddev,
>   			sysfs_link_rdev(mddev, rdev);
>   			if (!test_bit(Journal, &rdev->flags))
>   				spares++;
> -			md_new_event();
> +			md_new_event(mddev, true);
>   			set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
>   		}
>   	}
> @@ -9505,7 +9522,7 @@ static void md_start_sync(struct work_struct *ws)
>   		__mddev_resume(mddev, false);
>   	md_wakeup_thread(mddev->sync_thread);
>   	sysfs_notify_dirent_safe(mddev->sysfs_action);
> -	md_new_event();
> +	md_new_event(mddev, true);
>   	return;
>   
>   not_running:
> @@ -9757,7 +9774,7 @@ void md_reap_sync_thread(struct mddev *mddev)
>   	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
>   	sysfs_notify_dirent_safe(mddev->sysfs_completed);
>   	sysfs_notify_dirent_safe(mddev->sysfs_action);
> -	md_new_event();
> +	md_new_event(mddev, true);
>   	if (mddev->event_work.func)
>   		queue_work(md_misc_wq, &mddev->event_work);
>   	wake_up(&resync_wait);
> diff --git a/drivers/md/md.h b/drivers/md/md.h
> index ca085ecad504..6c0a45d4613e 100644
> --- a/drivers/md/md.h
> +++ b/drivers/md/md.h
> @@ -803,7 +803,7 @@ extern int md_super_wait(struct mddev *mddev);
>   extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
>   		struct page *page, blk_opf_t opf, bool metadata_op);
>   extern void md_do_sync(struct md_thread *thread);
> -extern void md_new_event(void);
> +extern void md_new_event(struct mddev *mddev, bool trigger_event);
>   extern void md_allow_write(struct mddev *mddev);
>   extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
>   extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
> diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
> index a4556d2e46bf..4f4adbe5da95 100644
> --- a/drivers/md/raid10.c
> +++ b/drivers/md/raid10.c
> @@ -4545,7 +4545,7 @@ static int raid10_start_reshape(struct mddev *mddev)
>   	set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
>   	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
>   	conf->reshape_checkpoint = jiffies;
> -	md_new_event();
> +	md_new_event(mddev, true);
>   	return 0;
>   
>   abort:
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index 2bd1ce9b3922..085206f1cdcc 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -8503,7 +8503,7 @@ static int raid5_start_reshape(struct mddev *mddev)
>   	set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
>   	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
>   	conf->reshape_checkpoint = jiffies;
> -	md_new_event();
> +	md_new_event(mddev, true);
>   	return 0;
>   }
>   
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v6 1/1] md: generate CHANGE uevents for md device
  2024-06-11  8:56   ` Yu Kuai
@ 2024-06-11  9:01     ` Yu Kuai
  0 siblings, 0 replies; 7+ messages in thread
From: Yu Kuai @ 2024-06-11  9:01 UTC (permalink / raw)
  To: Yu Kuai, Kinga Stefaniuk, linux-raid; +Cc: song, yukuai (C)

Hi,

在 2024/06/11 16:56, Yu Kuai 写道:
> Hi,
> 
> Please CC me in the next version. Some nits below.
> 
> 在 2024/05/22 15:33, Kinga Stefaniuk 写道:
>> In mdadm commit 49b69533e8 ("mdmonitor: check if udev has finished
>> events processing") mdmonitor has been learnt to wait for udev to finish
>> processing, and later in commit 9935cf0f64f3 ("Mdmonitor: Improve udev
>> event handling") pooling for MD events on /proc/mdstat file has been
>> deprecated because relying on udev events is more reliable and less bug
>> prone (we are not competing with udev).
>>
>> After those changes we are still observing missing mdmonitor events in
>> some scenarios, especially SpareEvent is likely to be missed. With this
>> patch MD will be able to generate more change uevents and wakeup
>> mdmonitor more frequently to give it possibility to notice events.
>> MD has md_new_event() functionality to trigger events and with this
>> patch this function is extended to generate udev CHANGE uevents. It
>> cannot be done directly for md_error because this function is called on
>> interrupts context, so appropriate workqueue is used. Uevents are less 
>> time
>> critical, it is safe to use workqueue. It is limited to CHANGE event as
>> there is no need to generate other uevents for now.
>> With this change, mdmonitor events are less likely to be missed. Our
>> internal tests suite confirms that, mdmonitor reliability is (again)
>> improved.
>>
>> Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
>> Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
>>
>> ---
>>
>> v6: use another workqueue and only on md_error, make configurable
>>      if kobject_uevent is run immediately on event or queued
>> v5: fix flush_work missing and commit message fixes
>> v4: add more detailed commit message
>> v3: fix problems with calling function from interrupt context,
>>      add work_queue and queue events notification
>> v2: resolve merge conflicts with applying the patch
>> Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
>> ---
>>   drivers/md/md.c     | 47 ++++++++++++++++++++++++++++++---------------
>>   drivers/md/md.h     |  2 +-
>>   drivers/md/raid10.c |  2 +-
>>   drivers/md/raid5.c  |  2 +-
>>   4 files changed, 35 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/md/md.c b/drivers/md/md.c
>> index aff9118ff697..2ec696e17f3d 100644
>> --- a/drivers/md/md.c
>> +++ b/drivers/md/md.c
>> @@ -313,6 +313,16 @@ static int start_readonly;
>>    */
>>   static bool create_on_open = true;
>> +/*
>> + * Send every new event to the userspace.
>> + */
>> +static void trigger_kobject_uevent(struct work_struct *work)
> 
> I'll prefer the name md_kobject_uevent_fn().
>> +{
>> +    struct mddev *mddev = container_of(work, struct mddev, event_work);
>> +
>> +    kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
>> +}
>> +
>>   /*
>>    * We have a system wide 'event count' that is incremented
>>    * on any 'interesting' event, and readers of /proc/mdstat
>> @@ -325,10 +335,15 @@ static bool create_on_open = true;
>>    */
>>   static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
>>   static atomic_t md_event_count;
>> -void md_new_event(void)
>> +void md_new_event(struct mddev *mddev, bool trigger_event)
> 
> You're going to send uevent anyway, the differece is sync/asyn, hence
> I'll use the name 'bool sync' instead.
>>   {
>>       atomic_inc(&md_event_count);
>>       wake_up(&md_event_waiters);
>> +
>> +    if (trigger_event)
>> +        kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
>> +    else
>> +        schedule_work(&mddev->event_work);

And for dm-raid, mddev->kobj is never initialized, you can't use it for
dm-raid(mddev_is_dm()).

Thanks,
Kuai

> 
> As I said in the last version, please use the workqueue md_misc_wq
> that is allocated by raid.
>>   }
>>   EXPORT_SYMBOL_GPL(md_new_event);
>> @@ -863,6 +878,7 @@ static void mddev_free(struct mddev *mddev)
>>       list_del(&mddev->all_mddevs);
>>       spin_unlock(&all_mddevs_lock);
>> +    cancel_work_sync(&mddev->event_work);
> 
> This is too late, you must cancel the work before deleting the mddev
> kobject in mddev_delayed_delete().
> 
> BTW, I think is reasonable to add a kobject_del() here as well.
>>       mddev_destroy(mddev);
>>       kfree(mddev);
>>   }
>> @@ -2940,7 +2956,7 @@ static int add_bound_rdev(struct md_rdev *rdev)
>>       if (mddev->degraded)
>>           set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
>>       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       return 0;
>>   }
>> @@ -3057,7 +3073,7 @@ state_store(struct md_rdev *rdev, const char 
>> *buf, size_t len)
>>                   md_kick_rdev_from_array(rdev);
>>                   if (mddev->pers)
>>                       set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
>> -                md_new_event();
>> +                md_new_event(mddev, true);
>>               }
>>           }
>>       } else if (cmd_match(buf, "writemostly")) {
>> @@ -4173,7 +4189,7 @@ level_store(struct mddev *mddev, const char 
>> *buf, size_t len)
>>       if (!mddev->thread)
>>           md_update_sb(mddev, 1);
>>       sysfs_notify_dirent_safe(mddev->sysfs_level);
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       rv = len;
>>   out_unlock:
>>       mddev_unlock_and_resume(mddev);
>> @@ -4700,7 +4716,7 @@ new_dev_store(struct mddev *mddev, const char 
>> *buf, size_t len)
>>           export_rdev(rdev, mddev);
>>       mddev_unlock_and_resume(mddev);
>>       if (!err)
>> -        md_new_event();
>> +        md_new_event(mddev, true);
>>       return err ? err : len;
>>   }
>> @@ -5902,6 +5918,7 @@ struct mddev *md_alloc(dev_t dev, char *name)
>>           return ERR_PTR(error);
>>       }
>> +    INIT_WORK(&mddev->event_work, trigger_kobject_uevent);
> 
> Please add a new work struct, and add INIT_WORK() in mddev_init() with
> other works.
>>       kobject_uevent(&mddev->kobj, KOBJ_ADD);
>>       mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, 
>> "array_state");
>>       mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, 
>> "level");
>> @@ -6244,7 +6261,7 @@ int md_run(struct mddev *mddev)
>>       if (mddev->sb_flags)
>>           md_update_sb(mddev, 0);
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       return 0;
>>   bitmap_abort:
>> @@ -6603,7 +6620,7 @@ static int do_md_stop(struct mddev *mddev, int 
>> mode)
>>           if (mddev->hold_active == UNTIL_STOP)
>>               mddev->hold_active = 0;
>>       }
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       sysfs_notify_dirent_safe(mddev->sysfs_state);
>>       return 0;
>>   }
>> @@ -7099,7 +7116,7 @@ static int hot_remove_disk(struct mddev *mddev, 
>> dev_t dev)
>>       set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
>>       if (!mddev->thread)
>>           md_update_sb(mddev, 1);
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       return 0;
>>   busy:
>> @@ -7179,7 +7196,7 @@ static int hot_add_disk(struct mddev *mddev, 
>> dev_t dev)
>>        * array immediately.
>>        */
>>       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       return 0;
>>   abort_export:
>> @@ -8159,7 +8176,7 @@ void md_error(struct mddev *mddev, struct 
>> md_rdev *rdev)
>>       }
>>       if (mddev->event_work.func)
>>           queue_work(md_misc_wq, &mddev->event_work);
>> -    md_new_event();
>> +    md_new_event(mddev, false);
> 
> md_error() has lots of callers, and I'm not quite sure yet if this can
> concurent with deleting mddev. Otherwise you must check if 'MD_DELETED'
> is not set before queuing the new work.
> 
> Thanks,
> Kuai
> 
> 
>>   }
>>   EXPORT_SYMBOL(md_error);
>> @@ -9049,7 +9066,7 @@ void md_do_sync(struct md_thread *thread)
>>           mddev->curr_resync = MD_RESYNC_ACTIVE; /* no longer delayed */
>>       mddev->curr_resync_completed = j;
>>       sysfs_notify_dirent_safe(mddev->sysfs_completed);
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       update_time = jiffies;
>>       blk_start_plug(&plug);
>> @@ -9120,7 +9137,7 @@ void md_do_sync(struct md_thread *thread)
>>               /* this is the earliest that rebuild will be
>>                * visible in /proc/mdstat
>>                */
>> -            md_new_event();
>> +            md_new_event(mddev, true);
>>           if (last_check + window > io_sectors || j == max_sectors)
>>               continue;
>> @@ -9386,7 +9403,7 @@ static int remove_and_add_spares(struct mddev 
>> *mddev,
>>               sysfs_link_rdev(mddev, rdev);
>>               if (!test_bit(Journal, &rdev->flags))
>>                   spares++;
>> -            md_new_event();
>> +            md_new_event(mddev, true);
>>               set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
>>           }
>>       }
>> @@ -9505,7 +9522,7 @@ static void md_start_sync(struct work_struct *ws)
>>           __mddev_resume(mddev, false);
>>       md_wakeup_thread(mddev->sync_thread);
>>       sysfs_notify_dirent_safe(mddev->sysfs_action);
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       return;
>>   not_running:
>> @@ -9757,7 +9774,7 @@ void md_reap_sync_thread(struct mddev *mddev)
>>       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
>>       sysfs_notify_dirent_safe(mddev->sysfs_completed);
>>       sysfs_notify_dirent_safe(mddev->sysfs_action);
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       if (mddev->event_work.func)
>>           queue_work(md_misc_wq, &mddev->event_work);
>>       wake_up(&resync_wait);
>> diff --git a/drivers/md/md.h b/drivers/md/md.h
>> index ca085ecad504..6c0a45d4613e 100644
>> --- a/drivers/md/md.h
>> +++ b/drivers/md/md.h
>> @@ -803,7 +803,7 @@ extern int md_super_wait(struct mddev *mddev);
>>   extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int 
>> size,
>>           struct page *page, blk_opf_t opf, bool metadata_op);
>>   extern void md_do_sync(struct md_thread *thread);
>> -extern void md_new_event(void);
>> +extern void md_new_event(struct mddev *mddev, bool trigger_event);
>>   extern void md_allow_write(struct mddev *mddev);
>>   extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct 
>> mddev *mddev);
>>   extern void md_set_array_sectors(struct mddev *mddev, sector_t 
>> array_sectors);
>> diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
>> index a4556d2e46bf..4f4adbe5da95 100644
>> --- a/drivers/md/raid10.c
>> +++ b/drivers/md/raid10.c
>> @@ -4545,7 +4545,7 @@ static int raid10_start_reshape(struct mddev 
>> *mddev)
>>       set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
>>       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
>>       conf->reshape_checkpoint = jiffies;
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       return 0;
>>   abort:
>> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
>> index 2bd1ce9b3922..085206f1cdcc 100644
>> --- a/drivers/md/raid5.c
>> +++ b/drivers/md/raid5.c
>> @@ -8503,7 +8503,7 @@ static int raid5_start_reshape(struct mddev *mddev)
>>       set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
>>       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
>>       conf->reshape_checkpoint = jiffies;
>> -    md_new_event();
>> +    md_new_event(mddev, true);
>>       return 0;
>>   }
>>
> 
> .
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v6 1/1] md: generate CHANGE uevents for md device
  2024-06-10 18:03   ` Song Liu
@ 2024-07-04  9:43     ` Kinga Stefaniuk
  0 siblings, 0 replies; 7+ messages in thread
From: Kinga Stefaniuk @ 2024-07-04  9:43 UTC (permalink / raw)
  To: Song Liu; +Cc: Kinga Stefaniuk, linux-raid

On Mon, 10 Jun 2024 11:03:25 -0700
Song Liu <song@kernel.org> wrote:

> On Wed, May 22, 2024 at 12:32 AM Kinga Stefaniuk
> <kinga.stefaniuk@intel.com> wrote:
> >  
> [...]
> 
> > ---
> >  drivers/md/md.c     | 47
> > ++++++++++++++++++++++++++++++--------------- drivers/md/md.h     |
> >  2 +- drivers/md/raid10.c |  2 +-
> >  drivers/md/raid5.c  |  2 +-
> >  4 files changed, 35 insertions(+), 18 deletions(-)
> >
> > diff --git a/drivers/md/md.c b/drivers/md/md.c
> > index aff9118ff697..2ec696e17f3d 100644
> > --- a/drivers/md/md.c
> > +++ b/drivers/md/md.c
> > @@ -313,6 +313,16 @@ static int start_readonly;
> >   */
> >  static bool create_on_open = true;
> >
> > +/*
> > + * Send every new event to the userspace.
> > + */
> > +static void trigger_kobject_uevent(struct work_struct *work)
> > +{
> > +       struct mddev *mddev = container_of(work, struct mddev,
> > event_work); +
> > +       kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj,
> > KOBJ_CHANGE); +}
> > +
> >  /*
> >   * We have a system wide 'event count' that is incremented
> >   * on any 'interesting' event, and readers of /proc/mdstat
> > @@ -325,10 +335,15 @@ static bool create_on_open = true;
> >   */
> >  static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
> >  static atomic_t md_event_count;
> > -void md_new_event(void)
> > +void md_new_event(struct mddev *mddev, bool trigger_event)
> >  {
> >         atomic_inc(&md_event_count);
> >         wake_up(&md_event_waiters);
> > +
> > +       if (trigger_event)
> > +               kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj,
> > KOBJ_CHANGE);
> > +       else
> > +               schedule_work(&mddev->event_work);  
> 
> event_work is also used by dmraid. Will this cause an issue with
> dmraid?
> 
> Thanks,
> Song
> 

Hi Song,

yes, you're right. It is fixed in next patchset - new work_struct
uevent_work was added.

Regards,
Kinga

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-07-04  9:43 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-22  7:33 [PATCH v6 0/1] md: generate CHANGE uevents for md device Kinga Stefaniuk
2024-05-22  7:33 ` [PATCH v6 1/1] " Kinga Stefaniuk
2024-05-28  8:51   ` kernel test robot
2024-06-10 18:03   ` Song Liu
2024-07-04  9:43     ` Kinga Stefaniuk
2024-06-11  8:56   ` Yu Kuai
2024-06-11  9:01     ` Yu Kuai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).