Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fs: add CONFIG_BUFFER_HEAD

Add a new config option that controls building the buffer_head code, and
select it from all file systems and stacking drivers that need it.

For the block device nodes and alternative iomap based buffered I/O path
is provided when buffer_head support is not enabled, and iomap needs a
a small tweak to define the IOMAP_F_BUFFER_HEAD flag to 0 to not call
into the buffer_head code when it doesn't exist.

Otherwise this is just Kconfig and ifdef changes.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Link: https://lore.kernel.org/r/20230801172201.1923299-7-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
925c86a1 487c607d

+119 -29
+60 -10
block/fops.c
··· 24 24 return file->f_mapping->host; 25 25 } 26 26 27 - static int blkdev_get_block(struct inode *inode, sector_t iblock, 28 - struct buffer_head *bh, int create) 29 - { 30 - bh->b_bdev = I_BDEV(inode); 31 - bh->b_blocknr = iblock; 32 - set_buffer_mapped(bh); 33 - return 0; 34 - } 35 - 36 27 static blk_opf_t dio_bio_write_op(struct kiocb *iocb) 37 28 { 38 29 blk_opf_t opf = REQ_OP_WRITE | REQ_SYNC | REQ_IDLE; ··· 391 400 iomap->type = IOMAP_MAPPED; 392 401 iomap->addr = iomap->offset; 393 402 iomap->length = isize - iomap->offset; 394 - iomap->flags |= IOMAP_F_BUFFER_HEAD; 403 + iomap->flags |= IOMAP_F_BUFFER_HEAD; /* noop for !CONFIG_BUFFER_HEAD */ 395 404 return 0; 396 405 } 397 406 398 407 static const struct iomap_ops blkdev_iomap_ops = { 399 408 .iomap_begin = blkdev_iomap_begin, 400 409 }; 410 + 411 + #ifdef CONFIG_BUFFER_HEAD 412 + static int blkdev_get_block(struct inode *inode, sector_t iblock, 413 + struct buffer_head *bh, int create) 414 + { 415 + bh->b_bdev = I_BDEV(inode); 416 + bh->b_blocknr = iblock; 417 + set_buffer_mapped(bh); 418 + return 0; 419 + } 401 420 402 421 static int blkdev_writepage(struct page *page, struct writeback_control *wbc) 403 422 { ··· 454 453 .migrate_folio = buffer_migrate_folio_norefs, 455 454 .is_dirty_writeback = buffer_check_dirty_writeback, 456 455 }; 456 + #else /* CONFIG_BUFFER_HEAD */ 457 + static int blkdev_read_folio(struct file *file, struct folio *folio) 458 + { 459 + return iomap_read_folio(folio, &blkdev_iomap_ops); 460 + } 461 + 462 + static void blkdev_readahead(struct readahead_control *rac) 463 + { 464 + iomap_readahead(rac, &blkdev_iomap_ops); 465 + } 466 + 467 + static int blkdev_map_blocks(struct iomap_writepage_ctx *wpc, 468 + struct inode *inode, loff_t offset) 469 + { 470 + loff_t isize = i_size_read(inode); 471 + 472 + if (WARN_ON_ONCE(offset >= isize)) 473 + return -EIO; 474 + if (offset >= wpc->iomap.offset && 475 + offset < wpc->iomap.offset + wpc->iomap.length) 476 + return 0; 477 + return blkdev_iomap_begin(inode, offset, isize - offset, 478 + IOMAP_WRITE, &wpc->iomap, NULL); 479 + } 480 + 481 + static const struct iomap_writeback_ops blkdev_writeback_ops = { 482 + .map_blocks = blkdev_map_blocks, 483 + }; 484 + 485 + static int blkdev_writepages(struct address_space *mapping, 486 + struct writeback_control *wbc) 487 + { 488 + struct iomap_writepage_ctx wpc = { }; 489 + 490 + return iomap_writepages(mapping, wbc, &wpc, &blkdev_writeback_ops); 491 + } 492 + 493 + const struct address_space_operations def_blk_aops = { 494 + .dirty_folio = filemap_dirty_folio, 495 + .release_folio = iomap_release_folio, 496 + .invalidate_folio = iomap_invalidate_folio, 497 + .read_folio = blkdev_read_folio, 498 + .readahead = blkdev_readahead, 499 + .writepages = blkdev_writepages, 500 + .is_partially_uptodate = iomap_is_partially_uptodate, 501 + .error_remove_page = generic_error_remove_page, 502 + .migrate_folio = filemap_migrate_folio, 503 + }; 504 + #endif /* CONFIG_BUFFER_HEAD */ 457 505 458 506 /* 459 507 * for a block special file file_inode(file)->i_size is zero
+1
drivers/md/Kconfig
··· 15 15 config BLK_DEV_MD 16 16 tristate "RAID support" 17 17 select BLOCK_HOLDER_DEPRECATED if SYSFS 18 + select BUFFER_HEAD 18 19 # BLOCK_LEGACY_AUTOLOAD requirement should be removed 19 20 # after relevant mdadm enhancements - to make "names=yes" 20 21 # the default - are widely available.
+4
fs/Kconfig
··· 18 18 config FS_IOMAP 19 19 bool 20 20 21 + config BUFFER_HEAD 22 + bool 23 + 21 24 # old blockdev_direct_IO implementation. Use iomap for new code instead 22 25 config LEGACY_DIRECT_IO 26 + depends on BUFFER_HEAD 23 27 bool 24 28 25 29 if BLOCK
+1 -1
fs/Makefile
··· 17 17 fs_types.o fs_context.o fs_parser.o fsopen.o init.o \ 18 18 kernel_read_file.o mnt_idmapping.o remap_range.o 19 19 20 - obj-$(CONFIG_BLOCK) += buffer.o mpage.o 20 + obj-$(CONFIG_BUFFER_HEAD) += buffer.o mpage.o 21 21 obj-$(CONFIG_PROC_FS) += proc_namespace.o 22 22 obj-$(CONFIG_LEGACY_DIRECT_IO) += direct-io.o 23 23 obj-y += notify/
+1
fs/adfs/Kconfig
··· 2 2 config ADFS_FS 3 3 tristate "ADFS file system support" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 help 6 7 The Acorn Disc Filing System is the standard file system of the 7 8 RiscOS operating system which runs on Acorn's ARM-based Risc PC
+1
fs/affs/Kconfig
··· 2 2 config AFFS_FS 3 3 tristate "Amiga FFS file system support" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 select LEGACY_DIRECT_IO 6 7 help 7 8 The Fast File System (FFS) is the common file system used on hard
+1
fs/befs/Kconfig
··· 2 2 config BEFS_FS 3 3 tristate "BeOS file system (BeFS) support (read only)" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 select NLS 6 7 help 7 8 The BeOS File System (BeFS) is the native file system of Be, Inc's
+1
fs/bfs/Kconfig
··· 2 2 config BFS_FS 3 3 tristate "BFS file system support" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 help 6 7 Boot File System (BFS) is a file system used under SCO UnixWare to 7 8 allow the bootloader access to the kernel image and other important
+1
fs/efs/Kconfig
··· 2 2 config EFS_FS 3 3 tristate "EFS file system support (read only)" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 help 6 7 EFS is an older file system used for non-ISO9660 CD-ROMs and hard 7 8 disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer
+1
fs/exfat/Kconfig
··· 2 2 3 3 config EXFAT_FS 4 4 tristate "exFAT filesystem support" 5 + select BUFFER_HEAD 5 6 select NLS 6 7 select LEGACY_DIRECT_IO 7 8 help
+1
fs/ext2/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config EXT2_FS 3 3 tristate "Second extended fs support" 4 + select BUFFER_HEAD 4 5 select FS_IOMAP 5 6 select LEGACY_DIRECT_IO 6 7 help
+1
fs/ext4/Kconfig
··· 28 28 29 29 config EXT4_FS 30 30 tristate "The Extended 4 (ext4) filesystem" 31 + select BUFFER_HEAD 31 32 select JBD2 32 33 select CRC16 33 34 select CRYPTO
+1
fs/f2fs/Kconfig
··· 2 2 config F2FS_FS 3 3 tristate "F2FS filesystem support" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 select NLS 6 7 select CRYPTO 7 8 select CRYPTO_CRC32
+1
fs/fat/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config FAT_FS 3 3 tristate 4 + select BUFFER_HEAD 4 5 select NLS 5 6 select LEGACY_DIRECT_IO 6 7 help
+1
fs/freevxfs/Kconfig
··· 2 2 config VXFS_FS 3 3 tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 help 6 7 FreeVxFS is a file system driver that support the VERITAS VxFS(TM) 7 8 file system format. VERITAS VxFS(TM) is the standard file system
+1
fs/gfs2/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config GFS2_FS 3 3 tristate "GFS2 file system support" 4 + select BUFFER_HEAD 4 5 select FS_POSIX_ACL 5 6 select CRC32 6 7 select LIBCRC32C
+1
fs/hfs/Kconfig
··· 2 2 config HFS_FS 3 3 tristate "Apple Macintosh file system support" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 select NLS 6 7 select LEGACY_DIRECT_IO 7 8 help
+1
fs/hfsplus/Kconfig
··· 2 2 config HFSPLUS_FS 3 3 tristate "Apple Extended HFS file system support" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 select NLS 6 7 select NLS_UTF8 7 8 select LEGACY_DIRECT_IO
+1
fs/hpfs/Kconfig
··· 2 2 config HPFS_FS 3 3 tristate "OS/2 HPFS file system support" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 select FS_IOMAP 6 7 help 7 8 OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
+1
fs/isofs/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config ISO9660_FS 3 3 tristate "ISO 9660 CDROM file system support" 4 + select BUFFER_HEAD 4 5 help 5 6 This is the standard file system used on CD-ROMs. It was previously 6 7 known as "High Sierra File System" and is called "hsfs" on other
+1
fs/jfs/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config JFS_FS 3 3 tristate "JFS filesystem support" 4 + select BUFFER_HEAD 4 5 select NLS 5 6 select CRC32 6 7 select LEGACY_DIRECT_IO
+1
fs/minix/Kconfig
··· 2 2 config MINIX_FS 3 3 tristate "Minix file system support" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 help 6 7 Minix is a simple operating system used in many classes about OS's. 7 8 The minix file system (method to organize files on a hard disk
+1
fs/nilfs2/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config NILFS2_FS 3 3 tristate "NILFS2 file system support" 4 + select BUFFER_HEAD 4 5 select CRC32 5 6 select LEGACY_DIRECT_IO 6 7 help
+1
fs/ntfs/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config NTFS_FS 3 3 tristate "NTFS file system support" 4 + select BUFFER_HEAD 4 5 select NLS 5 6 help 6 7 NTFS is the file system of Microsoft Windows NT, 2000, XP and 2003.
+1
fs/ntfs3/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config NTFS3_FS 3 3 tristate "NTFS Read-Write file system support" 4 + select BUFFER_HEAD 4 5 select NLS 5 6 select LEGACY_DIRECT_IO 6 7 help
+1
fs/ocfs2/Kconfig
··· 2 2 config OCFS2_FS 3 3 tristate "OCFS2 file system support" 4 4 depends on INET && SYSFS && CONFIGFS_FS 5 + select BUFFER_HEAD 5 6 select JBD2 6 7 select CRC32 7 8 select QUOTA
+1
fs/omfs/Kconfig
··· 2 2 config OMFS_FS 3 3 tristate "SonicBlue Optimized MPEG File System support" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 select CRC_ITU_T 6 7 help 7 8 This is the proprietary file system used by the Rio Karma music
+1
fs/qnx4/Kconfig
··· 2 2 config QNX4FS_FS 3 3 tristate "QNX4 file system support (read only)" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 help 6 7 This is the file system used by the real-time operating systems 7 8 QNX 4 and QNX 6 (the latter is also called QNX RTP).
+1
fs/qnx6/Kconfig
··· 2 2 config QNX6FS_FS 3 3 tristate "QNX6 file system support (read only)" 4 4 depends on BLOCK && CRC32 5 + select BUFFER_HEAD 5 6 help 6 7 This is the file system used by the real-time operating systems 7 8 QNX 6 (also called QNX RTP).
+1
fs/reiserfs/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config REISERFS_FS 3 3 tristate "Reiserfs support (deprecated)" 4 + select BUFFER_HEAD 4 5 select CRC32 5 6 select LEGACY_DIRECT_IO 6 7 help
+1
fs/sysv/Kconfig
··· 2 2 config SYSV_FS 3 3 tristate "System V/Xenix/V7/Coherent file system support" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 help 6 7 SCO, Xenix and Coherent are commercial Unix systems for Intel 7 8 machines, and Version 7 was used on the DEC PDP-11. Saying Y
+1
fs/udf/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config UDF_FS 3 3 tristate "UDF file system support" 4 + select BUFFER_HEAD 4 5 select CRC_ITU_T 5 6 select NLS 6 7 select LEGACY_DIRECT_IO
+1
fs/ufs/Kconfig
··· 2 2 config UFS_FS 3 3 tristate "UFS file system support (read only)" 4 4 depends on BLOCK 5 + select BUFFER_HEAD 5 6 help 6 7 BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, 7 8 OpenBSD and NeXTstep) use a file system called UFS. Some System V
+16 -16
include/linux/buffer_head.h
··· 16 16 #include <linux/wait.h> 17 17 #include <linux/atomic.h> 18 18 19 - #ifdef CONFIG_BLOCK 20 - 21 19 enum bh_state_bits { 22 20 BH_Uptodate, /* Contains valid data */ 23 21 BH_Dirty, /* Is dirty */ ··· 196 198 struct page *page, unsigned long offset); 197 199 void folio_set_bh(struct buffer_head *bh, struct folio *folio, 198 200 unsigned long offset); 199 - bool try_to_free_buffers(struct folio *); 200 201 struct buffer_head *folio_alloc_buffers(struct folio *folio, unsigned long size, 201 202 bool retry); 202 203 struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size, ··· 210 213 211 214 /* Things to do with buffers at mapping->private_list */ 212 215 void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode); 213 - int inode_has_buffers(struct inode *); 214 - void invalidate_inode_buffers(struct inode *); 215 - int remove_inode_buffers(struct inode *inode); 216 - int sync_mapping_buffers(struct address_space *mapping); 217 216 int generic_buffers_fsync_noflush(struct file *file, loff_t start, loff_t end, 218 217 bool datasync); 219 218 int generic_buffers_fsync(struct file *file, loff_t start, loff_t end, ··· 233 240 void __breadahead(struct block_device *, sector_t block, unsigned int size); 234 241 struct buffer_head *__bread_gfp(struct block_device *, 235 242 sector_t block, unsigned size, gfp_t gfp); 236 - void invalidate_bh_lrus(void); 237 - void invalidate_bh_lrus_cpu(void); 238 - bool has_bh_in_lru(int cpu, void *dummy); 239 243 struct buffer_head *alloc_buffer_head(gfp_t gfp_flags); 240 244 void free_buffer_head(struct buffer_head * bh); 241 245 void unlock_buffer(struct buffer_head *bh); ··· 247 257 int __bh_read(struct buffer_head *bh, blk_opf_t op_flags, bool wait); 248 258 void __bh_read_batch(int nr, struct buffer_head *bhs[], 249 259 blk_opf_t op_flags, bool force_lock); 250 - 251 - extern int buffer_heads_over_limit; 252 260 253 261 /* 254 262 * Generic address_space_operations implementations for buffer_head-backed ··· 291 303 #define buffer_migrate_folio NULL 292 304 #define buffer_migrate_folio_norefs NULL 293 305 #endif 294 - 295 - void buffer_init(void); 296 306 297 307 /* 298 308 * inline definitions ··· 451 465 452 466 bool block_dirty_folio(struct address_space *mapping, struct folio *folio); 453 467 454 - #else /* CONFIG_BLOCK */ 468 + #ifdef CONFIG_BUFFER_HEAD 469 + 470 + void buffer_init(void); 471 + bool try_to_free_buffers(struct folio *folio); 472 + int inode_has_buffers(struct inode *inode); 473 + void invalidate_inode_buffers(struct inode *inode); 474 + int remove_inode_buffers(struct inode *inode); 475 + int sync_mapping_buffers(struct address_space *mapping); 476 + void invalidate_bh_lrus(void); 477 + void invalidate_bh_lrus_cpu(void); 478 + bool has_bh_in_lru(int cpu, void *dummy); 479 + extern int buffer_heads_over_limit; 480 + 481 + #else /* CONFIG_BUFFER_HEAD */ 455 482 456 483 static inline void buffer_init(void) {} 457 484 static inline bool try_to_free_buffers(struct folio *folio) { return true; } ··· 472 473 static inline void invalidate_inode_buffers(struct inode *inode) {} 473 474 static inline int remove_inode_buffers(struct inode *inode) { return 1; } 474 475 static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; } 476 + static inline void invalidate_bh_lrus(void) {} 475 477 static inline void invalidate_bh_lrus_cpu(void) {} 476 478 static inline bool has_bh_in_lru(int cpu, void *dummy) { return false; } 477 479 #define buffer_heads_over_limit 0 478 480 479 - #endif /* CONFIG_BLOCK */ 481 + #endif /* CONFIG_BUFFER_HEAD */ 480 482 #endif /* _LINUX_BUFFER_HEAD_H */
+4
include/linux/iomap.h
··· 58 58 #define IOMAP_F_DIRTY (1U << 1) 59 59 #define IOMAP_F_SHARED (1U << 2) 60 60 #define IOMAP_F_MERGED (1U << 3) 61 + #ifdef CONFIG_BUFFER_HEAD 61 62 #define IOMAP_F_BUFFER_HEAD (1U << 4) 63 + #else 64 + #define IOMAP_F_BUFFER_HEAD 0 65 + #endif /* CONFIG_BUFFER_HEAD */ 62 66 #define IOMAP_F_XATTR (1U << 5) 63 67 64 68 /*
+2
include/trace/events/block.h
··· 12 12 13 13 #define RWBS_LEN 8 14 14 15 + #ifdef CONFIG_BUFFER_HEAD 15 16 DECLARE_EVENT_CLASS(block_buffer, 16 17 17 18 TP_PROTO(struct buffer_head *bh), ··· 62 61 63 62 TP_ARGS(bh) 64 63 ); 64 + #endif /* CONFIG_BUFFER_HEAD */ 65 65 66 66 /** 67 67 * block_rq_requeue - place block IO request back on a queue
+2 -2
mm/migrate.c
··· 684 684 } 685 685 EXPORT_SYMBOL(migrate_folio); 686 686 687 - #ifdef CONFIG_BLOCK 687 + #ifdef CONFIG_BUFFER_HEAD 688 688 /* Returns true if all buffers are successfully locked */ 689 689 static bool buffer_migrate_lock_buffers(struct buffer_head *head, 690 690 enum migrate_mode mode) ··· 837 837 return __buffer_migrate_folio(mapping, dst, src, mode, true); 838 838 } 839 839 EXPORT_SYMBOL_GPL(buffer_migrate_folio_norefs); 840 - #endif 840 + #endif /* CONFIG_BUFFER_HEAD */ 841 841 842 842 int filemap_migrate_folio(struct address_space *mapping, 843 843 struct folio *dst, struct folio *src, enum migrate_mode mode)