From: Mike Snitzer <snitzer@kernel.org>
To: Mikulas Patocka <mpatocka@redhat.com>
Cc: Ming Lei <ming.lei@redhat.com>,
dm-devel@lists.linux.dev, linux-block@vger.kernel.org,
axboe@kernel.dk
Subject: [PATCH v3] dm: respect REQ_NOWAIT flag in normal bios issued to DM
Date: Wed, 25 Oct 2023 20:12:05 -0400 [thread overview]
Message-ID: <ZTmu1T5mf3Xgf0tR@redhat.com> (raw)
In-Reply-To: <ZTlt0HPbVZf0gYcI@redhat.com>
Update DM core's normal IO submission to allocate required memory
using GFP_NOWAIT if REQ_NOWAIT is set.
Tested with simple test provided in commit a9ce385344f916 ("dm: don't
attempt to queue IO under RCU protection") that was enhanced to check
error codes. Also tested using fio's pvsync2 with nowait=1.
But testing with induced GFP_NOWAIT allocation failures wasn't
performed (yet).
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
---
drivers/md/dm.c | 50 ++++++++++++++++++++++++++++++++++++-------------
1 file changed, 37 insertions(+), 13 deletions(-)
v3:
- followed Mikulas's suggestion of only supporting NOWAIT for normal IO
- changed attribution to me since basically all the code was rewritten
- removed dm_io_rewind() changes thanks to Ming's reminder that DM's
requeue won't block IO submission because it is called from worker
(so it using GFP_NOIO is fine).
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 1113a8da3c47..609c68287158 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -570,13 +570,15 @@ static void dm_end_io_acct(struct dm_io *io)
dm_io_acct(io, true);
}
-static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio)
+static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio, gfp_t gfp_mask)
{
struct dm_io *io;
struct dm_target_io *tio;
struct bio *clone;
- clone = bio_alloc_clone(NULL, bio, GFP_NOIO, &md->mempools->io_bs);
+ clone = bio_alloc_clone(NULL, bio, gfp_mask, &md->mempools->io_bs);
+ if (unlikely(!clone))
+ return NULL;
tio = clone_to_tio(clone);
tio->flags = 0;
dm_tio_set_flag(tio, DM_TIO_INSIDE_DM_IO);
@@ -1714,10 +1716,6 @@ static blk_status_t __split_and_process_bio(struct clone_info *ci)
if (unlikely(!ti))
return BLK_STS_IOERR;
- if (unlikely((ci->bio->bi_opf & REQ_NOWAIT) != 0) &&
- unlikely(!dm_target_supports_nowait(ti->type)))
- return BLK_STS_NOTSUPP;
-
if (unlikely(ci->is_abnormal_io))
return __process_abnormal_io(ci, ti);
@@ -1729,7 +1727,17 @@ static blk_status_t __split_and_process_bio(struct clone_info *ci)
len = min_t(sector_t, max_io_len(ti, ci->sector), ci->sector_count);
setup_split_accounting(ci, len);
- clone = alloc_tio(ci, ti, 0, &len, GFP_NOIO);
+
+ if (unlikely(ci->bio->bi_opf & REQ_NOWAIT)) {
+ if (unlikely(!dm_target_supports_nowait(ti->type)))
+ return BLK_STS_NOTSUPP;
+
+ clone = alloc_tio(ci, ti, 0, &len, GFP_NOWAIT);
+ if (unlikely(!clone))
+ return BLK_STS_AGAIN;
+ } else {
+ clone = alloc_tio(ci, ti, 0, &len, GFP_NOIO);
+ }
__map_bio(clone);
ci->sector += len;
@@ -1738,11 +1746,11 @@ static blk_status_t __split_and_process_bio(struct clone_info *ci)
return BLK_STS_OK;
}
-static void init_clone_info(struct clone_info *ci, struct mapped_device *md,
+static void init_clone_info(struct clone_info *ci, struct dm_io *io,
struct dm_table *map, struct bio *bio, bool is_abnormal)
{
ci->map = map;
- ci->io = alloc_io(md, bio);
+ ci->io = io;
ci->bio = bio;
ci->is_abnormal_io = is_abnormal;
ci->submit_as_polled = false;
@@ -1764,7 +1772,7 @@ static void dm_split_and_process_bio(struct mapped_device *md,
struct clone_info ci;
struct dm_io *io;
blk_status_t error = BLK_STS_OK;
- bool is_abnormal;
+ bool is_abnormal, is_preflush = !!(bio->bi_opf & REQ_PREFLUSH);
is_abnormal = is_abnormal_io(bio);
if (unlikely(is_abnormal)) {
@@ -1777,10 +1785,26 @@ static void dm_split_and_process_bio(struct mapped_device *md,
return;
}
- init_clone_info(&ci, md, map, bio, is_abnormal);
- io = ci.io;
+ if (unlikely(bio->bi_opf & REQ_NOWAIT)) {
+ /* Only support nowait for normal IO */
+ if (unlikely(is_preflush || is_abnormal)) {
+ bio->bi_status = BLK_STS_NOTSUPP;
+ bio_endio(bio);
+ return;
+ }
- if (bio->bi_opf & REQ_PREFLUSH) {
+ io = alloc_io(md, bio, GFP_NOWAIT);
+ if (unlikely(!io)) {
+ /* Unable to do anything without dm_io. */
+ bio_wouldblock_error(bio);
+ return;
+ }
+ } else {
+ io = alloc_io(md, bio, GFP_NOIO);
+ }
+ init_clone_info(&ci, io, map, bio, is_abnormal);
+
+ if (is_preflush) {
__send_empty_flush(&ci);
/* dm_io_complete submits any data associated with flush */
goto out;
--
2.40.0
prev parent reply other threads:[~2023-10-26 0:12 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-03 15:30 [dm-devel] [PATCH] Respect REQ_NOWATI bios Mikulas Patocka
2023-10-24 17:58 ` dm: Respect REQ_NOWAIT bios Mike Snitzer
2023-10-24 19:18 ` Mikulas Patocka
2023-10-24 19:32 ` Mike Snitzer
2023-10-25 19:34 ` [PATCH v2] dm: respect REQ_NOWAIT flag in bios issued to DM Mike Snitzer
2023-10-25 19:55 ` Mike Snitzer
2023-10-25 23:44 ` Ming Lei
2023-10-26 0:12 ` Mike Snitzer [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZTmu1T5mf3Xgf0tR@redhat.com \
--to=snitzer@kernel.org \
--cc=axboe@kernel.dk \
--cc=dm-devel@lists.linux.dev \
--cc=linux-block@vger.kernel.org \
--cc=ming.lei@redhat.com \
--cc=mpatocka@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.