@@ -1931,6 +1931,7 @@ static int btrfs_init_btree_inode(struct super_block *sb)
inode->i_size = OFFSET_MAX;
inode->i_mapping->a_ops = &btree_aops;
mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
+ set_bit(AS_NO_MEMCG, &inode->i_mapping->flags);
extent_io_tree_init(fs_info, &BTRFS_I(inode)->io_tree,
IO_TREE_BTREE_INODE_IO);
@@ -209,6 +209,7 @@ enum mapping_flags {
AS_STABLE_WRITES, /* must wait for writeback before modifying
folio contents */
AS_UNMOVABLE, /* The mapping cannot be moved, ever */
+ AS_NO_MEMCG, /* No memcg should be applied to this address space .*/
};
/**
@@ -960,11 +960,17 @@ int filemap_add_folio(struct address_space *mapping, struct folio *folio,
pgoff_t index, gfp_t gfp)
{
void *shadow = NULL;
+ const bool no_memcg = test_bit(AS_NO_MEMCG, &mapping->flags);
int ret;
- ret = mem_cgroup_charge(folio, NULL, gfp);
- if (ret)
- return ret;
+ if (!no_memcg) {
+ ret = mem_cgroup_charge(folio, NULL, gfp);
+ if (ret)
+ return ret;
+ } else {
+ /* The page should not has any memcg set for it. */
+ VM_BUG_ON_FOLIO(folio_memcg(folio), folio);
+ }
__folio_set_locked(folio);
ret = __filemap_add_folio(mapping, folio, index, gfp, &shadow);
Currently any page/folio added to an address space will be accounted by memcg. However this is not always true for certain address spaces. One example is the address space of btrfs btree inode, which stores the metadata of one btrfs. Currently btrfs is using __GFP_NOFAIL for all operations touching that address space, but this can has other problems as __GFP_NOFAIL can wait infinitely until the request is met. To avoid unnecessary memcg charge for the btree inode address space, introduce a new flag, AS_NO_MEMCG, to inform that folios added to that address space should not trigger memcg charge/uncharge, and add btrfs btree inode to utilize that new flag. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/disk-io.c | 1 + include/linux/pagemap.h | 1 + mm/filemap.c | 12 +++++++++--- 3 files changed, 11 insertions(+), 3 deletions(-)