mm-shmem-make-unused-huge-shrinker-memcg-aware.patch removed from -mm tree
The quilt patch titled
Subject: mm: shmem: make unused huge shrinker memcg aware
has been removed from the -mm tree. Its filename was
mm-shmem-make-unused-huge-shrinker-memcg-aware.patch
This patch was dropped because it was merged into the mm-stable branch of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
------------------------------------------------------
From: Qi Zheng <[email protected]>
Subject: mm: shmem: make unused huge shrinker memcg aware
Date: Mon, 17 Aug 2026 17:03:28 +0800
The shmem unused huge shrinker keeps a per-superblock list of inodes whose tail huge folio extends beyond i_size. Since that list is not memcg aware, reclaim triggered by one memcg can scan inodes from the whole superblock and split shmem huge folios charged to unrelated memcgs.
Convert the shrink list to a memcg-aware list_lru. Queue each inode on the list_lru sublist matching the memcg and node of the current tail huge folio, so non-root memcg reclaim only walks candidates charged to the reclaiming memcg. Global reclaim, root memcg reclaim and shmem quota reclaim keep global semantics.
Rather than pinning a struct mem_cgroup reference in shmem_inode_info, store a struct obj_cgroup reference instead. The list_lru add and delete paths resolve the current memcg from the objcg under RCU, so that memcg offline and list_lru entry migration remain consistent: list_lru migrates entries to the parent memcg sublist on offline, and obj_cgroup_memcg() follows the same reparenting, ensuring the correct sublist is always found at delete time. This avoids pinning a dying memcg through a long-lived CSS reference.
The list_lru still tracks inodes while the actual split target is the current tail huge folio, so validate the folio memcg/node during scan. If the folio no longer matches the reclaim context or splitting cannot proceed, requeue the inode according to the current tail folio; if the inode is no longer shrinkable, drop the scan entry.
This can be tested with the shrinker debugfs interface by allocating 32 tmpfs tail THPs in each of two memcgs, then scanning the sb-tmpfs shrinker with memcg A's cgroup id:
before A scan after A scan base A=64M, B=64M A=64M, B=64M (per-memcg count is skipped) patched A=64M, B=64M A=0, B=64M
---
include/linux/shmem_fs.h | 12 - mm/shmem.c | 362 ++++++++++++++++++++++++++++--------- 2 files changed, 289 insertions(+), 85 deletions(-)
include/linux/shmem_fs.h renamed from include/linux/shmem_fs.h~mm-shmem-make-unused-huge-shrinker-memcg-aware +9 -3
@@ -11,6 +11,7 @@#include <linux/fs_parser.h> #include <linux/userfaultfd_k.h> #include <linux/bits.h> +#include <linux/list_lru.h> /* inode in-kernel data */
@@ -54,6 +55,11 @@ struct shmem_inode_info {struct dquot __rcu *i_dquot[MAXQUOTAS ];#endif struct inode vfs_inode; + +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +struct obj_cgroup *shrinklist_objcg; +int shrinklist_nid; +#endif };#define SHMEM_FL_USER_VISIBLE (FS_FL_USER_VISIBLE | FS_CASEFOLD_FL)
@@ -83,9 +89,9 @@ struct shmem_sb_info {ino_t next_ino;/* The next per-sb inode number to use */ ino_t __percpu *ino_batch;/* The next per-cpu inode number to use */ struct mempolicy *mpol;/* default memory policy for mappings */ -spinlock_t shrinklist_lock;/* Protects shrinklist */ -struct list_head shrinklist;/* List of shinkable inodes */ -unsigned long shrinklist_len;/* Length of shrinklist */ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +struct list_lru shrinklist;/* List of shrinkable inodes */ +#endif struct shmem_quota_limits qlimits;/* Default quota limits */ struct simple_xattr_cache xa_cache; };
mm/shmem.c renamed from mm/shmem.c~mm-shmem-make-unused-huge-shrinker-memcg-aware +280 -82
466 lines not on this page · raw message
_
Patches currently in -mm which might be from [email protected] are