diff mbox series

[1/3] llist: add ability to remove a particular entry from the list

Message ID 20250115232406.44815-2-okorniev@redhat.com (mailing list archive)
State New
Headers show
Series fix removal of nfsd listeners | expand

Commit Message

Olga Kornievskaia Jan. 15, 2025, 11:24 p.m. UTC
nfsd stores its network transports in a lwq (which is a lockless list)
llist has no ability to remove a particular entry which nfsd needs
to remove a listener thread.

Suggested-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
---
 include/linux/llist.h | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)
diff mbox series

Patch

diff --git a/include/linux/llist.h b/include/linux/llist.h
index 2c982ff7475a..fe6be21897d9 100644
--- a/include/linux/llist.h
+++ b/include/linux/llist.h
@@ -253,6 +253,42 @@  static inline bool __llist_add(struct llist_node *new, struct llist_head *head)
 	return __llist_add_batch(new, new, head);
 }
 
+/**
+ * llist_del_entry - remove a particular entry from a lock-less list
+ * @head: head of the list to remove the entry from
+ * @entry: entry to be removed from the list
+ *
+ * Walk the list, find the given entry and remove it from the list.
+ * The caller must ensure that nothing can race in and change the
+ * list while this is running.
+ *
+ * Returns true if the entry was found and removed.
+ */
+static inline bool llist_del_entry(struct llist_head *head, struct llist_node *entry)
+{
+	struct llist_node *pos;
+
+	if (!head->first)
+		return false;
+
+	/* Is it the first entry? */
+	if (head->first == entry) {
+		head->first = entry->next;
+		entry->next = entry;
+		return true;
+	}
+
+	/* Find it in the list */
+	llist_for_each(head->first, pos) {
+		if (pos->next == entry) {
+			pos->next = entry->next;
+			entry->next = entry;
+			return true;
+		}
+	}
+	return false;
+}
+
 /**
  * llist_del_all - delete all entries from lock-less list
  * @head:	the head of lock-less list to delete all entries