FAILED: patch "[PATCH] getrusage: use sig->stats_lock rather than" failed to apply to 4.19-stable tree
[email protected]
maintainerThe patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-4.19.y
git checkout FETCH_HEAD
git cherry-pick -x f7ec1cd5cc7ef3ad964b677ba82b8b77f1c93009
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2024021941-showman-diaper-6105@gregkh' --subject-prefix 'PATCH 4.19.y' HEAD^..
Possible dependencies:
f7ec1cd5cc7e ("getrusage: use sig->stats_lock rather than lock_task_sighand()") daa694e41375 ("getrusage: move thread_group_cputime_adjusted() outside of lock_task_sighand()") 13b7bc60b535 ("getrusage: use __for_each_thread()")c7ac8231ace9 ("getrusage: add the "signal_struct *sig" local variable") bdd565f817a7 ("y2038: rusage: use __kernel_old_timeval")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From f7ec1cd5cc7ef3ad964b677ba82b8b77f1c93009 Mon Sep 17 00:00:00 2001
From: Oleg Nesterov <[email protected]>
Date: Mon, 22 Jan 2024 16:50:53 +0100
Subject: [PATCH] getrusage: use sig->stats_lock rather than
lock_task_sighand()
lock_task_sighand() can trigger a hard lockup. If NR_CPUS threads call getrusage() at the same time and the process has NR_THREADS, spin_lock_irq will spin with irqs disabled O(NR_CPUS * NR_THREADS) time.
Change getrusage() to use sig->stats_lock, it was specifically designed for this type of use. This way it runs lockless in the likely case.
TODO:
- Change do_task_stat() to use sig->stats_lock too, then we can remove spin_lock_irq(siglock) in wait_task_zombie().
- Turn sig->stats_lock into seqcount_rwlock_t, this way the readers in the slow mode won't exclude each other. See
https://lore.kernel.org/all/[email protected]/
- stats_lock has to disable irqs because ->siglock can be taken in irq context, it would be very nice to change __exit_signal() to avoid the siglock->stats_lock dependency.
kernel/sys.c +13 -3
@@ -1788,7 +1788,9 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)unsigned long maxrss;struct mm_struct *mm;struct signal_struct *sig = p->signal; +unsigned int seq =0 ; +retry:memset (r,0 ,sizeof (*r)); utime = stime =0 ; maxrss =0 ;
@@ -1800,8 +1802,7 @@ void getrusage(struct task_struct *p, int who, struct rusage *r) goto out_thread; } -if (!lock_task_sighand (p, &flags)) -return ; + flags =read_seqbegin_or_lock_irqsave (&sig->stats_lock, &seq);switch (who) {case RUSAGE_BOTH :
@@ -1829,14 +1830,23 @@ void getrusage(struct task_struct *p, int who, struct rusage *r) r->ru_oublock += sig->oublock;if (maxrss < sig->maxrss) maxrss = sig->maxrss; + +rcu_read_lock ();__for_each_thread (sig, t)accumulate_thread_rusage (t, r); +rcu_read_unlock (); +break ;default :BUG (); } -unlock_task_sighand (p, &flags); + +if (need_seqretry (&sig->stats_lock, seq)) { + seq =1 ; + goto retry; + } +done_seqretry_irqrestore (&sig->stats_lock, seq, flags);if (who ==RUSAGE_CHILDREN ) goto out_children;