public inbox for [email protected]
 help / color / mirror / Atom feed
From: Pavel Begunkov <[email protected]>
To: [email protected]
Cc: Jens Axboe <[email protected]>,
	[email protected], [email protected],
	[email protected], Christoph Hellwig <[email protected]>,
	Conrad Meyer <[email protected]>
Subject: [PATCH v5 6/8] block: implement write zeroes io_uring cmd
Date: Wed, 11 Sep 2024 17:34:42 +0100	[thread overview]
Message-ID: <8e7975e44504d8371d716167face2bc8e248f7a4.1726072086.git.asml.silence@gmail.com> (raw)
In-Reply-To: <[email protected]>

Add a second io_uring cmd for block layer implementing asynchronous
write zeroes. It reuses helpers we've added for async discards, and
inherits the code structure as well as all considerations in regards to
page cache races. It has to be supported by underlying hardware to be
used, otherwise the request will fail. A fallback version is implemented
separately in a later patch.

Suggested-by: Conrad Meyer <[email protected]>
Signed-off-by: Pavel Begunkov <[email protected]>
---
 block/ioctl.c               | 66 +++++++++++++++++++++++++++++++++++++
 include/uapi/linux/blkdev.h |  1 +
 2 files changed, 67 insertions(+)

diff --git a/block/ioctl.c b/block/ioctl.c
index 007f6399de66..f8f6d6a71ff0 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -778,6 +778,69 @@ static void bio_cmd_bio_end_io(struct bio *bio)
 	bio_put(bio);
 }
 
+static int blkdev_cmd_write_zeroes(struct io_uring_cmd *cmd,
+				   struct block_device *bdev,
+				   uint64_t start, uint64_t len, bool nowait)
+{
+	struct blk_iou_cmd *bic = io_uring_cmd_to_pdu(cmd, struct blk_iou_cmd);
+	sector_t bs_mask = (bdev_logical_block_size(bdev) >> SECTOR_SHIFT) - 1;
+	sector_t limit = bdev_write_zeroes_sectors(bdev);
+	sector_t sector = start >> SECTOR_SHIFT;
+	sector_t nr_sects = len >> SECTOR_SHIFT;
+	struct bio *prev = NULL, *bio;
+	gfp_t gfp = nowait ? GFP_NOWAIT : GFP_KERNEL;
+	int err;
+
+	if (!(file_to_blk_mode(cmd->file) & BLK_OPEN_WRITE))
+		return -EBADF;
+	if (bdev_read_only(bdev))
+		return -EPERM;
+	err = blk_validate_byte_range(bdev, start, len);
+	if (err)
+		return err;
+
+	if (!limit)
+		return -EOPNOTSUPP;
+	/*
+	 * Don't allow multi-bio non-blocking submissions as subsequent bios
+	 * may fail but we won't get a direct indication of that. Normally,
+	 * the caller should retry from a blocking context.
+	 */
+	if (nowait && nr_sects > limit)
+		return -EAGAIN;
+
+	err = filemap_invalidate_pages(bdev->bd_mapping, start,
+					start + len - 1, nowait);
+	if (err)
+		return err;
+
+	limit = min(limit, (UINT_MAX >> SECTOR_SHIFT) & ~bs_mask);
+	while (nr_sects) {
+		sector_t bio_sects = min(nr_sects, limit);
+
+		bio = bio_alloc(bdev, 0, REQ_OP_WRITE_ZEROES|REQ_NOUNMAP, gfp);
+		if (!bio)
+			break;
+		if (nowait)
+			bio->bi_opf |= REQ_NOWAIT;
+		bio->bi_iter.bi_sector = sector;
+		bio->bi_iter.bi_size = bio_sects << SECTOR_SHIFT;
+		sector += bio_sects;
+		nr_sects -= bio_sects;
+
+		prev = bio_chain_and_submit(prev, bio);
+	}
+	if (unlikely(!prev))
+		return -EAGAIN;
+	if (unlikely(nr_sects))
+		bic->res = -EAGAIN;
+
+	prev->bi_private = cmd;
+	prev->bi_end_io = bio_cmd_bio_end_io;
+	submit_bio(prev);
+	return -EIOCBQUEUED;
+}
+
 static int blkdev_cmd_discard(struct io_uring_cmd *cmd,
 			      struct block_device *bdev,
 			      uint64_t start, uint64_t len, bool nowait)
@@ -856,6 +919,9 @@ int blkdev_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
 	switch (cmd_op) {
 	case BLOCK_URING_CMD_DISCARD:
 		return blkdev_cmd_discard(cmd, bdev, start, len, bic->nowait);
+	case BLOCK_URING_CMD_WRITE_ZEROES:
+		return blkdev_cmd_write_zeroes(cmd, bdev, start, len,
+					       bic->nowait);
 	}
 	return -EINVAL;
 }
diff --git a/include/uapi/linux/blkdev.h b/include/uapi/linux/blkdev.h
index 66373cd1a83a..b4664139a82a 100644
--- a/include/uapi/linux/blkdev.h
+++ b/include/uapi/linux/blkdev.h
@@ -10,5 +10,6 @@
  * It's a different number space from ioctl(), reuse the block's code 0x12.
  */
 #define BLOCK_URING_CMD_DISCARD			_IO(0x12, 0)
+#define BLOCK_URING_CMD_WRITE_ZEROES		_IO(0x12, 1)
 
 #endif
-- 
2.45.2


  parent reply	other threads:[~2024-09-11 16:34 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-11 16:34 [PATCH v5 0/8] implement async block discards and other ops via io_uring Pavel Begunkov
2024-09-11 16:34 ` [PATCH v5 1/8] io_uring/cmd: expose iowq to cmds Pavel Begunkov
2024-09-11 16:34 ` [PATCH v5 2/8] io_uring/cmd: give inline space in request " Pavel Begunkov
2024-09-11 16:34 ` [PATCH v5 3/8] filemap: introduce filemap_invalidate_pages Pavel Begunkov
2024-09-11 16:34 ` [PATCH v5 4/8] block: introduce blk_validate_byte_range() Pavel Begunkov
2024-09-12  9:29   ` Christoph Hellwig
2024-09-11 16:34 ` [PATCH v5 5/8] block: implement async io_uring discard cmd Pavel Begunkov
2024-09-12  9:31   ` Christoph Hellwig
2024-09-12 16:19     ` Pavel Begunkov
2024-09-11 16:34 ` Pavel Begunkov [this message]
2024-09-12  9:32   ` [PATCH v5 6/8] block: implement write zeroes io_uring cmd Christoph Hellwig
2024-09-12 16:25     ` Pavel Begunkov
2024-09-12 16:32       ` Jens Axboe
2024-09-12 16:53         ` Pavel Begunkov
2024-09-12 16:59           ` Jens Axboe
2024-09-13  7:45         ` Christoph Hellwig
2024-09-11 16:34 ` [PATCH v5 7/8] block: add nowait flag for __blkdev_issue_zero_pages Pavel Begunkov
2024-09-11 16:34 ` [PATCH v5 8/8] block: implement write zero pages cmd Pavel Begunkov
2024-09-11 20:56 ` [PATCH v5 0/8] implement async block discards and other ops via io_uring Jens Axboe

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=8e7975e44504d8371d716167face2bc8e248f7a4.1726072086.git.asml.silence@gmail.com \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    [email protected] \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox