From: Sasha Levin Date: Wed, 29 Nov 2023 18:18:36 +0000 (-0500) Subject: Drop dm-delay-for-short-delays-use-kthread-instead-of-tim.patch X-Git-Tag: v5.15.141~38 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2a734d1f22b37b9010e32f51f51b4f50d5fa43c6;p=thirdparty%2Fkernel%2Fstable-queue.git Drop dm-delay-for-short-delays-use-kthread-instead-of-tim.patch Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/dm-delay-for-short-delays-use-kthread-instead-of-tim.patch b/queue-6.1/dm-delay-for-short-delays-use-kthread-instead-of-tim.patch deleted file mode 100644 index 54ea8ed6221..00000000000 --- a/queue-6.1/dm-delay-for-short-delays-use-kthread-instead-of-tim.patch +++ /dev/null @@ -1,290 +0,0 @@ -From 8fc3662c0d81119ae3a7c3fc1c2cd441c3054905 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 20 Oct 2023 12:46:05 +0100 -Subject: dm delay: for short delays, use kthread instead of timers and wq - -From: Christian Loehle - -[ Upstream commit 70bbeb29fab09d6ea6cfe64109db60a97d84d739 ] - -DM delay's current design of using timers and wq to realize the delays -is insufficient for delays below ~50ms. - -This commit enhances the design to use a kthread to flush the expired -delays, trading some CPU time (in some cases) for better delay -accuracy and delays closer to what the user requested for smaller -delays. The new design is chosen as long as all the delays are below -50ms. - -Since bios can't be completed in interrupt context using a kthread -is probably the most reasonable way to approach this. - -Testing with -echo "0 2097152 zero" | dmsetup create dm-zeros -for i in $(seq 0 20); -do - echo "0 2097152 delay /dev/mapper/dm-zeros 0 $i" | dmsetup create dm-delay-${i}ms; -done - -Some performance numbers for comparison, on beaglebone black (single -core) CONFIG_HZ_1000=y: - -fio --name=1msread --rw=randread --bs=4k --runtime=60 --time_based \ - --filename=/dev/mapper/dm-delay-1ms -Theoretical maximum: 1000 IOPS -Previous: 250 IOPS -Kthread: 500 IOPS - -fio --name=10msread --rw=randread --bs=4k --runtime=60 --time_based \ - --filename=/dev/mapper/dm-delay-10ms -Theoretical maximum: 100 IOPS -Previous: 45 IOPS -Kthread: 50 IOPS - -fio --name=1mswrite --rw=randwrite --direct=1 --bs=4k --runtime=60 \ - --time_based --filename=/dev/mapper/dm-delay-1ms -Theoretical maximum: 1000 IOPS -Previous: 498 IOPS -Kthread: 1000 IOPS - -fio --name=10mswrite --rw=randwrite --direct=1 --bs=4k --runtime=60 \ - --time_based --filename=/dev/mapper/dm-delay-10ms -Theoretical maximum: 100 IOPS -Previous: 90 IOPS -Kthread: 100 IOPS - -(This one is just to prove the new design isn't impacting throughput, -not really about delays): -fio --name=10mswriteasync --rw=randwrite --direct=1 --bs=4k \ - --runtime=60 --time_based --filename=/dev/mapper/dm-delay-10ms \ - --numjobs=32 --iodepth=64 --ioengine=libaio --group_reporting -Previous: 13.3k IOPS -Kthread: 13.3k IOPS - -Signed-off-by: Christian Loehle -[Harshit: kthread_create error handling fix in delay_ctr] -Signed-off-by: Harshit Mogalapalli -Signed-off-by: Mike Snitzer -Stable-dep-of: 6fc45b6ed921 ("dm-delay: fix a race between delay_presuspend and delay_bio") -Signed-off-by: Sasha Levin ---- - drivers/md/dm-delay.c | 103 ++++++++++++++++++++++++++++++++++++------ - 1 file changed, 88 insertions(+), 15 deletions(-) - -diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c -index 02b8f4e818276..358e870a03a56 100644 ---- a/drivers/md/dm-delay.c -+++ b/drivers/md/dm-delay.c -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - - #include - -@@ -30,6 +31,7 @@ struct delay_c { - struct workqueue_struct *kdelayd_wq; - struct work_struct flush_expired_bios; - struct list_head delayed_bios; -+ struct task_struct *worker; - atomic_t may_delay; - - struct delay_class read; -@@ -65,6 +67,44 @@ static void queue_timeout(struct delay_c *dc, unsigned long expires) - mutex_unlock(&dc->timer_lock); - } - -+static inline bool delay_is_fast(struct delay_c *dc) -+{ -+ return !!dc->worker; -+} -+ -+static void flush_delayed_bios_fast(struct delay_c *dc, bool flush_all) -+{ -+ struct dm_delay_info *delayed, *next; -+ -+ mutex_lock(&delayed_bios_lock); -+ list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) { -+ if (flush_all || time_after_eq(jiffies, delayed->expires)) { -+ struct bio *bio = dm_bio_from_per_bio_data(delayed, -+ sizeof(struct dm_delay_info)); -+ list_del(&delayed->list); -+ dm_submit_bio_remap(bio, NULL); -+ delayed->class->ops--; -+ } -+ } -+ mutex_unlock(&delayed_bios_lock); -+} -+ -+static int flush_worker_fn(void *data) -+{ -+ struct delay_c *dc = data; -+ -+ while (1) { -+ flush_delayed_bios_fast(dc, false); -+ if (unlikely(list_empty(&dc->delayed_bios))) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule(); -+ } else -+ cond_resched(); -+ } -+ -+ return 0; -+} -+ - static void flush_bios(struct bio *bio) - { - struct bio *n; -@@ -77,7 +117,7 @@ static void flush_bios(struct bio *bio) - } - } - --static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all) -+static struct bio *flush_delayed_bios(struct delay_c *dc, bool flush_all) - { - struct dm_delay_info *delayed, *next; - unsigned long next_expires = 0; -@@ -114,7 +154,10 @@ static void flush_expired_bios(struct work_struct *work) - struct delay_c *dc; - - dc = container_of(work, struct delay_c, flush_expired_bios); -- flush_bios(flush_delayed_bios(dc, 0)); -+ if (delay_is_fast(dc)) -+ flush_delayed_bios_fast(dc, false); -+ else -+ flush_bios(flush_delayed_bios(dc, false)); - } - - static void delay_dtr(struct dm_target *ti) -@@ -130,8 +173,11 @@ static void delay_dtr(struct dm_target *ti) - dm_put_device(ti, dc->write.dev); - if (dc->flush.dev) - dm_put_device(ti, dc->flush.dev); -+ if (dc->worker) -+ kthread_stop(dc->worker); - -- mutex_destroy(&dc->timer_lock); -+ if (!delay_is_fast(dc)) -+ mutex_destroy(&dc->timer_lock); - - kfree(dc); - } -@@ -174,6 +220,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) - { - struct delay_c *dc; - int ret; -+ unsigned int max_delay; - - if (argc != 3 && argc != 6 && argc != 9) { - ti->error = "Requires exactly 3, 6 or 9 arguments"; -@@ -187,16 +234,14 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) - } - - ti->private = dc; -- timer_setup(&dc->delay_timer, handle_delayed_timer, 0); -- INIT_WORK(&dc->flush_expired_bios, flush_expired_bios); - INIT_LIST_HEAD(&dc->delayed_bios); -- mutex_init(&dc->timer_lock); - atomic_set(&dc->may_delay, 1); - dc->argc = argc; - - ret = delay_class_ctr(ti, &dc->read, argv); - if (ret) - goto bad; -+ max_delay = dc->read.delay; - - if (argc == 3) { - ret = delay_class_ctr(ti, &dc->write, argv); -@@ -205,6 +250,8 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) - ret = delay_class_ctr(ti, &dc->flush, argv); - if (ret) - goto bad; -+ max_delay = max(max_delay, dc->write.delay); -+ max_delay = max(max_delay, dc->flush.delay); - goto out; - } - -@@ -215,19 +262,37 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) - ret = delay_class_ctr(ti, &dc->flush, argv + 3); - if (ret) - goto bad; -+ max_delay = max(max_delay, dc->flush.delay); - goto out; - } - - ret = delay_class_ctr(ti, &dc->flush, argv + 6); - if (ret) - goto bad; -+ max_delay = max(max_delay, dc->flush.delay); - - out: -- dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0); -- if (!dc->kdelayd_wq) { -- ret = -EINVAL; -- DMERR("Couldn't start kdelayd"); -- goto bad; -+ if (max_delay < 50) { -+ /* -+ * In case of small requested delays, use kthread instead of -+ * timers and workqueue to achieve better latency. -+ */ -+ dc->worker = kthread_create(&flush_worker_fn, dc, -+ "dm-delay-flush-worker"); -+ if (IS_ERR(dc->worker)) { -+ ret = PTR_ERR(dc->worker); -+ goto bad; -+ } -+ } else { -+ timer_setup(&dc->delay_timer, handle_delayed_timer, 0); -+ INIT_WORK(&dc->flush_expired_bios, flush_expired_bios); -+ mutex_init(&dc->timer_lock); -+ dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0); -+ if (!dc->kdelayd_wq) { -+ ret = -EINVAL; -+ DMERR("Couldn't start kdelayd"); -+ goto bad; -+ } - } - - ti->num_flush_bios = 1; -@@ -259,7 +324,10 @@ static int delay_bio(struct delay_c *dc, struct delay_class *c, struct bio *bio) - list_add_tail(&delayed->list, &dc->delayed_bios); - mutex_unlock(&delayed_bios_lock); - -- queue_timeout(dc, expires); -+ if (delay_is_fast(dc)) -+ wake_up_process(dc->worker); -+ else -+ queue_timeout(dc, expires); - - return DM_MAPIO_SUBMITTED; - } -@@ -269,8 +337,13 @@ static void delay_presuspend(struct dm_target *ti) - struct delay_c *dc = ti->private; - - atomic_set(&dc->may_delay, 0); -- del_timer_sync(&dc->delay_timer); -- flush_bios(flush_delayed_bios(dc, 1)); -+ -+ if (delay_is_fast(dc)) -+ flush_delayed_bios_fast(dc, true); -+ else { -+ del_timer_sync(&dc->delay_timer); -+ flush_bios(flush_delayed_bios(dc, true)); -+ } - } - - static void delay_resume(struct dm_target *ti) -@@ -355,7 +428,7 @@ static int delay_iterate_devices(struct dm_target *ti, - - static struct target_type delay_target = { - .name = "delay", -- .version = {1, 3, 0}, -+ .version = {1, 4, 0}, - .features = DM_TARGET_PASSES_INTEGRITY, - .module = THIS_MODULE, - .ctr = delay_ctr, --- -2.42.0 - diff --git a/queue-6.1/series b/queue-6.1/series index 406eb192bd0..4821650be22 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -36,7 +36,6 @@ cifs-distribute-channels-across-interfaces-based-on-.patch cifs-account-for-primary-channel-in-the-interface-li.patch cifs-fix-leak-of-iface-for-primary-channel.patch mips-kvm-fix-a-build-warning-about-variable-set-but-.patch -dm-delay-for-short-delays-use-kthread-instead-of-tim.patch dm-delay-fix-a-race-between-delay_presuspend-and-del.patch media-camss-split-power-domain-management.patch media-camss-convert-to-platform-remove-callback-retu.patch diff --git a/queue-6.6/dm-delay-for-short-delays-use-kthread-instead-of-tim.patch b/queue-6.6/dm-delay-for-short-delays-use-kthread-instead-of-tim.patch deleted file mode 100644 index 7b64485fc31..00000000000 --- a/queue-6.6/dm-delay-for-short-delays-use-kthread-instead-of-tim.patch +++ /dev/null @@ -1,290 +0,0 @@ -From 976fd593415e170a8ed5db68683b280d5876982d Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 20 Oct 2023 12:46:05 +0100 -Subject: dm delay: for short delays, use kthread instead of timers and wq - -From: Christian Loehle - -[ Upstream commit 70bbeb29fab09d6ea6cfe64109db60a97d84d739 ] - -DM delay's current design of using timers and wq to realize the delays -is insufficient for delays below ~50ms. - -This commit enhances the design to use a kthread to flush the expired -delays, trading some CPU time (in some cases) for better delay -accuracy and delays closer to what the user requested for smaller -delays. The new design is chosen as long as all the delays are below -50ms. - -Since bios can't be completed in interrupt context using a kthread -is probably the most reasonable way to approach this. - -Testing with -echo "0 2097152 zero" | dmsetup create dm-zeros -for i in $(seq 0 20); -do - echo "0 2097152 delay /dev/mapper/dm-zeros 0 $i" | dmsetup create dm-delay-${i}ms; -done - -Some performance numbers for comparison, on beaglebone black (single -core) CONFIG_HZ_1000=y: - -fio --name=1msread --rw=randread --bs=4k --runtime=60 --time_based \ - --filename=/dev/mapper/dm-delay-1ms -Theoretical maximum: 1000 IOPS -Previous: 250 IOPS -Kthread: 500 IOPS - -fio --name=10msread --rw=randread --bs=4k --runtime=60 --time_based \ - --filename=/dev/mapper/dm-delay-10ms -Theoretical maximum: 100 IOPS -Previous: 45 IOPS -Kthread: 50 IOPS - -fio --name=1mswrite --rw=randwrite --direct=1 --bs=4k --runtime=60 \ - --time_based --filename=/dev/mapper/dm-delay-1ms -Theoretical maximum: 1000 IOPS -Previous: 498 IOPS -Kthread: 1000 IOPS - -fio --name=10mswrite --rw=randwrite --direct=1 --bs=4k --runtime=60 \ - --time_based --filename=/dev/mapper/dm-delay-10ms -Theoretical maximum: 100 IOPS -Previous: 90 IOPS -Kthread: 100 IOPS - -(This one is just to prove the new design isn't impacting throughput, -not really about delays): -fio --name=10mswriteasync --rw=randwrite --direct=1 --bs=4k \ - --runtime=60 --time_based --filename=/dev/mapper/dm-delay-10ms \ - --numjobs=32 --iodepth=64 --ioengine=libaio --group_reporting -Previous: 13.3k IOPS -Kthread: 13.3k IOPS - -Signed-off-by: Christian Loehle -[Harshit: kthread_create error handling fix in delay_ctr] -Signed-off-by: Harshit Mogalapalli -Signed-off-by: Mike Snitzer -Stable-dep-of: 6fc45b6ed921 ("dm-delay: fix a race between delay_presuspend and delay_bio") -Signed-off-by: Sasha Levin ---- - drivers/md/dm-delay.c | 103 ++++++++++++++++++++++++++++++++++++------ - 1 file changed, 88 insertions(+), 15 deletions(-) - -diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c -index 7433525e59856..efd510984e259 100644 ---- a/drivers/md/dm-delay.c -+++ b/drivers/md/dm-delay.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #include - -@@ -31,6 +32,7 @@ struct delay_c { - struct workqueue_struct *kdelayd_wq; - struct work_struct flush_expired_bios; - struct list_head delayed_bios; -+ struct task_struct *worker; - atomic_t may_delay; - - struct delay_class read; -@@ -66,6 +68,44 @@ static void queue_timeout(struct delay_c *dc, unsigned long expires) - mutex_unlock(&dc->timer_lock); - } - -+static inline bool delay_is_fast(struct delay_c *dc) -+{ -+ return !!dc->worker; -+} -+ -+static void flush_delayed_bios_fast(struct delay_c *dc, bool flush_all) -+{ -+ struct dm_delay_info *delayed, *next; -+ -+ mutex_lock(&delayed_bios_lock); -+ list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) { -+ if (flush_all || time_after_eq(jiffies, delayed->expires)) { -+ struct bio *bio = dm_bio_from_per_bio_data(delayed, -+ sizeof(struct dm_delay_info)); -+ list_del(&delayed->list); -+ dm_submit_bio_remap(bio, NULL); -+ delayed->class->ops--; -+ } -+ } -+ mutex_unlock(&delayed_bios_lock); -+} -+ -+static int flush_worker_fn(void *data) -+{ -+ struct delay_c *dc = data; -+ -+ while (1) { -+ flush_delayed_bios_fast(dc, false); -+ if (unlikely(list_empty(&dc->delayed_bios))) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule(); -+ } else -+ cond_resched(); -+ } -+ -+ return 0; -+} -+ - static void flush_bios(struct bio *bio) - { - struct bio *n; -@@ -78,7 +118,7 @@ static void flush_bios(struct bio *bio) - } - } - --static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all) -+static struct bio *flush_delayed_bios(struct delay_c *dc, bool flush_all) - { - struct dm_delay_info *delayed, *next; - unsigned long next_expires = 0; -@@ -115,7 +155,10 @@ static void flush_expired_bios(struct work_struct *work) - struct delay_c *dc; - - dc = container_of(work, struct delay_c, flush_expired_bios); -- flush_bios(flush_delayed_bios(dc, 0)); -+ if (delay_is_fast(dc)) -+ flush_delayed_bios_fast(dc, false); -+ else -+ flush_bios(flush_delayed_bios(dc, false)); - } - - static void delay_dtr(struct dm_target *ti) -@@ -131,8 +174,11 @@ static void delay_dtr(struct dm_target *ti) - dm_put_device(ti, dc->write.dev); - if (dc->flush.dev) - dm_put_device(ti, dc->flush.dev); -+ if (dc->worker) -+ kthread_stop(dc->worker); - -- mutex_destroy(&dc->timer_lock); -+ if (!delay_is_fast(dc)) -+ mutex_destroy(&dc->timer_lock); - - kfree(dc); - } -@@ -175,6 +221,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) - { - struct delay_c *dc; - int ret; -+ unsigned int max_delay; - - if (argc != 3 && argc != 6 && argc != 9) { - ti->error = "Requires exactly 3, 6 or 9 arguments"; -@@ -188,16 +235,14 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) - } - - ti->private = dc; -- timer_setup(&dc->delay_timer, handle_delayed_timer, 0); -- INIT_WORK(&dc->flush_expired_bios, flush_expired_bios); - INIT_LIST_HEAD(&dc->delayed_bios); -- mutex_init(&dc->timer_lock); - atomic_set(&dc->may_delay, 1); - dc->argc = argc; - - ret = delay_class_ctr(ti, &dc->read, argv); - if (ret) - goto bad; -+ max_delay = dc->read.delay; - - if (argc == 3) { - ret = delay_class_ctr(ti, &dc->write, argv); -@@ -206,6 +251,8 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) - ret = delay_class_ctr(ti, &dc->flush, argv); - if (ret) - goto bad; -+ max_delay = max(max_delay, dc->write.delay); -+ max_delay = max(max_delay, dc->flush.delay); - goto out; - } - -@@ -216,19 +263,37 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) - ret = delay_class_ctr(ti, &dc->flush, argv + 3); - if (ret) - goto bad; -+ max_delay = max(max_delay, dc->flush.delay); - goto out; - } - - ret = delay_class_ctr(ti, &dc->flush, argv + 6); - if (ret) - goto bad; -+ max_delay = max(max_delay, dc->flush.delay); - - out: -- dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0); -- if (!dc->kdelayd_wq) { -- ret = -EINVAL; -- DMERR("Couldn't start kdelayd"); -- goto bad; -+ if (max_delay < 50) { -+ /* -+ * In case of small requested delays, use kthread instead of -+ * timers and workqueue to achieve better latency. -+ */ -+ dc->worker = kthread_create(&flush_worker_fn, dc, -+ "dm-delay-flush-worker"); -+ if (IS_ERR(dc->worker)) { -+ ret = PTR_ERR(dc->worker); -+ goto bad; -+ } -+ } else { -+ timer_setup(&dc->delay_timer, handle_delayed_timer, 0); -+ INIT_WORK(&dc->flush_expired_bios, flush_expired_bios); -+ mutex_init(&dc->timer_lock); -+ dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0); -+ if (!dc->kdelayd_wq) { -+ ret = -EINVAL; -+ DMERR("Couldn't start kdelayd"); -+ goto bad; -+ } - } - - ti->num_flush_bios = 1; -@@ -260,7 +325,10 @@ static int delay_bio(struct delay_c *dc, struct delay_class *c, struct bio *bio) - list_add_tail(&delayed->list, &dc->delayed_bios); - mutex_unlock(&delayed_bios_lock); - -- queue_timeout(dc, expires); -+ if (delay_is_fast(dc)) -+ wake_up_process(dc->worker); -+ else -+ queue_timeout(dc, expires); - - return DM_MAPIO_SUBMITTED; - } -@@ -270,8 +338,13 @@ static void delay_presuspend(struct dm_target *ti) - struct delay_c *dc = ti->private; - - atomic_set(&dc->may_delay, 0); -- del_timer_sync(&dc->delay_timer); -- flush_bios(flush_delayed_bios(dc, 1)); -+ -+ if (delay_is_fast(dc)) -+ flush_delayed_bios_fast(dc, true); -+ else { -+ del_timer_sync(&dc->delay_timer); -+ flush_bios(flush_delayed_bios(dc, true)); -+ } - } - - static void delay_resume(struct dm_target *ti) -@@ -356,7 +429,7 @@ static int delay_iterate_devices(struct dm_target *ti, - - static struct target_type delay_target = { - .name = "delay", -- .version = {1, 3, 0}, -+ .version = {1, 4, 0}, - .features = DM_TARGET_PASSES_INTEGRITY, - .module = THIS_MODULE, - .ctr = delay_ctr, --- -2.42.0 - diff --git a/queue-6.6/series b/queue-6.6/series index 6b461b0c227..abb5f6f37c5 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -59,5 +59,4 @@ cifs-account-for-primary-channel-in-the-interface-li.patch cifs-fix-leak-of-iface-for-primary-channel.patch alsa-hda-asus-um5302la-added-quirks-for-cs35l41-1043.patch alsa-hda-realtek-add-quirks-for-asus-2024-zenbooks.patch -dm-delay-for-short-delays-use-kthread-instead-of-tim.patch dm-delay-fix-a-race-between-delay_presuspend-and-del.patch