#include <linux/rculist_nulls.h>
#include <linux/sched.h>
#include <linux/workqueue.h>
+#include <linux/rcuref.h>
#include <linux/rwsem.h>
#include <linux/sysctl.h>
#include <linux/err.h>
struct user_namespace *ns;
kuid_t uid;
struct rcu_head rcu;
- atomic_t count;
+ rcuref_t count;
atomic_long_t ucount[UCOUNT_COUNTS];
atomic_long_t rlimit[UCOUNT_RLIMIT_COUNTS];
};
struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, enum ucount_type type);
void dec_ucount(struct ucounts *ucounts, enum ucount_type type);
struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid);
-struct ucounts * __must_check get_ucounts(struct ucounts *ucounts);
void put_ucounts(struct ucounts *ucounts);
+static inline struct ucounts * __must_check get_ucounts(struct ucounts *ucounts)
+{
+ if (rcuref_get(&ucounts->count))
+ return ucounts;
+ return NULL;
+}
+
static inline long get_rlimit_value(struct ucounts *ucounts, enum rlimit_type type)
{
return atomic_long_read(&ucounts->rlimit[type]);
struct ucounts init_ucounts = {
.ns = &init_user_ns,
.uid = GLOBAL_ROOT_UID,
- .count = ATOMIC_INIT(1),
+ .count = RCUREF_INIT(1),
};
#define UCOUNTS_HASHTABLE_BITS 10
guard(rcu)();
hlist_nulls_for_each_entry_rcu(ucounts, pos, hashent, node) {
if (uid_eq(ucounts->uid, uid) && (ucounts->ns == ns)) {
- if (atomic_inc_not_zero(&ucounts->count))
+ if (rcuref_get(&ucounts->count))
return ucounts;
}
}
spin_unlock_irq(&ucounts_lock);
}
-struct ucounts *get_ucounts(struct ucounts *ucounts)
-{
- if (atomic_inc_not_zero(&ucounts->count))
- return ucounts;
- return NULL;
-}
-
struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
{
struct hlist_nulls_head *hashent = ucounts_hashentry(ns, uid);
new->ns = ns;
new->uid = uid;
- atomic_set(&new->count, 1);
+ rcuref_init(&new->count, 1);
spin_lock_irq(&ucounts_lock);
ucounts = find_ucounts(ns, uid, hashent);
{
unsigned long flags;
- if (atomic_dec_and_lock_irqsave(&ucounts->count, &ucounts_lock, flags)) {
+ if (rcuref_put(&ucounts->count)) {
+ spin_lock_irqsave(&ucounts_lock, flags);
hlist_nulls_del_rcu(&ucounts->node);
spin_unlock_irqrestore(&ucounts_lock, flags);