diff mbox series

[02/15] block: don't try to poll multi-bio I/Os in __blkdev_direct_IO

Message ID 20210512131545.495160-3-hch@lst.de (mailing list archive)
State New, archived
Headers show
Series [01/15] direct-io: remove blk_poll support | expand

Commit Message

Christoph Hellwig May 12, 2021, 1:15 p.m. UTC
If an iocb is split into multiple bios we can't poll for both.  So don't
bother to even try to poll in that case.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/block_dev.c | 37 ++++++++++++++-----------------------
 1 file changed, 14 insertions(+), 23 deletions(-)

Comments

Sagi Grimberg May 12, 2021, 8:54 p.m. UTC | #1
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Kanchan Joshi May 16, 2021, 6:01 p.m. UTC | #2
On Wed, May 12, 2021 at 6:50 PM Christoph Hellwig <hch@lst.de> wrote:
>
> If an iocb is split into multiple bios we can't poll for both.  So don't
> bother to even try to poll in that case.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/block_dev.c | 37 ++++++++++++++-----------------------
>  1 file changed, 14 insertions(+), 23 deletions(-)
>
> diff --git a/fs/block_dev.c b/fs/block_dev.c
> index b8abccd03e5d..0080a3b710b4 100644
> --- a/fs/block_dev.c
> +++ b/fs/block_dev.c
> @@ -375,7 +375,7 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
>         struct blk_plug plug;
>         struct blkdev_dio *dio;
>         struct bio *bio;
> -       bool is_poll = (iocb->ki_flags & IOCB_HIPRI) != 0;
> +       bool is_poll = (iocb->ki_flags & IOCB_HIPRI), do_poll = false;
>         bool is_read = (iov_iter_rw(iter) == READ), is_sync;
>         loff_t pos = iocb->ki_pos;
>         blk_qc_t qc = BLK_QC_T_NONE;
> @@ -437,22 +437,9 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
>                 pos += bio->bi_iter.bi_size;
>
>                 nr_pages = bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS);
> -               if (!nr_pages) {
> -                       bool polled = false;
> -
> -                       if (iocb->ki_flags & IOCB_HIPRI) {
> -                               bio_set_polled(bio, iocb);
> -                               polled = true;
> -                       }
> -
> -                       qc = submit_bio(bio);
> -
> -                       if (polled)
> -                               WRITE_ONCE(iocb->ki_cookie, qc);
> -                       break;
> -               }
> -
> -               if (!dio->multi_bio) {
> +               if (dio->multi_bio) {
> +                       atomic_inc(&dio->ref);
> +               } else if (nr_pages) {
>                         /*
>                          * AIO needs an extra reference to ensure the dio
>                          * structure which is embedded into the first bio
> @@ -462,11 +449,16 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
>                                 bio_get(bio);
>                         dio->multi_bio = true;
>                         atomic_set(&dio->ref, 2);
> -               } else {
> -                       atomic_inc(&dio->ref);
> +               } else if (is_poll) {
> +                       bio_set_polled(bio, iocb);
> +                       do_poll = true;
> +               }
> +               qc = submit_bio(bio);
> +               if (!nr_pages) {
> +                       if (do_poll)
> +                               WRITE_ONCE(iocb->ki_cookie, qc);
> +                       break;
>                 }
> -
> -               submit_bio(bio);
>                 bio = bio_alloc(GFP_KERNEL, nr_pages);
>         }

dio->ref update goes amiss here.
For multi-bio, if the original code sets it as N, this will set it as
N+1, causing endless-wait for the caller.
diff mbox series

Patch

diff --git a/fs/block_dev.c b/fs/block_dev.c
index b8abccd03e5d..0080a3b710b4 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -375,7 +375,7 @@  static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 	struct blk_plug plug;
 	struct blkdev_dio *dio;
 	struct bio *bio;
-	bool is_poll = (iocb->ki_flags & IOCB_HIPRI) != 0;
+	bool is_poll = (iocb->ki_flags & IOCB_HIPRI), do_poll = false;
 	bool is_read = (iov_iter_rw(iter) == READ), is_sync;
 	loff_t pos = iocb->ki_pos;
 	blk_qc_t qc = BLK_QC_T_NONE;
@@ -437,22 +437,9 @@  static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 		pos += bio->bi_iter.bi_size;
 
 		nr_pages = bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS);
-		if (!nr_pages) {
-			bool polled = false;
-
-			if (iocb->ki_flags & IOCB_HIPRI) {
-				bio_set_polled(bio, iocb);
-				polled = true;
-			}
-
-			qc = submit_bio(bio);
-
-			if (polled)
-				WRITE_ONCE(iocb->ki_cookie, qc);
-			break;
-		}
-
-		if (!dio->multi_bio) {
+		if (dio->multi_bio) {
+			atomic_inc(&dio->ref);
+		} else if (nr_pages) {
 			/*
 			 * AIO needs an extra reference to ensure the dio
 			 * structure which is embedded into the first bio
@@ -462,11 +449,16 @@  static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 				bio_get(bio);
 			dio->multi_bio = true;
 			atomic_set(&dio->ref, 2);
-		} else {
-			atomic_inc(&dio->ref);
+		} else if (is_poll) {
+			bio_set_polled(bio, iocb);
+			do_poll = true;
+		}
+		qc = submit_bio(bio);
+		if (!nr_pages) {
+			if (do_poll)
+				WRITE_ONCE(iocb->ki_cookie, qc);
+			break;
 		}
-
-		submit_bio(bio);
 		bio = bio_alloc(GFP_KERNEL, nr_pages);
 	}
 
@@ -481,8 +473,7 @@  static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 		if (!READ_ONCE(dio->waiter))
 			break;
 
-		if (!(iocb->ki_flags & IOCB_HIPRI) ||
-		    !blk_poll(bdev_get_queue(bdev), qc, true))
+		if (!do_poll || !blk_poll(bdev_get_queue(bdev), qc, true))
 			blk_io_schedule();
 	}
 	__set_current_state(TASK_RUNNING);