Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

memcg: mm_update_next_owner: move for_each_thread() into try_to_set_owner()

mm_update_next_owner() checks the children / real_parent->children to
avoid the "everything else" loop in the likely case, but this won't work
if a child/sibling has a zombie leader with ->mm == NULL.

Move the for_each_thread() logic into try_to_set_owner(), if nothing else
this makes the children/siblings/everything searches more consistent.

Link: https://lkml.kernel.org/r/20240626152930.GA17936@redhat.com
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jinliang Zheng <alexjlzheng@tencent.com>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Tycho Andersen <tandersen@netflix.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Oleg Nesterov and committed by
Andrew Morton
d73d0035 2a22b773

+24 -16
+24 -16
kernel/exit.c
··· 440 440 441 441 #ifdef CONFIG_MEMCG 442 442 /* drops tasklist_lock if succeeds */ 443 - static bool try_to_set_owner(struct task_struct *tsk, struct mm_struct *mm) 443 + static bool __try_to_set_owner(struct task_struct *tsk, struct mm_struct *mm) 444 444 { 445 445 bool ret = false; 446 446 ··· 456 456 return ret; 457 457 } 458 458 459 + static bool try_to_set_owner(struct task_struct *g, struct mm_struct *mm) 460 + { 461 + struct task_struct *t; 462 + 463 + for_each_thread(g, t) { 464 + struct mm_struct *t_mm = READ_ONCE(t->mm); 465 + if (t_mm == mm) { 466 + if (__try_to_set_owner(t, mm)) 467 + return true; 468 + } else if (t_mm) 469 + break; 470 + } 471 + 472 + return false; 473 + } 474 + 459 475 /* 460 476 * A task is exiting. If it owned this mm, find a new owner for the mm. 461 477 */ 462 478 void mm_update_next_owner(struct mm_struct *mm) 463 479 { 464 - struct task_struct *c, *g, *p = current; 480 + struct task_struct *g, *p = current; 465 481 466 482 /* 467 483 * If the exiting or execing task is not the owner, it's ··· 499 483 /* 500 484 * Search in the children 501 485 */ 502 - list_for_each_entry(c, &p->children, sibling) { 503 - if (c->mm == mm && try_to_set_owner(c, mm)) 486 + list_for_each_entry(g, &p->children, sibling) { 487 + if (try_to_set_owner(g, mm)) 504 488 goto ret; 505 489 } 506 - 507 490 /* 508 491 * Search in the siblings 509 492 */ 510 - list_for_each_entry(c, &p->real_parent->children, sibling) { 511 - if (c->mm == mm && try_to_set_owner(c, mm)) 493 + list_for_each_entry(g, &p->real_parent->children, sibling) { 494 + if (try_to_set_owner(g, mm)) 512 495 goto ret; 513 496 } 514 - 515 497 /* 516 498 * Search through everything else, we should not get here often. 517 499 */ ··· 518 504 break; 519 505 if (g->flags & PF_KTHREAD) 520 506 continue; 521 - for_each_thread(g, c) { 522 - struct mm_struct *c_mm = READ_ONCE(c->mm); 523 - if (c_mm == mm) { 524 - if (try_to_set_owner(c, mm)) 525 - goto ret; 526 - } else if (c_mm) 527 - break; 528 - } 507 + if (try_to_set_owner(g, mm)) 508 + goto ret; 529 509 } 530 510 read_unlock(&tasklist_lock); 531 511 /*