The patch titled Subject: mm: swap_cgroup: allocate swap_cgroup map using vcalloc() has been added to the -mm mm-unstable branch. Its filename is mm-swap_cgroup-allocate-swap_cgroup-map-using-vcalloc.patch This patch will shortly appear at https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/mm-swap_cgroup-allocate-swap_cgroup-map-using-vcalloc.patch This patch will later appear in the mm-unstable branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next via the mm-everything branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm and is updated there every 2-3 working days ------------------------------------------------------ From: Roman Gushchin <roman.gushchin@xxxxxxxxx> Subject: mm: swap_cgroup: allocate swap_cgroup map using vcalloc() Date: Fri, 15 Nov 2024 19:02:28 +0000 Currently swap_cgroup's map is constructed as a vmalloc()'s-based array of pointers to individual struct pages. This brings an unnecessary complexity into the code. This patch turns the swap_cgroup's map into a single space allocated by vcalloc(). Link: https://lkml.kernel.org/r/20241115190229.676440-1-roman.gushchin@xxxxxxxxx Signed-off-by: Roman Gushchin <roman.gushchin@xxxxxxxxx> Acked-by: Shakeel Butt <shakeel.butt@xxxxxxxxx> Cc: Johannes Weiner <hannes@xxxxxxxxxxx> Cc: Michal Hocko <mhocko@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- mm/swap_cgroup.c | 83 +++++++-------------------------------------- 1 file changed, 13 insertions(+), 70 deletions(-) --- a/mm/swap_cgroup.c~mm-swap_cgroup-allocate-swap_cgroup-map-using-vcalloc +++ a/mm/swap_cgroup.c @@ -6,17 +6,18 @@ #include <linux/swapops.h> /* depends on mm.h include */ static DEFINE_MUTEX(swap_cgroup_mutex); + +struct swap_cgroup { + unsigned short id; +}; + struct swap_cgroup_ctrl { - struct page **map; - unsigned long length; + struct swap_cgroup *map; spinlock_t lock; }; static struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES]; -struct swap_cgroup { - unsigned short id; -}; #define SC_PER_PAGE (PAGE_SIZE/sizeof(struct swap_cgroup)) /* @@ -33,44 +34,10 @@ struct swap_cgroup { * TODO: we can push these buffers out to HIGHMEM. */ -/* - * allocate buffer for swap_cgroup. - */ -static int swap_cgroup_prepare(int type) -{ - struct page *page; - struct swap_cgroup_ctrl *ctrl; - unsigned long idx, max; - - ctrl = &swap_cgroup_ctrl[type]; - - for (idx = 0; idx < ctrl->length; idx++) { - page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!page) - goto not_enough_page; - ctrl->map[idx] = page; - - if (!(idx % SWAP_CLUSTER_MAX)) - cond_resched(); - } - return 0; -not_enough_page: - max = idx; - for (idx = 0; idx < max; idx++) - __free_page(ctrl->map[idx]); - - return -ENOMEM; -} - static struct swap_cgroup *__lookup_swap_cgroup(struct swap_cgroup_ctrl *ctrl, pgoff_t offset) { - struct page *mappage; - struct swap_cgroup *sc; - - mappage = ctrl->map[offset / SC_PER_PAGE]; - sc = page_address(mappage); - return sc + offset % SC_PER_PAGE; + return &ctrl->map[offset]; } static struct swap_cgroup *lookup_swap_cgroup(swp_entry_t ent, @@ -168,32 +135,20 @@ unsigned short lookup_swap_cgroup_id(swp int swap_cgroup_swapon(int type, unsigned long max_pages) { - void *array; - unsigned long length; + struct swap_cgroup *map; struct swap_cgroup_ctrl *ctrl; if (mem_cgroup_disabled()) return 0; - length = DIV_ROUND_UP(max_pages, SC_PER_PAGE); - - array = vcalloc(length, sizeof(void *)); - if (!array) + map = vcalloc(max_pages, sizeof(struct swap_cgroup)); + if (!map) goto nomem; ctrl = &swap_cgroup_ctrl[type]; mutex_lock(&swap_cgroup_mutex); - ctrl->length = length; - ctrl->map = array; + ctrl->map = map; spin_lock_init(&ctrl->lock); - if (swap_cgroup_prepare(type)) { - /* memory shortage */ - ctrl->map = NULL; - ctrl->length = 0; - mutex_unlock(&swap_cgroup_mutex); - vfree(array); - goto nomem; - } mutex_unlock(&swap_cgroup_mutex); return 0; @@ -205,8 +160,7 @@ nomem: void swap_cgroup_swapoff(int type) { - struct page **map; - unsigned long i, length; + struct swap_cgroup *map; struct swap_cgroup_ctrl *ctrl; if (mem_cgroup_disabled()) @@ -215,19 +169,8 @@ void swap_cgroup_swapoff(int type) mutex_lock(&swap_cgroup_mutex); ctrl = &swap_cgroup_ctrl[type]; map = ctrl->map; - length = ctrl->length; ctrl->map = NULL; - ctrl->length = 0; mutex_unlock(&swap_cgroup_mutex); - if (map) { - for (i = 0; i < length; i++) { - struct page *page = map[i]; - if (page) - __free_page(page); - if (!(i % SWAP_CLUSTER_MAX)) - cond_resched(); - } - vfree(map); - } + kvfree(map); } _ Patches currently in -mm which might be from roman.gushchin@xxxxxxxxx are mm-swap_cgroup-allocate-swap_cgroup-map-using-vcalloc.patch mm-swap_cgroup-get-rid-of-__lookup_swap_cgroup.patch