Skip to content

Commit 8ed66e2

Browse files
kamalesh-babulaljfvogel
authored andcommitted
mm/memcontrol: Fix LRU reparenting logic when !MGLRU
The Multi-Gen LRU (MGLRU) is enabled by default via CONFIG_LRU_GEN_ENABLED=y, but it can be dynamically disabled by writing n to /sys/kernel/mm/lru_gen/enabled. While attempting to disable the MGLRU and switching over to the classic LRU (anon/file), the following crash is seen: >> trace #0 crash_setup_regs (./arch/x86/include/asm/kexec.h:111:15) #1 __crash_kexec (kernel/crash_core.c:122:4) #2 panic (kernel/panic.c:399:3) #3 oops_end (arch/x86/kernel/dumpstack.c:382:3) #4 do_trap_no_signal (arch/x86/kernel/traps.c:156:3) #5 do_trap (arch/x86/kernel/traps.c:197:7) #6 do_error_trap (arch/x86/kernel/traps.c:217:3) #7 handle_invalid_op (arch/x86/kernel/traps.c:254:2) #8 exc_invalid_op (arch/x86/kernel/traps.c:314:2) #9 asm_exc_invalid_op+0x1a/0x1f (./arch/x86/include/asm/idtentry.h:621) #10 __list_del_entry_valid_or_report (lib/list_debug.c:62:6) #11 __list_del_entry_valid (./include/linux/list.h:124:9) #12 __list_del_entry (./include/linux/list.h:215:7) #13 list_del (./include/linux/list.h:229:2) #14 lruvec_del_folio (./include/linux/mm_inline.h:361:3) #15 lru_activate (mm/swap.c:342:2) #16 folio_batch_move_lru (mm/swap.c:199:3) #17 lru_add_drain (mm/swap.c:734:2) #18 wp_can_reuse_anon_folio (mm/memory.c:3788:3) #19 do_wp_page (mm/memory.c:3900:39) #20 __handle_mm_fault (mm/memory.c:6090:9) #21 handle_mm_fault (mm/memory.c:6258:9) #22 do_user_addr_fault (arch/x86/mm/fault.c:1338:10) #23 handle_page_fault (arch/x86/mm/fault.c:1481:3) #24 exc_page_fault (arch/x86/mm/fault.c:1539:2) #25 asm_exc_page_fault+0x26/0x2b (./arch/x86/include/asm/idtentry.h:623) #26 0x7f82f0896ed2 The issue occurs because the MGLRU-specific version of lruvec_reparent_relocate() is invoked even when the system is using the classic LRU. Fix this, by ensuring the call is properly gated by lru_gen_enabled(), which checks whether MGLRU is enabled either statically via Kconfig or dynamically via the /sys interface. Orabug: 37920452 Fixes: cc65a5d ("mm: memcontrol: use obj_cgroup APIs to charge the LRU pages") Cc: Tom Hromatka <[email protected]> Reported-by: Sidhartha Kumar <[email protected]> Reviewed-by: Sidhartha Kumar <[email protected]> Reviewed-by: Harry Yoo <[email protected]> Tested-by: Harry Yoo <[email protected]> Reviewed-by: Imran Khan <[email protected]> Signed-off-by: Kamalesh Babulal <[email protected]> Signed-off-by: Harry Yoo <[email protected]>
1 parent bb4924b commit 8ed66e2

File tree

1 file changed

+38
-38
lines changed

1 file changed

+38
-38
lines changed

mm/memcontrol.c

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,48 @@ static void lruvec_reparent_lock(struct mem_cgroup *src, struct mem_cgroup *dst)
244244
for ((gen) = 0; (gen) < MAX_NR_GENS; (gen)++) \
245245
for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \
246246
for ((zone) = 0; (zone) < MAX_NR_ZONES; (zone)++)
247+
#endif
248+
249+
static void lruvec_reparent_lru(struct lruvec *src, struct lruvec *dst,
250+
enum lru_list lru)
251+
{
252+
int zid;
253+
struct mem_cgroup_per_node *mz_src, *mz_dst;
254+
255+
mz_src = container_of(src, struct mem_cgroup_per_node, lruvec);
256+
mz_dst = container_of(dst, struct mem_cgroup_per_node, lruvec);
257+
258+
if (lru != LRU_UNEVICTABLE)
259+
list_splice_tail_init(&src->lists[lru], &dst->lists[lru]);
260+
261+
for (zid = 0; zid < MAX_NR_ZONES; zid++) {
262+
mz_dst->lru_zone_size[zid][lru] += mz_src->lru_zone_size[zid][lru];
263+
mz_src->lru_zone_size[zid][lru] = 0;
264+
}
265+
}
247266

248267
static void lruvec_reparent_relocate(struct mem_cgroup *src, struct mem_cgroup *dst)
249268
{
250269
int nid;
251270

271+
if (!lru_gen_enabled()) {
272+
for_each_node(nid) {
273+
enum lru_list lru;
274+
struct lruvec *src_lruvec, *dst_lruvec;
275+
276+
src_lruvec = mem_cgroup_lruvec(src, NODE_DATA(nid));
277+
dst_lruvec = mem_cgroup_lruvec(dst, NODE_DATA(nid));
278+
279+
dst_lruvec->anon_cost += src_lruvec->anon_cost;
280+
dst_lruvec->file_cost += src_lruvec->file_cost;
281+
282+
for_each_lru(lru)
283+
lruvec_reparent_lru(src_lruvec, dst_lruvec, lru);
284+
}
285+
return;
286+
}
287+
288+
#ifdef CONFIG_LRU_GEN
252289
for_each_node(nid) {
253290
enum lru_list lru;
254291
int gen, type, zone, zid;
@@ -287,45 +324,8 @@ static void lruvec_reparent_relocate(struct mem_cgroup *src, struct mem_cgroup *
287324
}
288325
}
289326
}
290-
}
291-
#else
292-
static void lruvec_reparent_lru(struct lruvec *src, struct lruvec *dst,
293-
enum lru_list lru)
294-
{
295-
int zid;
296-
struct mem_cgroup_per_node *mz_src, *mz_dst;
297-
298-
mz_src = container_of(src, struct mem_cgroup_per_node, lruvec);
299-
mz_dst = container_of(dst, struct mem_cgroup_per_node, lruvec);
300-
301-
if (lru != LRU_UNEVICTABLE)
302-
list_splice_tail_init(&src->lists[lru], &dst->lists[lru]);
303-
304-
for (zid = 0; zid < MAX_NR_ZONES; zid++) {
305-
mz_dst->lru_zone_size[zid][lru] += mz_src->lru_zone_size[zid][lru];
306-
mz_src->lru_zone_size[zid][lru] = 0;
307-
}
308-
}
309-
310-
static void lruvec_reparent_relocate(struct mem_cgroup *src, struct mem_cgroup *dst)
311-
{
312-
int nid;
313-
314-
for_each_node(nid) {
315-
enum lru_list lru;
316-
struct lruvec *src_lruvec, *dst_lruvec;
317-
318-
src_lruvec = mem_cgroup_lruvec(src, NODE_DATA(nid));
319-
dst_lruvec = mem_cgroup_lruvec(dst, NODE_DATA(nid));
320-
321-
dst_lruvec->anon_cost += src_lruvec->anon_cost;
322-
dst_lruvec->file_cost += src_lruvec->file_cost;
323-
324-
for_each_lru(lru)
325-
lruvec_reparent_lru(src_lruvec, dst_lruvec, lru);
326-
}
327-
}
328327
#endif
328+
}
329329

330330
static void lruvec_reparent_unlock(struct mem_cgroup *src, struct mem_cgroup *dst)
331331
{

0 commit comments

Comments
 (0)