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

Configure Feed

Select the types of activity you want to include in your feed.

fs: Ignore inode metadata buffers in inode_lru_isolate()

There are only a few filesystems that use generic tracking of inode
metadata buffer heads. As such the logic to reclaim tracked metadata
buffer heads in inode_lru_isolate() doesn't bring a benefit big enough
to justify intertwining of inode reclaim and metadata buffer head
tracking. Just treat tracked metadata buffer heads as any other metadata
filesystem has to properly clean up on inode eviction and stop handling
it in inode_lru_isolate(). As a result filesystems using generic
tracking of metadata buffer heads may now see dirty metadata buffers in
their .evict methods more often which can slow down inode reclaim but
given these filesystems aren't used in performance demanding setups we
should be fine.

Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20260326095354.16340-64-jack@suse.cz
Tested-by: syzbot@syzkaller.appspotmail.com
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Jan Kara and committed by
Christian Brauner
972b9dd4 23dae9e1

+9 -44
-29
fs/buffer.c
··· 879 879 EXPORT_SYMBOL(invalidate_inode_buffers); 880 880 881 881 /* 882 - * Remove any clean buffers from the inode's buffer list. This is called 883 - * when we're trying to free the inode itself. Those buffers can pin it. 884 - * 885 - * Returns true if all buffers were removed. 886 - */ 887 - int remove_inode_buffers(struct inode *inode) 888 - { 889 - int ret = 1; 890 - 891 - if (inode_has_buffers(inode)) { 892 - struct address_space *mapping = &inode->i_data; 893 - struct list_head *list = &mapping->i_private_list; 894 - struct address_space *buffer_mapping = mapping->i_private_data; 895 - 896 - spin_lock(&buffer_mapping->i_private_lock); 897 - while (!list_empty(list)) { 898 - struct buffer_head *bh = BH_ENTRY(list->next); 899 - if (buffer_dirty(bh)) { 900 - ret = 0; 901 - break; 902 - } 903 - __remove_assoc_queue(bh); 904 - } 905 - spin_unlock(&buffer_mapping->i_private_lock); 906 - } 907 - return ret; 908 - } 909 - 910 - /* 911 882 * Create the appropriate buffers when given a folio for data area and 912 883 * the size of each buffer.. Use the bh->b_this_page linked list to 913 884 * follow the buffers created. Return NULL if unable to create more
+9 -12
fs/inode.c
··· 17 17 #include <linux/fsverity.h> 18 18 #include <linux/mount.h> 19 19 #include <linux/posix_acl.h> 20 - #include <linux/buffer_head.h> /* for inode_has_buffers */ 21 20 #include <linux/ratelimit.h> 22 21 #include <linux/list_lru.h> 23 22 #include <linux/iversion.h> ··· 366 367 367 368 void __destroy_inode(struct inode *inode) 368 369 { 369 - BUG_ON(inode_has_buffers(inode)); 370 370 inode_detach_wb(inode); 371 371 security_inode_free(inode); 372 372 fsnotify_inode_delete(inode); ··· 992 994 * page cache in order to free up struct inodes: lowmem might 993 995 * be under pressure before the cache inside the highmem zone. 994 996 */ 995 - if (inode_has_buffers(inode) || !mapping_empty(&inode->i_data)) { 997 + if (!mapping_empty(&inode->i_data)) { 998 + unsigned long reap; 999 + 996 1000 inode_pin_lru_isolating(inode); 997 1001 spin_unlock(&inode->i_lock); 998 1002 spin_unlock(&lru->lock); 999 - if (remove_inode_buffers(inode)) { 1000 - unsigned long reap; 1001 - reap = invalidate_mapping_pages(&inode->i_data, 0, -1); 1002 - if (current_is_kswapd()) 1003 - __count_vm_events(KSWAPD_INODESTEAL, reap); 1004 - else 1005 - __count_vm_events(PGINODESTEAL, reap); 1006 - mm_account_reclaimed_pages(reap); 1007 - } 1003 + reap = invalidate_mapping_pages(&inode->i_data, 0, -1); 1004 + if (current_is_kswapd()) 1005 + __count_vm_events(KSWAPD_INODESTEAL, reap); 1006 + else 1007 + __count_vm_events(PGINODESTEAL, reap); 1008 + mm_account_reclaimed_pages(reap); 1008 1009 inode_unpin_lru_isolating(inode); 1009 1010 return LRU_RETRY; 1010 1011 }
-3
include/linux/buffer_head.h
··· 517 517 bool try_to_free_buffers(struct folio *folio); 518 518 int inode_has_buffers(struct inode *inode); 519 519 void invalidate_inode_buffers(struct inode *inode); 520 - int remove_inode_buffers(struct inode *inode); 521 520 int sync_mapping_buffers(struct address_space *mapping); 522 521 void invalidate_bh_lrus(void); 523 522 void invalidate_bh_lrus_cpu(void); ··· 527 528 528 529 static inline void buffer_init(void) {} 529 530 static inline bool try_to_free_buffers(struct folio *folio) { return true; } 530 - static inline int inode_has_buffers(struct inode *inode) { return 0; } 531 531 static inline void invalidate_inode_buffers(struct inode *inode) {} 532 - static inline int remove_inode_buffers(struct inode *inode) { return 1; } 533 532 static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; } 534 533 static inline void invalidate_bh_lrus(void) {} 535 534 static inline void invalidate_bh_lrus_cpu(void) {}