summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Wilcox (Oracle) <willy@infradead.org>2026-05-28 20:31:15 +0300
committerChristian Brauner <brauner@kernel.org>2026-06-04 11:28:06 +0300
commit4b7381326424809577eb43bf635ea1d43a095d89 (patch)
tree22124ed43b0c21011eeea5af5e8eb33a792e8eb7
parent6b1a162ba1a2dfd1ceac24029e4d0c2443173ed2 (diff)
downloadlinux-4b7381326424809577eb43bf635ea1d43a095d89.tar.xz
buffer: Add bh_submit()
bh_submit() takes a bio_end_io allowing users to avoid the indirect function call through bh->b_end_io, and eventually allowing us to remove bh->b_end_io. Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Link: https://patch.msgid.link/20260528173150.1093780-3-willy@infradead.org Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
-rw-r--r--fs/buffer.c31
-rw-r--r--include/linux/buffer_head.h1
2 files changed, 28 insertions, 4 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index d4e9a10d2a26..ea926963529e 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1180,15 +1180,15 @@ static void buffer_set_crypto_ctx(struct bio *bio, const struct buffer_head *bh,
folio_pos(bh->b_folio) + bh_offset(bh), gfp_mask);
}
-static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
- enum rw_hint write_hint, struct writeback_control *wbc)
+static void __bh_submit(struct buffer_head *bh, blk_opf_t opf,
+ enum rw_hint write_hint, struct writeback_control *wbc,
+ bio_end_io_t end_bio)
{
const enum req_op op = opf & REQ_OP_MASK;
struct bio *bio;
BUG_ON(!buffer_locked(bh));
BUG_ON(!buffer_mapped(bh));
- BUG_ON(!bh->b_end_io);
BUG_ON(buffer_delay(bh));
BUG_ON(buffer_unwritten(bh));
@@ -1213,7 +1213,7 @@ static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
bio_add_folio_nofail(bio, bh->b_folio, bh->b_size, bh_offset(bh));
- bio->bi_end_io = end_bio_bh_io_sync;
+ bio->bi_end_io = end_bio;
bio->bi_private = bh;
/* Take care of bh's that straddle the end of the device */
@@ -1227,6 +1227,29 @@ static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
blk_crypto_submit_bio(bio);
}
+static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
+ enum rw_hint write_hint,
+ struct writeback_control *wbc)
+{
+ BUG_ON(!bh->b_end_io);
+ __bh_submit(bh, opf, write_hint, wbc, end_bio_bh_io_sync);
+}
+
+/**
+ * bh_submit - Start I/O against a buffer head
+ * @bh: The buffer head to perform I/O on.
+ * @opf: Operation and flags for bio.
+ * @end_io: The routine to call when I/O has completed.
+ *
+ * If you need to do I/O on an individual bh (instead of allowing the
+ * page cache to do I/O on the folio that it is in), call this function.
+ */
+void bh_submit(struct buffer_head *bh, blk_opf_t opf, bio_end_io_t end_io)
+{
+ __bh_submit(bh, opf, WRITE_LIFE_NOT_SET, NULL, end_io);
+}
+EXPORT_SYMBOL(bh_submit);
+
static struct buffer_head *__bread_slow(struct buffer_head *bh)
{
lock_buffer(bh);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index e4939e33b4b5..d59980e4adda 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -240,6 +240,7 @@ int sync_dirty_buffer(struct buffer_head *bh);
int __sync_dirty_buffer(struct buffer_head *bh, blk_opf_t op_flags);
void write_dirty_buffer(struct buffer_head *bh, blk_opf_t op_flags);
void submit_bh(blk_opf_t, struct buffer_head *);
+void bh_submit(struct buffer_head *, blk_opf_t, bio_end_io_t);
void write_boundary_block(struct block_device *bdev,
sector_t bblock, unsigned blocksize);
int bh_uptodate_or_lock(struct buffer_head *bh);