From: Sasha Levin Date: Fri, 23 Aug 2024 00:12:56 +0000 (-0400) Subject: Fixes for 5.4 X-Git-Tag: v6.1.107~77 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c4c286a3b00c2989ed8c5b6d8cf1aa24d8a497c3;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/dm-do-not-use-waitqueue-for-request-based-dm.patch b/queue-5.4/dm-do-not-use-waitqueue-for-request-based-dm.patch new file mode 100644 index 00000000000..74f976458c8 --- /dev/null +++ b/queue-5.4/dm-do-not-use-waitqueue-for-request-based-dm.patch @@ -0,0 +1,144 @@ +From 263a9a6fccc9efc92f056328c105472f60273782 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jun 2020 16:00:58 -0400 +Subject: dm: do not use waitqueue for request-based DM + +From: Ming Lei + +[ Upstream commit 85067747cf9888249fa11fa49ef75af5192d3988 ] + +Given request-based DM now uses blk-mq's blk_mq_queue_inflight() to +determine if outstanding IO has completed (and DM has no control over +the blk-mq state machine used to track outstanding IO) it is unsafe to +wakeup waiter (dm_wait_for_completion) before blk-mq has cleared a +request's state bits (e.g. MQ_RQ_IN_FLIGHT or MQ_RQ_COMPLETE). As +such dm_wait_for_completion() could be left to wait indefinitely if no +other requests complete. + +Fix this by eliminating request-based DM's use of waitqueue to wait +for blk-mq requests to complete in dm_wait_for_completion. + +Signed-off-by: Ming Lei +Depends-on: 3c94d83cb3526 ("blk-mq: change blk_mq_queue_busy() to blk_mq_queue_inflight()") +Cc: stable@vger.kernel.org +Signed-off-by: Mike Snitzer +Stable-dep-of: 1e1fd567d32f ("dm suspend: return -ERESTARTSYS instead of -EINTR") +Signed-off-by: Sasha Levin +--- + drivers/md/dm-rq.c | 4 --- + drivers/md/dm.c | 64 ++++++++++++++++++++++++++++------------------ + 2 files changed, 39 insertions(+), 29 deletions(-) + +diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c +index 6bc61927d3205..3d6ac63ee85ae 100644 +--- a/drivers/md/dm-rq.c ++++ b/drivers/md/dm-rq.c +@@ -143,10 +143,6 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig) + */ + static void rq_completed(struct mapped_device *md) + { +- /* nudge anyone waiting on suspend queue */ +- if (unlikely(wq_has_sleeper(&md->wait))) +- wake_up(&md->wait); +- + /* + * dm_put() must be at the end of this function. See the comment above + */ +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 36d21a5d09ebf..f6f5b68a6950b 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -637,28 +637,6 @@ static void free_tio(struct dm_target_io *tio) + bio_put(&tio->clone); + } + +-static bool md_in_flight_bios(struct mapped_device *md) +-{ +- int cpu; +- struct hd_struct *part = &dm_disk(md)->part0; +- long sum = 0; +- +- for_each_possible_cpu(cpu) { +- sum += part_stat_local_read_cpu(part, in_flight[0], cpu); +- sum += part_stat_local_read_cpu(part, in_flight[1], cpu); +- } +- +- return sum != 0; +-} +- +-static bool md_in_flight(struct mapped_device *md) +-{ +- if (queue_is_mq(md->queue)) +- return blk_mq_queue_inflight(md->queue); +- else +- return md_in_flight_bios(md); +-} +- + u64 dm_start_time_ns_from_clone(struct bio *bio) + { + struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone); +@@ -2428,15 +2406,29 @@ void dm_put(struct mapped_device *md) + } + EXPORT_SYMBOL_GPL(dm_put); + +-static int dm_wait_for_completion(struct mapped_device *md, long task_state) ++static bool md_in_flight_bios(struct mapped_device *md) ++{ ++ int cpu; ++ struct hd_struct *part = &dm_disk(md)->part0; ++ long sum = 0; ++ ++ for_each_possible_cpu(cpu) { ++ sum += part_stat_local_read_cpu(part, in_flight[0], cpu); ++ sum += part_stat_local_read_cpu(part, in_flight[1], cpu); ++ } ++ ++ return sum != 0; ++} ++ ++static int dm_wait_for_bios_completion(struct mapped_device *md, long task_state) + { + int r = 0; + DEFINE_WAIT(wait); + +- while (1) { ++ while (true) { + prepare_to_wait(&md->wait, &wait, task_state); + +- if (!md_in_flight(md)) ++ if (!md_in_flight_bios(md)) + break; + + if (signal_pending_state(task_state, current)) { +@@ -2453,6 +2445,28 @@ static int dm_wait_for_completion(struct mapped_device *md, long task_state) + return r; + } + ++static int dm_wait_for_completion(struct mapped_device *md, long task_state) ++{ ++ int r = 0; ++ ++ if (!queue_is_mq(md->queue)) ++ return dm_wait_for_bios_completion(md, task_state); ++ ++ while (true) { ++ if (!blk_mq_queue_inflight(md->queue)) ++ break; ++ ++ if (signal_pending_state(task_state, current)) { ++ r = -EINTR; ++ break; ++ } ++ ++ msleep(5); ++ } ++ ++ return r; ++} ++ + /* + * Process the deferred bios + */ +-- +2.43.0 + diff --git a/queue-5.4/dm-mpath-pass-io-start-time-to-path-selector.patch b/queue-5.4/dm-mpath-pass-io-start-time-to-path-selector.patch new file mode 100644 index 00000000000..c355b883516 --- /dev/null +++ b/queue-5.4/dm-mpath-pass-io-start-time-to-path-selector.patch @@ -0,0 +1,135 @@ +From a82d33934515ca591b0746a08889aa2c6bfc2187 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Apr 2020 16:48:29 -0400 +Subject: dm mpath: pass IO start time to path selector + +From: Gabriel Krisman Bertazi + +[ Upstream commit 087615bf3acdafd0ba7c7c9ed5286e7b7c80fe1b ] + +The HST path selector needs this information to perform path +prediction. For request-based mpath, struct request's io_start_time_ns +is used, while for bio-based, use the start_time stored in dm_io. + +Signed-off-by: Gabriel Krisman Bertazi +Signed-off-by: Mike Snitzer +Stable-dep-of: 1e1fd567d32f ("dm suspend: return -ERESTARTSYS instead of -EINTR") +Signed-off-by: Sasha Levin +--- + drivers/md/dm-mpath.c | 9 ++++++--- + drivers/md/dm-path-selector.h | 2 +- + drivers/md/dm-queue-length.c | 2 +- + drivers/md/dm-service-time.c | 2 +- + drivers/md/dm.c | 9 +++++++++ + include/linux/device-mapper.h | 2 ++ + 6 files changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c +index 54ecfea2cf47b..4f6a54452b1ca 100644 +--- a/drivers/md/dm-mpath.c ++++ b/drivers/md/dm-mpath.c +@@ -558,7 +558,8 @@ static void multipath_release_clone(struct request *clone, + if (pgpath && pgpath->pg->ps.type->end_io) + pgpath->pg->ps.type->end_io(&pgpath->pg->ps, + &pgpath->path, +- mpio->nr_bytes); ++ mpio->nr_bytes, ++ clone->io_start_time_ns); + } + + blk_put_request(clone); +@@ -1568,7 +1569,8 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone, + struct path_selector *ps = &pgpath->pg->ps; + + if (ps->type->end_io) +- ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes); ++ ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes, ++ clone->io_start_time_ns); + } + + return r; +@@ -1612,7 +1614,8 @@ static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone, + struct path_selector *ps = &pgpath->pg->ps; + + if (ps->type->end_io) +- ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes); ++ ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes, ++ dm_start_time_ns_from_clone(clone)); + } + + return r; +diff --git a/drivers/md/dm-path-selector.h b/drivers/md/dm-path-selector.h +index b6eb5365b1a46..c47bc0e20275b 100644 +--- a/drivers/md/dm-path-selector.h ++++ b/drivers/md/dm-path-selector.h +@@ -74,7 +74,7 @@ struct path_selector_type { + int (*start_io) (struct path_selector *ps, struct dm_path *path, + size_t nr_bytes); + int (*end_io) (struct path_selector *ps, struct dm_path *path, +- size_t nr_bytes); ++ size_t nr_bytes, u64 start_time); + }; + + /* Register a path selector */ +diff --git a/drivers/md/dm-queue-length.c b/drivers/md/dm-queue-length.c +index 969c4f1a36336..5fd018d184187 100644 +--- a/drivers/md/dm-queue-length.c ++++ b/drivers/md/dm-queue-length.c +@@ -227,7 +227,7 @@ static int ql_start_io(struct path_selector *ps, struct dm_path *path, + } + + static int ql_end_io(struct path_selector *ps, struct dm_path *path, +- size_t nr_bytes) ++ size_t nr_bytes, u64 start_time) + { + struct path_info *pi = path->pscontext; + +diff --git a/drivers/md/dm-service-time.c b/drivers/md/dm-service-time.c +index f006a9005593b..9cfda665e9ebd 100644 +--- a/drivers/md/dm-service-time.c ++++ b/drivers/md/dm-service-time.c +@@ -309,7 +309,7 @@ static int st_start_io(struct path_selector *ps, struct dm_path *path, + } + + static int st_end_io(struct path_selector *ps, struct dm_path *path, +- size_t nr_bytes) ++ size_t nr_bytes, u64 start_time) + { + struct path_info *pi = path->pscontext; + +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index a7724ba45b437..36d21a5d09ebf 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -659,6 +659,15 @@ static bool md_in_flight(struct mapped_device *md) + return md_in_flight_bios(md); + } + ++u64 dm_start_time_ns_from_clone(struct bio *bio) ++{ ++ struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone); ++ struct dm_io *io = tio->io; ++ ++ return jiffies_to_nsecs(io->start_time); ++} ++EXPORT_SYMBOL_GPL(dm_start_time_ns_from_clone); ++ + static void start_io_acct(struct dm_io *io) + { + struct mapped_device *md = io->md; +diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h +index 60631f3abddbd..b077f32043653 100644 +--- a/include/linux/device-mapper.h ++++ b/include/linux/device-mapper.h +@@ -332,6 +332,8 @@ void *dm_per_bio_data(struct bio *bio, size_t data_size); + struct bio *dm_bio_from_per_bio_data(void *data, size_t data_size); + unsigned dm_bio_get_target_bio_nr(const struct bio *bio); + ++u64 dm_start_time_ns_from_clone(struct bio *bio); ++ + int dm_register_target(struct target_type *t); + void dm_unregister_target(struct target_type *t); + +-- +2.43.0 + diff --git a/queue-5.4/dm-suspend-return-erestartsys-instead-of-eintr.patch b/queue-5.4/dm-suspend-return-erestartsys-instead-of-eintr.patch new file mode 100644 index 00000000000..9561cd906d2 --- /dev/null +++ b/queue-5.4/dm-suspend-return-erestartsys-instead-of-eintr.patch @@ -0,0 +1,48 @@ +From ee49ba706df738f33aac5c82b710918e96b70d75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Aug 2024 12:38:51 +0200 +Subject: dm suspend: return -ERESTARTSYS instead of -EINTR + +From: Mikulas Patocka + +[ Upstream commit 1e1fd567d32fcf7544c6e09e0e5bc6c650da6e23 ] + +This commit changes device mapper, so that it returns -ERESTARTSYS +instead of -EINTR when it is interrupted by a signal (so that the ioctl +can be restarted). + +The manpage signal(7) says that the ioctl function should be restarted if +the signal was handled with SA_RESTART. + +Signed-off-by: Mikulas Patocka +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/md/dm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index f6f5b68a6950b..3d00bb98d702b 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -2432,7 +2432,7 @@ static int dm_wait_for_bios_completion(struct mapped_device *md, long task_state + break; + + if (signal_pending_state(task_state, current)) { +- r = -EINTR; ++ r = -ERESTARTSYS; + break; + } + +@@ -2457,7 +2457,7 @@ static int dm_wait_for_completion(struct mapped_device *md, long task_state) + break; + + if (signal_pending_state(task_state, current)) { +- r = -EINTR; ++ r = -ERESTARTSYS; + break; + } + +-- +2.43.0 + diff --git a/queue-5.4/series b/queue-5.4/series index f504c6f4065..f8a9023cd69 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -77,3 +77,6 @@ hrtimer-prevent-queuing-of-hrtimer-without-a-functio.patch gtp-pull-network-headers-in-gtp_dev_xmit.patch block-use-unsigned-long-for-blk_validate_block_size.patch media-solo6x10-replace-max-a-min-b-c-by-clamp-b-a-c.patch +dm-mpath-pass-io-start-time-to-path-selector.patch +dm-do-not-use-waitqueue-for-request-based-dm.patch +dm-suspend-return-erestartsys-instead-of-eintr.patch