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@xxxxxxxxxx> Signed-off-by: Olga Kornievskaia <okorniev@xxxxxxxxxx> --- include/linux/llist.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) 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 -- 2.47.1