]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mm: swap_cgroup: allocate swap_cgroup map using vcalloc()
authorRoman Gushchin <roman.gushchin@linux.dev>
Fri, 15 Nov 2024 19:02:28 +0000 (19:02 +0000)
committerAndrew Morton <akpm@linux-foundation.org>
Tue, 14 Jan 2025 06:40:40 +0000 (22:40 -0800)
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().

[akpm@linux-foundation.org: s/vfree/kvfree/, per Shakeel]
Link: https://lkml.kernel.org/r/20241115190229.676440-1-roman.gushchin@linux.dev
Signed-off-by: Roman Gushchin <roman.gushchin@linux.dev>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/swap_cgroup.c

index da1278f0563bc101776aeb7ceda0a3a96c50db4a..76f645537e9611aabf93409cebeee5b5bdccc1df 100644 (file)
@@ -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_entry_t ent)
 
 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);
-       }
+       vfree(map);
 }