Skip to content

Commit ab9041a

Browse files
Sebastian Andrzej Siewiorakpm00
Sebastian Andrzej Siewior
authored andcommitted
ucount: use rcuref_t for reference counting
Use rcuref_t for reference counting. This eliminates the cmpxchg loop in the get and put path. This also eliminates the need to acquire the lock in the put path because once the final user returns the reference, it can no longer be obtained anymore. Use rcuref_t for reference counting. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Reviewed-by: Paul E. McKenney <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Boqun Feng <[email protected]> Cc: Joel Fernandes <[email protected]> Cc: Josh Triplett <[email protected]> Cc: Lai jiangshan <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Mengen Sun <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: "Uladzislau Rezki (Sony)" <[email protected]> Cc: YueHong Wu <[email protected]> Cc: Zqiang <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 6a37e36 commit ab9041a

File tree

2 files changed

+14
-13
lines changed

2 files changed

+14
-13
lines changed

include/linux/user_namespace.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/rculist_nulls.h>
99
#include <linux/sched.h>
1010
#include <linux/workqueue.h>
11+
#include <linux/rcuref.h>
1112
#include <linux/rwsem.h>
1213
#include <linux/sysctl.h>
1314
#include <linux/err.h>
@@ -120,7 +121,7 @@ struct ucounts {
120121
struct user_namespace *ns;
121122
kuid_t uid;
122123
struct rcu_head rcu;
123-
atomic_t count;
124+
rcuref_t count;
124125
atomic_long_t ucount[UCOUNT_COUNTS];
125126
atomic_long_t rlimit[UCOUNT_RLIMIT_COUNTS];
126127
};
@@ -133,9 +134,15 @@ void retire_userns_sysctls(struct user_namespace *ns);
133134
struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, enum ucount_type type);
134135
void dec_ucount(struct ucounts *ucounts, enum ucount_type type);
135136
struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid);
136-
struct ucounts * __must_check get_ucounts(struct ucounts *ucounts);
137137
void put_ucounts(struct ucounts *ucounts);
138138

139+
static inline struct ucounts * __must_check get_ucounts(struct ucounts *ucounts)
140+
{
141+
if (rcuref_get(&ucounts->count))
142+
return ucounts;
143+
return NULL;
144+
}
145+
139146
static inline long get_rlimit_value(struct ucounts *ucounts, enum rlimit_type type)
140147
{
141148
return atomic_long_read(&ucounts->rlimit[type]);

kernel/ucount.c

+5-11
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
struct ucounts init_ucounts = {
1212
.ns = &init_user_ns,
1313
.uid = GLOBAL_ROOT_UID,
14-
.count = ATOMIC_INIT(1),
14+
.count = RCUREF_INIT(1),
1515
};
1616

1717
#define UCOUNTS_HASHTABLE_BITS 10
@@ -138,7 +138,7 @@ static struct ucounts *find_ucounts(struct user_namespace *ns, kuid_t uid,
138138
guard(rcu)();
139139
hlist_nulls_for_each_entry_rcu(ucounts, pos, hashent, node) {
140140
if (uid_eq(ucounts->uid, uid) && (ucounts->ns == ns)) {
141-
if (atomic_inc_not_zero(&ucounts->count))
141+
if (rcuref_get(&ucounts->count))
142142
return ucounts;
143143
}
144144
}
@@ -154,13 +154,6 @@ static void hlist_add_ucounts(struct ucounts *ucounts)
154154
spin_unlock_irq(&ucounts_lock);
155155
}
156156

157-
struct ucounts *get_ucounts(struct ucounts *ucounts)
158-
{
159-
if (atomic_inc_not_zero(&ucounts->count))
160-
return ucounts;
161-
return NULL;
162-
}
163-
164157
struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
165158
{
166159
struct hlist_nulls_head *hashent = ucounts_hashentry(ns, uid);
@@ -176,7 +169,7 @@ struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
176169

177170
new->ns = ns;
178171
new->uid = uid;
179-
atomic_set(&new->count, 1);
172+
rcuref_init(&new->count, 1);
180173

181174
spin_lock_irq(&ucounts_lock);
182175
ucounts = find_ucounts(ns, uid, hashent);
@@ -196,7 +189,8 @@ void put_ucounts(struct ucounts *ucounts)
196189
{
197190
unsigned long flags;
198191

199-
if (atomic_dec_and_lock_irqsave(&ucounts->count, &ucounts_lock, flags)) {
192+
if (rcuref_put(&ucounts->count)) {
193+
spin_lock_irqsave(&ucounts_lock, flags);
200194
hlist_nulls_del_rcu(&ucounts->node);
201195
spin_unlock_irqrestore(&ucounts_lock, flags);
202196

0 commit comments

Comments
 (0)