--- x/kernel/ucount.c +++ y/kernel/ucount.c @@ -149,11 +149,18 @@ static void hlist_add_ucounts(struct uco struct ucounts *get_ucounts(struct ucounts *ucounts) { - if (ucounts && atomic_add_negative(1, &ucounts->count)) { - put_ucounts(ucounts); - ucounts = NULL; + int count; + + if (!ucounts) + return NULL; + + count = atomic_read(&ucounts->count); + + while (count > 0 && count + 1 > count) { + if (atomic_try_cmpxchg(&ucounts->count, &count, count + 1)) + return ucounts; } - return ucounts; + return NULL; } struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid) @@ -184,8 +191,8 @@ struct ucounts *alloc_ucounts(struct use return new; } } - spin_unlock_irq(&ucounts_lock); ucounts = get_ucounts(ucounts); + spin_unlock_irq(&ucounts_lock); return ucounts; }