summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2026-06-04 11:28:17 +0300
committerChristian Brauner <brauner@kernel.org>2026-06-04 11:28:17 +0300
commitf0d857543e4d37464759c338f46ad6c85a618a2e (patch)
treea39f51aa38bedb7939a4ba5e979747481e782457 /include/linux
parent254f49634ee16a731174d2ae34bc50bd5f45e731 (diff)
parentb20f15420f786a029be09b1d9b81695581d1a122 (diff)
downloadlinux-f0d857543e4d37464759c338f46ad6c85a618a2e.tar.xz
Merge patch series "Remove b_end_io from struct buffer_head"
Matthew Wilcox (Oracle) <willy@infradead.org> says: There are four benefits to this patchset. First, it removes an indirect function call from the completion path. Instead of setting bio->bi_end_io to end_bio_bh_io_sync() which then calls bh->b_end_io(), we set bio->bi_end_io to the appropriate completion handler, replacing two indirect function calls with one. Second, there is a slight security advantage to this. It is one fewer function pointer in the middle of a writable data structure that can be corrupted. Third, it shrinks struct buffer_head from 104 bytes to 96 bytes, allowing for appropriximately 7% reduction in the amount of memory used by buffer_heads (or, alternatively, allows 7% more buffer_heads to be cached in the same amount of memory). Fourth, it removes some atomic operations as the buffer refcount is no longer incremented before calling the end_io handler. I've run ext4 through its paces, and everything seems OK. I've only compiled ocfs2/gfs2/nilfs/md-bitmap. Hopefully the maintainers can give this series a try. I'm sending the entire series to linux-fsdevel and cc'ing the fs-specific mailing lists for the fs-specific patches. * patches from https://patch.msgid.link/20260528173150.1093780-1-willy@infradead.org: (34 commits) buffer: Remove end_buffer_write_sync() buffer: Change calling convention for end_buffer_read_sync() buffer: Remove b_end_io buffer: Remove submit_bh() md-bitmap: Convert read_file_page and write_file_page to bh_submit() nilfs2: Convert nilfs_mdt_submit_block to bh_submit() nilfs2: Convert nilfs_gccache_submit_read_data to bh_submit() nilfs2: Convert nilfs_btnode_submit_block to bh_submit() buffer: Remove mark_buffer_async_write() gfs2: Convert gfs2_aspace_write_folio to bh_submit() gfs2: Remove use of b_end_io in gfs2_meta_read_endio() gfs2: Convert gfs2_dir_readahead to bh_submit() gfs2: Convert gfs2_metapath_ra to bh_submit() ocfs2: Convert ocfs2_write_super_or_backup to bh_submit() ocfs2: Convert ocfs2_read_blocks to bh_submit() ocfs2: Convert ocfs2_read_block to bh_submit() ocfs2: Convert ocfs2_write_block to bh_submit() jbd2: Convert jbd2_write_superblock() to bh_submit() jbd2: Convert journal commit to bh_submit() ext4: Convert ext4_commit_super() to bh_submit() ... Link: https://patch.msgid.link/20260528173150.1093780-1-willy@infradead.org Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/buffer_head.h16
1 files changed, 9 insertions, 7 deletions
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index e4939e33b4b5..8b23bc9a244c 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -46,7 +46,6 @@ enum bh_state_bits {
struct page;
struct buffer_head;
struct address_space;
-typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
/*
* Historically, a buffer_head was used to map a single block
@@ -55,7 +54,7 @@ typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
* is the bio, and buffer_heads are used for extracting block
* mappings (via a get_block_t call), for tracking state within
* a folio (via a folio_mapping) and for wrapping bio submission
- * for backward compatibility reasons (e.g. submit_bh).
+ * for backward compatibility reasons (e.g. bh_submit).
*/
struct buffer_head {
unsigned long b_state; /* buffer state bitmap (see above) */
@@ -70,8 +69,7 @@ struct buffer_head {
char *b_data; /* pointer to data within the page */
struct block_device *b_bdev;
- bh_end_io_t *b_end_io; /* I/O completion */
- void *b_private; /* reserved for b_end_io */
+ void *b_private; /* reserved for bio_end_io */
struct list_head b_assoc_buffers; /* associated with another mapping */
struct mapping_metadata_bhs *b_mmb; /* head of the list of metadata bhs
* this buffer is associated with */
@@ -203,7 +201,12 @@ struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size);
struct buffer_head *create_empty_buffers(struct folio *folio,
unsigned long blocksize, unsigned long b_state);
void end_buffer_read_sync(struct buffer_head *bh, int uptodate);
-void end_buffer_write_sync(struct buffer_head *bh, int uptodate);
+bool bio_endio_bh(struct bio *bio, struct buffer_head **bhp);
+
+/* Completion routines suitable for passing to bh_submit() */
+void bh_end_read(struct bio *bio);
+void bh_end_write(struct bio *bio);
+void bh_end_async_write(struct bio *bio);
/* Things to do with metadata buffers list */
void mmb_mark_buffer_dirty(struct buffer_head *bh, struct mapping_metadata_bhs *mmb);
@@ -218,7 +221,6 @@ static inline void clean_bdev_bh_alias(struct buffer_head *bh)
clean_bdev_aliases(bh->b_bdev, bh->b_blocknr, 1);
}
-void mark_buffer_async_write(struct buffer_head *bh);
void __wait_on_buffer(struct buffer_head *);
wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block,
@@ -239,7 +241,7 @@ void __lock_buffer(struct buffer_head *bh);
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);