mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 17:57:38 -04:00
mm/memcg: remove no longer used swap cgroup array
Now all swap cgroup records are stored in the swap cluster directly, the static array is no longer needed. Link: https://lore.kernel.org/20260517-swap-table-p4-v5-11-88ae43e064c7@tencent.com Signed-off-by: Kairui Song <kasong@tencent.com> Acked-by: Chris Li <chrisl@kernel.org> Cc: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: Baoquan He <bhe@redhat.com> Cc: Barry Song <baohua@kernel.org> Cc: Chengming Zhou <chengming.zhou@linux.dev> Cc: David Hildenbrand <david@kernel.org> Cc: Hugh Dickins <hughd@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Kemeng Shi <shikemeng@huaweicloud.com> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Cc: Nhat Pham <nphamcs@gmail.com> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Shakeel Butt <shakeel.butt@linux.dev> Cc: Youngjun Park <youngjun.park@lge.com> Cc: Zi Yan <ziy@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
committed by
Andrew Morton
parent
b197d41462
commit
4e8e1c498d
@@ -6573,7 +6573,6 @@ F: mm/memcontrol.c
|
||||
F: mm/memcontrol-v1.c
|
||||
F: mm/memcontrol-v1.h
|
||||
F: mm/page_counter.c
|
||||
F: mm/swap_cgroup.c
|
||||
F: samples/cgroup/*
|
||||
F: tools/testing/selftests/cgroup/memcg_protection.m
|
||||
F: tools/testing/selftests/cgroup/test_hugetlb_memcg.c
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LINUX_SWAP_CGROUP_H
|
||||
#define __LINUX_SWAP_CGROUP_H
|
||||
|
||||
#include <linux/swap.h>
|
||||
|
||||
#if defined(CONFIG_MEMCG) && defined(CONFIG_SWAP)
|
||||
|
||||
extern void swap_cgroup_record(struct folio *folio, unsigned short id, swp_entry_t ent);
|
||||
extern unsigned short swap_cgroup_clear(swp_entry_t ent, unsigned int nr_ents);
|
||||
extern unsigned short lookup_swap_cgroup_id(swp_entry_t ent);
|
||||
extern int swap_cgroup_swapon(int type, unsigned long max_pages);
|
||||
extern void swap_cgroup_swapoff(int type);
|
||||
|
||||
#else
|
||||
|
||||
static inline
|
||||
void swap_cgroup_record(struct folio *folio, unsigned short id, swp_entry_t ent)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned short swap_cgroup_clear(swp_entry_t ent, unsigned int nr_ents)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned short lookup_swap_cgroup_id(swp_entry_t ent)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
swap_cgroup_swapon(int type, unsigned long max_pages)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void swap_cgroup_swapoff(int type)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_SWAP_CGROUP_H */
|
||||
@@ -103,9 +103,6 @@ obj-$(CONFIG_PAGE_COUNTER) += page_counter.o
|
||||
obj-$(CONFIG_LIVEUPDATE_MEMFD) += memfd_luo.o
|
||||
obj-$(CONFIG_MEMCG_V1) += memcontrol-v1.o
|
||||
obj-$(CONFIG_MEMCG) += memcontrol.o vmpressure.o
|
||||
ifdef CONFIG_SWAP
|
||||
obj-$(CONFIG_MEMCG) += swap_cgroup.o
|
||||
endif
|
||||
ifdef CONFIG_BPF_SYSCALL
|
||||
obj-$(CONFIG_MEMCG) += bpf_memcontrol.o
|
||||
endif
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <linux/rmap.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/leafops.h>
|
||||
#include <linux/swap_cgroup.h>
|
||||
#include <linux/tracepoint-defs.h>
|
||||
|
||||
/* Internal core VMA manipulation functions. */
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <linux/mm_inline.h>
|
||||
#include <linux/pagewalk.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/swap_cgroup.h>
|
||||
#include <linux/eventfd.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/sort.h>
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
#include <linux/vmpressure.h>
|
||||
#include <linux/memremap.h>
|
||||
#include <linux/mm_inline.h>
|
||||
#include <linux/swap_cgroup.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/oom.h>
|
||||
#include <linux/lockdep.h>
|
||||
|
||||
174
mm/swap_cgroup.c
174
mm/swap_cgroup.c
@@ -1,174 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/swap_cgroup.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <linux/swapops.h> /* depends on mm.h include */
|
||||
|
||||
static DEFINE_MUTEX(swap_cgroup_mutex);
|
||||
|
||||
/* Pack two cgroup id (short) of two entries in one swap_cgroup (atomic_t) */
|
||||
#define ID_PER_SC (sizeof(struct swap_cgroup) / sizeof(unsigned short))
|
||||
#define ID_SHIFT (BITS_PER_TYPE(unsigned short))
|
||||
#define ID_MASK (BIT(ID_SHIFT) - 1)
|
||||
struct swap_cgroup {
|
||||
atomic_t ids;
|
||||
};
|
||||
|
||||
struct swap_cgroup_ctrl {
|
||||
struct swap_cgroup *map;
|
||||
};
|
||||
|
||||
static struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES];
|
||||
|
||||
static unsigned short __swap_cgroup_id_lookup(struct swap_cgroup *map,
|
||||
pgoff_t offset)
|
||||
{
|
||||
unsigned int shift = (offset % ID_PER_SC) * ID_SHIFT;
|
||||
unsigned int old_ids = atomic_read(&map[offset / ID_PER_SC].ids);
|
||||
|
||||
BUILD_BUG_ON(!is_power_of_2(ID_PER_SC));
|
||||
BUILD_BUG_ON(sizeof(struct swap_cgroup) != sizeof(atomic_t));
|
||||
|
||||
return (old_ids >> shift) & ID_MASK;
|
||||
}
|
||||
|
||||
static unsigned short __swap_cgroup_id_xchg(struct swap_cgroup *map,
|
||||
pgoff_t offset,
|
||||
unsigned short new_id)
|
||||
{
|
||||
unsigned short old_id;
|
||||
struct swap_cgroup *sc = &map[offset / ID_PER_SC];
|
||||
unsigned int shift = (offset % ID_PER_SC) * ID_SHIFT;
|
||||
unsigned int new_ids, old_ids = atomic_read(&sc->ids);
|
||||
|
||||
do {
|
||||
old_id = (old_ids >> shift) & ID_MASK;
|
||||
new_ids = (old_ids & ~(ID_MASK << shift));
|
||||
new_ids |= ((unsigned int)new_id) << shift;
|
||||
} while (!atomic_try_cmpxchg(&sc->ids, &old_ids, new_ids));
|
||||
|
||||
return old_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* swap_cgroup_record - record mem_cgroup for a set of swap entries.
|
||||
* These entries must belong to one single folio, and that folio
|
||||
* must be being charged for swap space (swap out), and these
|
||||
* entries must not have been charged
|
||||
*
|
||||
* @folio: the folio that the swap entry belongs to
|
||||
* @id: mem_cgroup ID to be recorded
|
||||
* @ent: the first swap entry to be recorded
|
||||
*/
|
||||
void swap_cgroup_record(struct folio *folio, unsigned short id,
|
||||
swp_entry_t ent)
|
||||
{
|
||||
unsigned int nr_ents = folio_nr_pages(folio);
|
||||
struct swap_cgroup *map;
|
||||
pgoff_t offset, end;
|
||||
unsigned short old;
|
||||
|
||||
offset = swp_offset(ent);
|
||||
end = offset + nr_ents;
|
||||
map = swap_cgroup_ctrl[swp_type(ent)].map;
|
||||
|
||||
do {
|
||||
old = __swap_cgroup_id_xchg(map, offset, id);
|
||||
VM_BUG_ON(old);
|
||||
} while (++offset != end);
|
||||
}
|
||||
|
||||
/**
|
||||
* swap_cgroup_clear - clear mem_cgroup for a set of swap entries.
|
||||
* These entries must be being uncharged from swap. They either
|
||||
* belongs to one single folio in the swap cache (swap in for
|
||||
* cgroup v1), or no longer have any users (slot freeing).
|
||||
*
|
||||
* @ent: the first swap entry to be recorded into
|
||||
* @nr_ents: number of swap entries to be recorded
|
||||
*
|
||||
* Returns the existing old value.
|
||||
*/
|
||||
unsigned short swap_cgroup_clear(swp_entry_t ent, unsigned int nr_ents)
|
||||
{
|
||||
pgoff_t offset, end;
|
||||
struct swap_cgroup *map;
|
||||
unsigned short old, iter = 0;
|
||||
|
||||
offset = swp_offset(ent);
|
||||
end = offset + nr_ents;
|
||||
map = swap_cgroup_ctrl[swp_type(ent)].map;
|
||||
|
||||
do {
|
||||
old = __swap_cgroup_id_xchg(map, offset, 0);
|
||||
if (!iter)
|
||||
iter = old;
|
||||
VM_BUG_ON(iter != old);
|
||||
} while (++offset != end);
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* lookup_swap_cgroup_id - lookup mem_cgroup id tied to swap entry
|
||||
* @ent: swap entry to be looked up.
|
||||
*
|
||||
* Returns ID of mem_cgroup at success. 0 at failure. (0 is invalid ID)
|
||||
*/
|
||||
unsigned short lookup_swap_cgroup_id(swp_entry_t ent)
|
||||
{
|
||||
struct swap_cgroup_ctrl *ctrl;
|
||||
|
||||
if (mem_cgroup_disabled())
|
||||
return 0;
|
||||
|
||||
ctrl = &swap_cgroup_ctrl[swp_type(ent)];
|
||||
if (unlikely(!ctrl->map))
|
||||
return 0;
|
||||
return __swap_cgroup_id_lookup(ctrl->map, swp_offset(ent));
|
||||
}
|
||||
|
||||
int swap_cgroup_swapon(int type, unsigned long max_pages)
|
||||
{
|
||||
struct swap_cgroup *map;
|
||||
struct swap_cgroup_ctrl *ctrl;
|
||||
|
||||
if (mem_cgroup_disabled())
|
||||
return 0;
|
||||
|
||||
BUILD_BUG_ON(sizeof(unsigned short) * ID_PER_SC !=
|
||||
sizeof(struct swap_cgroup));
|
||||
map = vzalloc(DIV_ROUND_UP(max_pages, ID_PER_SC) *
|
||||
sizeof(struct swap_cgroup));
|
||||
if (!map)
|
||||
goto nomem;
|
||||
|
||||
ctrl = &swap_cgroup_ctrl[type];
|
||||
mutex_lock(&swap_cgroup_mutex);
|
||||
ctrl->map = map;
|
||||
mutex_unlock(&swap_cgroup_mutex);
|
||||
|
||||
return 0;
|
||||
nomem:
|
||||
pr_info("couldn't allocate enough memory for swap_cgroup\n");
|
||||
pr_info("swap_cgroup can be disabled by swapaccount=0 boot option\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void swap_cgroup_swapoff(int type)
|
||||
{
|
||||
struct swap_cgroup *map;
|
||||
struct swap_cgroup_ctrl *ctrl;
|
||||
|
||||
if (mem_cgroup_disabled())
|
||||
return;
|
||||
|
||||
mutex_lock(&swap_cgroup_mutex);
|
||||
ctrl = &swap_cgroup_ctrl[type];
|
||||
map = ctrl->map;
|
||||
ctrl->map = NULL;
|
||||
mutex_unlock(&swap_cgroup_mutex);
|
||||
|
||||
vfree(map);
|
||||
}
|
||||
@@ -45,7 +45,6 @@
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
#include <linux/leafops.h>
|
||||
#include <linux/swap_cgroup.h>
|
||||
#include "swap_table.h"
|
||||
#include "internal.h"
|
||||
#include "swap.h"
|
||||
@@ -3058,8 +3057,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
|
||||
p->global_cluster = NULL;
|
||||
kvfree(zeromap);
|
||||
free_swap_cluster_info(cluster_info, maxpages);
|
||||
/* Destroy swap account information */
|
||||
swap_cgroup_swapoff(p->type);
|
||||
|
||||
inode = mapping->host;
|
||||
|
||||
@@ -3590,10 +3587,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
||||
if (error)
|
||||
goto bad_swap_unlock_inode;
|
||||
|
||||
error = swap_cgroup_swapon(si->type, maxpages);
|
||||
if (error)
|
||||
goto bad_swap_unlock_inode;
|
||||
|
||||
/*
|
||||
* Use kvmalloc_array instead of bitmap_zalloc as the allocation order might
|
||||
* be above MAX_PAGE_ORDER incase of a large swap file.
|
||||
@@ -3704,7 +3697,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
||||
si->global_cluster = NULL;
|
||||
inode = NULL;
|
||||
destroy_swap_extents(si, swap_file);
|
||||
swap_cgroup_swapoff(si->type);
|
||||
free_swap_cluster_info(si->cluster_info, si->max);
|
||||
si->cluster_info = NULL;
|
||||
kvfree(si->zeromap);
|
||||
|
||||
Reference in New Issue
Block a user