block, fs: Restore the per-bio/request data lifetime fields
authorBart Van Assche <bvanassche@acm.org>
Fri, 2 Feb 2024 20:39:25 +0000 (12:39 -0800)
committerChristian Brauner <brauner@kernel.org>
Tue, 6 Feb 2024 13:31:05 +0000 (14:31 +0100)
Restore support for passing data lifetime information from filesystems to
block drivers. This patch reverts commit b179c98f7697 ("block: Remove
request.write_hint") and commit c75e707fe1aa ("block: remove the
per-bio/request write hint").

This patch does not modify the size of struct bio because the new
bi_write_hint member fills a hole in struct bio. pahole reports the
following for struct bio on an x86_64 system with this patch applied:

        /* size: 112, cachelines: 2, members: 20 */
        /* sum members: 110, holes: 1, sum holes: 2 */
        /* last cacheline: 48 bytes */

Reviewed-by: Kanchan Joshi <joshi.k@samsung.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20240202203926.2478590-7-bvanassche@acm.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
13 files changed:
block/bio.c
block/blk-crypto-fallback.c
block/blk-merge.c
block/blk-mq.c
block/bounce.c
block/fops.c
fs/buffer.c
fs/direct-io.c
fs/iomap/buffered-io.c
fs/iomap/direct-io.c
fs/mpage.c
include/linux/blk-mq.h
include/linux/blk_types.h

index b9642a41f286e5bb52d841255aa9286c1449e83d..c9223e9d31da5e84f90c8b3f11205e71ff36d011 100644 (file)
@@ -251,6 +251,7 @@ void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table,
        bio->bi_opf = opf;
        bio->bi_flags = 0;
        bio->bi_ioprio = 0;
+       bio->bi_write_hint = 0;
        bio->bi_status = 0;
        bio->bi_iter.bi_sector = 0;
        bio->bi_iter.bi_size = 0;
@@ -813,6 +814,7 @@ static int __bio_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp)
 {
        bio_set_flag(bio, BIO_CLONED);
        bio->bi_ioprio = bio_src->bi_ioprio;
+       bio->bi_write_hint = bio_src->bi_write_hint;
        bio->bi_iter = bio_src->bi_iter;
 
        if (bio->bi_bdev) {
index e6468eab2681e9f827e9b86b3b21d24f6a6fe0a5..b1e7415f8439c45d04c49f7fbeb48891e0392027 100644 (file)
@@ -172,6 +172,7 @@ static struct bio *blk_crypto_fallback_clone_bio(struct bio *bio_src)
        if (bio_flagged(bio_src, BIO_REMAPPED))
                bio_set_flag(bio, BIO_REMAPPED);
        bio->bi_ioprio          = bio_src->bi_ioprio;
+       bio->bi_write_hint      = bio_src->bi_write_hint;
        bio->bi_iter.bi_sector  = bio_src->bi_iter.bi_sector;
        bio->bi_iter.bi_size    = bio_src->bi_iter.bi_size;
 
index 2d470cf2173e29c540161401bd566942f049f27c..2a06fd33039da6ad1cbb2b6d212c8662184788e0 100644 (file)
@@ -810,6 +810,10 @@ static struct request *attempt_merge(struct request_queue *q,
        if (rq_data_dir(req) != rq_data_dir(next))
                return NULL;
 
+       /* Don't merge requests with different write hints. */
+       if (req->write_hint != next->write_hint)
+               return NULL;
+
        if (req->ioprio != next->ioprio)
                return NULL;
 
@@ -937,6 +941,10 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
        if (!bio_crypt_rq_ctx_compatible(rq, bio))
                return false;
 
+       /* Don't merge requests with different write hints. */
+       if (rq->write_hint != bio->bi_write_hint)
+               return false;
+
        if (rq->ioprio != bio_prio(bio))
                return false;
 
index aa87fcfda1ecfc875c86a0258fe16e707ce3f167..34ceb15d2ea47cdf40d5793d9f2b90ed83de4005 100644 (file)
@@ -2585,6 +2585,7 @@ static void blk_mq_bio_to_request(struct request *rq, struct bio *bio,
                rq->cmd_flags |= REQ_FAILFAST_MASK;
 
        rq->__sector = bio->bi_iter.bi_sector;
+       rq->write_hint = bio->bi_write_hint;
        blk_rq_bio_prep(rq, bio, nr_segs);
 
        /* This can't fail, since GFP_NOIO includes __GFP_DIRECT_RECLAIM. */
@@ -3185,6 +3186,7 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
        }
        rq->nr_phys_segments = rq_src->nr_phys_segments;
        rq->ioprio = rq_src->ioprio;
+       rq->write_hint = rq_src->write_hint;
 
        if (rq->bio && blk_crypto_rq_bio_prep(rq, rq->bio, gfp_mask) < 0)
                goto free_and_out;
index 7cfcb242f9a112cc8352121c5b6f73ceb467d4c9..d6a5219f29dd53b5fa7aa379d69a71aa5a087ebc 100644 (file)
@@ -169,6 +169,7 @@ static struct bio *bounce_clone_bio(struct bio *bio_src)
        if (bio_flagged(bio_src, BIO_REMAPPED))
                bio_set_flag(bio, BIO_REMAPPED);
        bio->bi_ioprio          = bio_src->bi_ioprio;
+       bio->bi_write_hint      = bio_src->bi_write_hint;
        bio->bi_iter.bi_sector  = bio_src->bi_iter.bi_sector;
        bio->bi_iter.bi_size    = bio_src->bi_iter.bi_size;
 
index 0cf8cf72cdfa108926ae8fc7f53bce05a3225058..ab0e37d1dc4879df1069ea1a9a748e61ce7da03c 100644 (file)
@@ -73,6 +73,7 @@ static ssize_t __blkdev_direct_IO_simple(struct kiocb *iocb,
                bio_init(&bio, bdev, vecs, nr_pages, dio_bio_write_op(iocb));
        }
        bio.bi_iter.bi_sector = pos >> SECTOR_SHIFT;
+       bio.bi_write_hint = file_inode(iocb->ki_filp)->i_write_hint;
        bio.bi_ioprio = iocb->ki_ioprio;
 
        ret = bio_iov_iter_get_pages(&bio, iter);
@@ -203,6 +204,7 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 
        for (;;) {
                bio->bi_iter.bi_sector = pos >> SECTOR_SHIFT;
+               bio->bi_write_hint = file_inode(iocb->ki_filp)->i_write_hint;
                bio->bi_private = dio;
                bio->bi_end_io = blkdev_bio_end_io;
                bio->bi_ioprio = iocb->ki_ioprio;
@@ -321,6 +323,7 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb,
        dio->flags = 0;
        dio->iocb = iocb;
        bio->bi_iter.bi_sector = pos >> SECTOR_SHIFT;
+       bio->bi_write_hint = file_inode(iocb->ki_filp)->i_write_hint;
        bio->bi_end_io = blkdev_bio_end_io_async;
        bio->bi_ioprio = iocb->ki_ioprio;
 
index d3bcf601d3e5a5330419d8e69500c3781f9e8cfc..eb7d3ded2c3362aa4cd49bf79e428c184f6d76b6 100644 (file)
@@ -55,7 +55,7 @@
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
-                         struct writeback_control *wbc);
+                         enum rw_hint hint, struct writeback_control *wbc);
 
 #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
 
@@ -1889,7 +1889,8 @@ int __block_write_full_folio(struct inode *inode, struct folio *folio,
        do {
                struct buffer_head *next = bh->b_this_page;
                if (buffer_async_write(bh)) {
-                       submit_bh_wbc(REQ_OP_WRITE | write_flags, bh, wbc);
+                       submit_bh_wbc(REQ_OP_WRITE | write_flags, bh,
+                                     inode->i_write_hint, wbc);
                        nr_underway++;
                }
                bh = next;
@@ -1944,7 +1945,8 @@ recover:
                struct buffer_head *next = bh->b_this_page;
                if (buffer_async_write(bh)) {
                        clear_buffer_dirty(bh);
-                       submit_bh_wbc(REQ_OP_WRITE | write_flags, bh, wbc);
+                       submit_bh_wbc(REQ_OP_WRITE | write_flags, bh,
+                                     inode->i_write_hint, wbc);
                        nr_underway++;
                }
                bh = next;
@@ -2756,6 +2758,7 @@ static void end_bio_bh_io_sync(struct bio *bio)
 }
 
 static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
+                         enum rw_hint write_hint,
                          struct writeback_control *wbc)
 {
        const enum req_op op = opf & REQ_OP_MASK;
@@ -2783,6 +2786,7 @@ static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
        fscrypt_set_bio_crypt_ctx_bh(bio, bh, GFP_NOIO);
 
        bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
+       bio->bi_write_hint = write_hint;
 
        __bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh));
 
@@ -2802,7 +2806,7 @@ static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
 
 void submit_bh(blk_opf_t opf, struct buffer_head *bh)
 {
-       submit_bh_wbc(opf, bh, NULL);
+       submit_bh_wbc(opf, bh, WRITE_LIFE_NOT_SET, NULL);
 }
 EXPORT_SYMBOL(submit_bh);
 
index 60456263a338e018e6b4cb0f79ce26e0806ec4c9..62c97ff9e852a15b495b1bdb3790290dddc33515 100644 (file)
@@ -410,6 +410,8 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio,
                bio->bi_end_io = dio_bio_end_io;
        if (dio->is_pinned)
                bio_set_flag(bio, BIO_PAGE_PINNED);
+       bio->bi_write_hint = file_inode(dio->iocb->ki_filp)->i_write_hint;
+
        sdio->bio = bio;
        sdio->logical_offset_in_bio = sdio->cur_page_fs_offset;
 }
index 093c4515b22a53b9b9f9b862747269d76448ab09..18e1fef53fbc5c75569634946b17aee42f38f4a5 100644 (file)
@@ -1667,6 +1667,7 @@ iomap_alloc_ioend(struct inode *inode, struct iomap_writepage_ctx *wpc,
                               REQ_OP_WRITE | wbc_to_write_flags(wbc),
                               GFP_NOFS, &iomap_ioend_bioset);
        bio->bi_iter.bi_sector = sector;
+       bio->bi_write_hint = inode->i_write_hint;
        wbc_init_bio(wbc, bio);
 
        ioend = container_of(bio, struct iomap_ioend, io_inline_bio);
index bcd3f8cf5ea42f0fa0e4967510230f7e5d25b1fa..f3b43d223a46ee9064315b6bc902852f16172ce1 100644 (file)
@@ -380,6 +380,7 @@ static loff_t iomap_dio_bio_iter(const struct iomap_iter *iter,
                fscrypt_set_bio_crypt_ctx(bio, inode, pos >> inode->i_blkbits,
                                          GFP_KERNEL);
                bio->bi_iter.bi_sector = iomap_sector(iomap, pos);
+               bio->bi_write_hint = inode->i_write_hint;
                bio->bi_ioprio = dio->iocb->ki_ioprio;
                bio->bi_private = dio;
                bio->bi_end_io = iomap_dio_bio_end_io;
index 738882e0766d083743698916df5f77ce1e68dea7..fa8b99a199fa70eed226ed9ea54927751849d62f 100644 (file)
@@ -605,6 +605,7 @@ alloc_new:
                                GFP_NOFS);
                bio->bi_iter.bi_sector = first_block << (blkbits - 9);
                wbc_init_bio(wbc, bio);
+               bio->bi_write_hint = inode->i_write_hint;
        }
 
        /*
index 7a8150a5f051339f680b9df83fa78da48b8c8af1..492b0128b5d9a84a0cfd746fb237e83f840e308f 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/scatterlist.h>
 #include <linux/prefetch.h>
 #include <linux/srcu.h>
+#include <linux/rw_hint.h>
 
 struct blk_mq_tags;
 struct blk_flush_queue;
@@ -135,6 +136,7 @@ struct request {
        struct blk_crypto_keyslot *crypt_keyslot;
 #endif
 
+       enum rw_hint write_hint;
        unsigned short ioprio;
 
        enum mq_rq_state state;
index f288c94374b307fb1f47cade7e86943858fd6741..12d87cef2c03c64ea7eb40c781ab76d15bf3b924 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/bvec.h>
 #include <linux/device.h>
 #include <linux/ktime.h>
+#include <linux/rw_hint.h>
 
 struct bio_set;
 struct bio;
@@ -269,6 +270,7 @@ struct bio {
                                                 */
        unsigned short          bi_flags;       /* BIO_* below */
        unsigned short          bi_ioprio;
+       enum rw_hint            bi_write_hint;
        blk_status_t            bi_status;
        atomic_t                __bi_remaining;