Linux RCU subsystem development
 help / color / mirror / Atom feed
* [PATCH 0/4] ucount: Simplify refcounting with rcuref_t.
@ 2025-02-03 15:05 Sebastian Andrzej Siewior
  2025-02-03 15:05 ` [PATCH 1/4] rcu: Provide a static initializer for hlist_nulls_head Sebastian Andrzej Siewior
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-02-03 15:05 UTC (permalink / raw)
  To: linux-kernel, rcu
  Cc: Andrew Morton, MengEn Sun, Thomas Gleixner, YueHong Wu,
	Paul E. McKenney, Joel Fernandes, Josh Triplett, Boqun Feng,
	Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
	Lai Jiangshan, Zqiang, Sebastian Andrzej Siewior

I noticed that the atomic_dec_and_lock_irqsave() in put_ucounts() loops
sometimes even during boot. Something like 2-3 iterations but still.
This series replaces the refcounting with rcuref_t and adds a RCU
lookup.
This allows a lockless lookup in alloc_ucounts() if the entry is
available and a cmpxchg()less put of the item.

Patch #1 adds HLIST_NULLS_HEAD_INIT for which I added the RCU folks.

Sebastian

Sebastian Andrzej Siewior (4):
  rcu: Provide a static initializer for hlist_nulls_head.
  ucount: Replace get_ucounts_or_wrap() with atomic_inc_not_zero().
  ucount: Use RCU for ucounts lookups.
  ucount: Use rcuref_t for reference counting.

 include/linux/list_nulls.h     |  1 +
 include/linux/user_namespace.h | 15 ++++--
 kernel/ucount.c                | 97 +++++++++++++++-------------------
 3 files changed, 55 insertions(+), 58 deletions(-)

-- 
2.47.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] rcu: Provide a static initializer for hlist_nulls_head.
  2025-02-03 15:05 [PATCH 0/4] ucount: Simplify refcounting with rcuref_t Sebastian Andrzej Siewior
@ 2025-02-03 15:05 ` Sebastian Andrzej Siewior
  2025-02-03 15:05 ` [PATCH 2/4] ucount: Replace get_ucounts_or_wrap() with atomic_inc_not_zero() Sebastian Andrzej Siewior
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-02-03 15:05 UTC (permalink / raw)
  To: linux-kernel, rcu
  Cc: Andrew Morton, MengEn Sun, Thomas Gleixner, YueHong Wu,
	Paul E. McKenney, Joel Fernandes, Josh Triplett, Boqun Feng,
	Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
	Lai Jiangshan, Zqiang, Sebastian Andrzej Siewior

Provide a static initializer for hlist_nulls_head so that it can be used
in statically defined data structures.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 include/linux/list_nulls.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/list_nulls.h b/include/linux/list_nulls.h
index fa6e8471bd227..248db9b77ee24 100644
--- a/include/linux/list_nulls.h
+++ b/include/linux/list_nulls.h
@@ -28,6 +28,7 @@ struct hlist_nulls_node {
 #define NULLS_MARKER(value) (1UL | (((long)value) << 1))
 #define INIT_HLIST_NULLS_HEAD(ptr, nulls) \
 	((ptr)->first = (struct hlist_nulls_node *) NULLS_MARKER(nulls))
+#define HLIST_NULLS_HEAD_INIT(nulls) {.first = (struct hlist_nulls_node *)NULLS_MARKER(nulls)}
 
 #define hlist_nulls_entry(ptr, type, member) container_of(ptr,type,member)
 
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] ucount: Replace get_ucounts_or_wrap() with atomic_inc_not_zero().
  2025-02-03 15:05 [PATCH 0/4] ucount: Simplify refcounting with rcuref_t Sebastian Andrzej Siewior
  2025-02-03 15:05 ` [PATCH 1/4] rcu: Provide a static initializer for hlist_nulls_head Sebastian Andrzej Siewior
@ 2025-02-03 15:05 ` Sebastian Andrzej Siewior
  2025-02-03 15:05 ` [PATCH 3/4] ucount: Use RCU for ucounts lookups Sebastian Andrzej Siewior
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-02-03 15:05 UTC (permalink / raw)
  To: linux-kernel, rcu
  Cc: Andrew Morton, MengEn Sun, Thomas Gleixner, YueHong Wu,
	Paul E. McKenney, Joel Fernandes, Josh Triplett, Boqun Feng,
	Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
	Lai Jiangshan, Zqiang, Sebastian Andrzej Siewior

get_ucounts_or_wrap() increments the counter and if the counter is
negative then it decrements it again in order to reset the previous increment.
This statement can be replaced with atomic_inc_not_zero() to only
increment the counter if it is not yet 0.
This simplifies the get function because the put (if the get failed) can
be removed. atomic_inc_not_zero() is implement as a cmpxchg() loop which
can be repeated several times if another get/put is performed in parallel. This
will be optimized later.

Increment the reference counter only if not yet dropped to zero.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 kernel/ucount.c | 24 ++++++------------------
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/kernel/ucount.c b/kernel/ucount.c
index 86c5f1c0bad90..4aa5011538257 100644
--- a/kernel/ucount.c
+++ b/kernel/ucount.c
@@ -146,25 +146,16 @@ static void hlist_add_ucounts(struct ucounts *ucounts)
 	spin_unlock_irq(&ucounts_lock);
 }
 
-static inline bool get_ucounts_or_wrap(struct ucounts *ucounts)
-{
-	/* Returns true on a successful get, false if the count wraps. */
-	return !atomic_add_negative(1, &ucounts->count);
-}
-
 struct ucounts *get_ucounts(struct ucounts *ucounts)
 {
-	if (!get_ucounts_or_wrap(ucounts)) {
-		put_ucounts(ucounts);
-		ucounts = NULL;
-	}
-	return 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_head *hashent = ucounts_hashentry(ns, uid);
-	bool wrapped;
 	struct ucounts *ucounts, *new = NULL;
 
 	spin_lock_irq(&ucounts_lock);
@@ -189,14 +180,11 @@ struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
 			return new;
 		}
 	}
-
-	wrapped = !get_ucounts_or_wrap(ucounts);
+	if (!atomic_inc_not_zero(&ucounts->count))
+		ucounts = NULL;
 	spin_unlock_irq(&ucounts_lock);
 	kfree(new);
-	if (wrapped) {
-		put_ucounts(ucounts);
-		return NULL;
-	}
+
 	return ucounts;
 }
 
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] ucount: Use RCU for ucounts lookups.
  2025-02-03 15:05 [PATCH 0/4] ucount: Simplify refcounting with rcuref_t Sebastian Andrzej Siewior
  2025-02-03 15:05 ` [PATCH 1/4] rcu: Provide a static initializer for hlist_nulls_head Sebastian Andrzej Siewior
  2025-02-03 15:05 ` [PATCH 2/4] ucount: Replace get_ucounts_or_wrap() with atomic_inc_not_zero() Sebastian Andrzej Siewior
@ 2025-02-03 15:05 ` Sebastian Andrzej Siewior
  2025-02-03 15:05 ` [PATCH 4/4] ucount: Use rcuref_t for reference counting Sebastian Andrzej Siewior
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-02-03 15:05 UTC (permalink / raw)
  To: linux-kernel, rcu
  Cc: Andrew Morton, MengEn Sun, Thomas Gleixner, YueHong Wu,
	Paul E. McKenney, Joel Fernandes, Josh Triplett, Boqun Feng,
	Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
	Lai Jiangshan, Zqiang, Sebastian Andrzej Siewior

The ucounts element is looked up under ucounts_lock. This can be
optimized by using RCU for a lockless lookup and return and element if the
reference can be obtained.

Replace hlist_head with hlist_nulls_head which is RCU compatible. Let
find_ucounts() search for the required item within a RCU section and
return the item if a reference could be obtained.
This means alloc_ucounts() will always return an element (unless the
memory allocation failed). Let put_ucounts() RCU free the element if the
reference counter dropped to zero.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 include/linux/user_namespace.h |  4 +-
 kernel/ucount.c                | 75 ++++++++++++++++++----------------
 2 files changed, 43 insertions(+), 36 deletions(-)

diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 7183e5aca2829..ad4dbef92597b 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -5,6 +5,7 @@
 #include <linux/kref.h>
 #include <linux/nsproxy.h>
 #include <linux/ns_common.h>
+#include <linux/rculist_nulls.h>
 #include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/rwsem.h>
@@ -115,9 +116,10 @@ struct user_namespace {
 } __randomize_layout;
 
 struct ucounts {
-	struct hlist_node node;
+	struct hlist_nulls_node node;
 	struct user_namespace *ns;
 	kuid_t uid;
+	struct rcu_head rcu;
 	atomic_t count;
 	atomic_long_t ucount[UCOUNT_COUNTS];
 	atomic_long_t rlimit[UCOUNT_RLIMIT_COUNTS];
diff --git a/kernel/ucount.c b/kernel/ucount.c
index 4aa5011538257..b6abaf68cdccb 100644
--- a/kernel/ucount.c
+++ b/kernel/ucount.c
@@ -15,7 +15,10 @@ struct ucounts init_ucounts = {
 };
 
 #define UCOUNTS_HASHTABLE_BITS 10
-static struct hlist_head ucounts_hashtable[(1 << UCOUNTS_HASHTABLE_BITS)];
+#define UCOUNTS_HASHTABLE_ENTRIES (1 << UCOUNTS_HASHTABLE_BITS)
+static struct hlist_nulls_head ucounts_hashtable[UCOUNTS_HASHTABLE_ENTRIES] = {
+	[0 ... UCOUNTS_HASHTABLE_ENTRIES - 1] = HLIST_NULLS_HEAD_INIT(0)
+};
 static DEFINE_SPINLOCK(ucounts_lock);
 
 #define ucounts_hashfn(ns, uid)						\
@@ -24,7 +27,6 @@ static DEFINE_SPINLOCK(ucounts_lock);
 #define ucounts_hashentry(ns, uid)	\
 	(ucounts_hashtable + ucounts_hashfn(ns, uid))
 
-
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_set *
 set_lookup(struct ctl_table_root *root)
@@ -127,22 +129,28 @@ void retire_userns_sysctls(struct user_namespace *ns)
 #endif
 }
 
-static struct ucounts *find_ucounts(struct user_namespace *ns, kuid_t uid, struct hlist_head *hashent)
+static struct ucounts *find_ucounts(struct user_namespace *ns, kuid_t uid,
+				    struct hlist_nulls_head *hashent)
 {
 	struct ucounts *ucounts;
+	struct hlist_nulls_node *pos;
 
-	hlist_for_each_entry(ucounts, hashent, node) {
-		if (uid_eq(ucounts->uid, uid) && (ucounts->ns == ns))
-			return ucounts;
+	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))
+				return ucounts;
+		}
 	}
 	return NULL;
 }
 
 static void hlist_add_ucounts(struct ucounts *ucounts)
 {
-	struct hlist_head *hashent = ucounts_hashentry(ucounts->ns, ucounts->uid);
+	struct hlist_nulls_head *hashent = ucounts_hashentry(ucounts->ns, ucounts->uid);
+
 	spin_lock_irq(&ucounts_lock);
-	hlist_add_head(&ucounts->node, hashent);
+	hlist_nulls_add_head_rcu(&ucounts->node, hashent);
 	spin_unlock_irq(&ucounts_lock);
 }
 
@@ -155,37 +163,33 @@ struct ucounts *get_ucounts(struct ucounts *ucounts)
 
 struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
 {
-	struct hlist_head *hashent = ucounts_hashentry(ns, uid);
-	struct ucounts *ucounts, *new = NULL;
+	struct hlist_nulls_head *hashent = ucounts_hashentry(ns, uid);
+	struct ucounts *ucounts, *new;
+
+	ucounts = find_ucounts(ns, uid, hashent);
+	if (ucounts)
+		return ucounts;
+
+	new = kzalloc(sizeof(*new), GFP_KERNEL);
+	if (!new)
+		return NULL;
+
+	new->ns = ns;
+	new->uid = uid;
+	atomic_set(&new->count, 1);
 
 	spin_lock_irq(&ucounts_lock);
 	ucounts = find_ucounts(ns, uid, hashent);
-	if (!ucounts) {
+	if (ucounts) {
 		spin_unlock_irq(&ucounts_lock);
-
-		new = kzalloc(sizeof(*new), GFP_KERNEL);
-		if (!new)
-			return NULL;
-
-		new->ns = ns;
-		new->uid = uid;
-		atomic_set(&new->count, 1);
-
-		spin_lock_irq(&ucounts_lock);
-		ucounts = find_ucounts(ns, uid, hashent);
-		if (!ucounts) {
-			hlist_add_head(&new->node, hashent);
-			get_user_ns(new->ns);
-			spin_unlock_irq(&ucounts_lock);
-			return new;
-		}
+		kfree(new);
+		return ucounts;
 	}
-	if (!atomic_inc_not_zero(&ucounts->count))
-		ucounts = NULL;
-	spin_unlock_irq(&ucounts_lock);
-	kfree(new);
 
-	return ucounts;
+	hlist_nulls_add_head_rcu(&new->node, hashent);
+	get_user_ns(new->ns);
+	spin_unlock_irq(&ucounts_lock);
+	return new;
 }
 
 void put_ucounts(struct ucounts *ucounts)
@@ -193,10 +197,11 @@ void put_ucounts(struct ucounts *ucounts)
 	unsigned long flags;
 
 	if (atomic_dec_and_lock_irqsave(&ucounts->count, &ucounts_lock, flags)) {
-		hlist_del_init(&ucounts->node);
+		hlist_nulls_del_rcu(&ucounts->node);
 		spin_unlock_irqrestore(&ucounts_lock, flags);
+
 		put_user_ns(ucounts->ns);
-		kfree(ucounts);
+		kfree_rcu(ucounts, rcu);
 	}
 }
 
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] ucount: Use rcuref_t for reference counting.
  2025-02-03 15:05 [PATCH 0/4] ucount: Simplify refcounting with rcuref_t Sebastian Andrzej Siewior
                   ` (2 preceding siblings ...)
  2025-02-03 15:05 ` [PATCH 3/4] ucount: Use RCU for ucounts lookups Sebastian Andrzej Siewior
@ 2025-02-03 15:05 ` Sebastian Andrzej Siewior
  2025-02-04  2:00 ` [PATCH 0/4] ucount: Simplify refcounting with rcuref_t Paul E. McKenney
  2025-02-07 20:48 ` Sebastian Andrzej Siewior
  5 siblings, 0 replies; 7+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-02-03 15:05 UTC (permalink / raw)
  To: linux-kernel, rcu
  Cc: Andrew Morton, MengEn Sun, Thomas Gleixner, YueHong Wu,
	Paul E. McKenney, Joel Fernandes, Josh Triplett, Boqun Feng,
	Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
	Lai Jiangshan, Zqiang, Sebastian Andrzej Siewior

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.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 include/linux/user_namespace.h | 11 +++++++++--
 kernel/ucount.c                | 16 +++++-----------
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index ad4dbef92597b..a0bb6d0121378 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -8,6 +8,7 @@
 #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>
@@ -120,7 +121,7 @@ struct ucounts {
 	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];
 };
@@ -133,9 +134,15 @@ void retire_userns_sysctls(struct user_namespace *ns);
 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]);
diff --git a/kernel/ucount.c b/kernel/ucount.c
index b6abaf68cdccb..8686e329b8f2c 100644
--- a/kernel/ucount.c
+++ b/kernel/ucount.c
@@ -11,7 +11,7 @@
 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
@@ -138,7 +138,7 @@ static struct ucounts *find_ucounts(struct user_namespace *ns, kuid_t uid,
 	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;
 		}
 	}
@@ -154,13 +154,6 @@ static void hlist_add_ucounts(struct ucounts *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);
@@ -176,7 +169,7 @@ struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t 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);
@@ -196,7 +189,8 @@ void put_ucounts(struct ucounts *ucounts)
 {
 	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);
 
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/4] ucount: Simplify refcounting with rcuref_t.
  2025-02-03 15:05 [PATCH 0/4] ucount: Simplify refcounting with rcuref_t Sebastian Andrzej Siewior
                   ` (3 preceding siblings ...)
  2025-02-03 15:05 ` [PATCH 4/4] ucount: Use rcuref_t for reference counting Sebastian Andrzej Siewior
@ 2025-02-04  2:00 ` Paul E. McKenney
  2025-02-07 20:48 ` Sebastian Andrzej Siewior
  5 siblings, 0 replies; 7+ messages in thread
From: Paul E. McKenney @ 2025-02-04  2:00 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-kernel, rcu, Andrew Morton, MengEn Sun, Thomas Gleixner,
	YueHong Wu, Joel Fernandes, Josh Triplett, Boqun Feng,
	Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
	Lai Jiangshan, Zqiang

On Mon, Feb 03, 2025 at 04:05:21PM +0100, Sebastian Andrzej Siewior wrote:
> I noticed that the atomic_dec_and_lock_irqsave() in put_ucounts() loops
> sometimes even during boot. Something like 2-3 iterations but still.
> This series replaces the refcounting with rcuref_t and adds a RCU
> lookup.
> This allows a lockless lookup in alloc_ucounts() if the entry is
> available and a cmpxchg()less put of the item.
> 
> Patch #1 adds HLIST_NULLS_HEAD_INIT for which I added the RCU folks.

The modification and later elimination of get_ucounts() threw me for
a bit, but for the series:

Reviewed-by: Paul E. McKenney <paulmck@kernel.org>

> Sebastian
> 
> Sebastian Andrzej Siewior (4):
>   rcu: Provide a static initializer for hlist_nulls_head.
>   ucount: Replace get_ucounts_or_wrap() with atomic_inc_not_zero().
>   ucount: Use RCU for ucounts lookups.
>   ucount: Use rcuref_t for reference counting.
> 
>  include/linux/list_nulls.h     |  1 +
>  include/linux/user_namespace.h | 15 ++++--
>  kernel/ucount.c                | 97 +++++++++++++++-------------------
>  3 files changed, 55 insertions(+), 58 deletions(-)
> 
> -- 
> 2.47.2
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/4] ucount: Simplify refcounting with rcuref_t.
  2025-02-03 15:05 [PATCH 0/4] ucount: Simplify refcounting with rcuref_t Sebastian Andrzej Siewior
                   ` (4 preceding siblings ...)
  2025-02-04  2:00 ` [PATCH 0/4] ucount: Simplify refcounting with rcuref_t Paul E. McKenney
@ 2025-02-07 20:48 ` Sebastian Andrzej Siewior
  5 siblings, 0 replies; 7+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-02-07 20:48 UTC (permalink / raw)
  To: linux-kernel, rcu, Andrew Morton
  Cc: MengEn Sun, Thomas Gleixner, YueHong Wu, Paul E. McKenney,
	Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki,
	Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang

On 2025-02-03 16:05:21 [+0100], To linux-kernel@vger.kernel.org wrote:
> I noticed that the atomic_dec_and_lock_irqsave() in put_ucounts() loops
> sometimes even during boot. Something like 2-3 iterations but still.
> This series replaces the refcounting with rcuref_t and adds a RCU
> lookup.
> This allows a lockless lookup in alloc_ucounts() if the entry is
> available and a cmpxchg()less put of the item.

Andrew, could you please take this series?

Sebastian

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-02-07 20:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-03 15:05 [PATCH 0/4] ucount: Simplify refcounting with rcuref_t Sebastian Andrzej Siewior
2025-02-03 15:05 ` [PATCH 1/4] rcu: Provide a static initializer for hlist_nulls_head Sebastian Andrzej Siewior
2025-02-03 15:05 ` [PATCH 2/4] ucount: Replace get_ucounts_or_wrap() with atomic_inc_not_zero() Sebastian Andrzej Siewior
2025-02-03 15:05 ` [PATCH 3/4] ucount: Use RCU for ucounts lookups Sebastian Andrzej Siewior
2025-02-03 15:05 ` [PATCH 4/4] ucount: Use rcuref_t for reference counting Sebastian Andrzej Siewior
2025-02-04  2:00 ` [PATCH 0/4] ucount: Simplify refcounting with rcuref_t Paul E. McKenney
2025-02-07 20:48 ` Sebastian Andrzej Siewior

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox