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

ucounts: move kfree() out of critical zone protected by ucounts_lock

Although kfree is a non-sleep function, it is possible to enter a long
chain of calls probabilistically, so it looks better to move kfree from
alloc_ucounts() out of the critical zone of ucounts_lock.

Link: https://lkml.kernel.org/r/1733458427-11794-1-git-send-email-mengensun@tencent.com
Signed-off-by: MengEn Sun <mengensun@tencent.com>
Reviewed-by: YueHong Wu <yuehongwu@tencent.com>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Andrei Vagin <avagin@google.com>
Cc: Joel Granados <joel.granados@kernel.org>
Cc: Thomas Weißschuh <linux@weissschuh.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

MengEn Sun and committed by
Andrew Morton
f49b42d4 c7bb5cf9

+4 -4
+4 -4
kernel/ucount.c
··· 164 164 struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid) 165 165 { 166 166 struct hlist_head *hashent = ucounts_hashentry(ns, uid); 167 - struct ucounts *ucounts, *new; 168 167 bool wrapped; 168 + struct ucounts *ucounts, *new = NULL; 169 169 170 170 spin_lock_irq(&ucounts_lock); 171 171 ucounts = find_ucounts(ns, uid, hashent); ··· 182 182 183 183 spin_lock_irq(&ucounts_lock); 184 184 ucounts = find_ucounts(ns, uid, hashent); 185 - if (ucounts) { 186 - kfree(new); 187 - } else { 185 + if (!ucounts) { 188 186 hlist_add_head(&new->node, hashent); 189 187 get_user_ns(new->ns); 190 188 spin_unlock_irq(&ucounts_lock); 191 189 return new; 192 190 } 193 191 } 192 + 194 193 wrapped = !get_ucounts_or_wrap(ucounts); 195 194 spin_unlock_irq(&ucounts_lock); 195 + kfree(new); 196 196 if (wrapped) { 197 197 put_ucounts(ucounts); 198 198 return NULL;