18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * klist.c - Routines for manipulating klists.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2005 Patrick Mochel
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * This klist interface provides a couple of structures that wrap around
88c2ecf20Sopenharmony_ci * struct list_head to provide explicit list "head" (struct klist) and list
98c2ecf20Sopenharmony_ci * "node" (struct klist_node) objects. For struct klist, a spinlock is
108c2ecf20Sopenharmony_ci * included that protects access to the actual list itself. struct
118c2ecf20Sopenharmony_ci * klist_node provides a pointer to the klist that owns it and a kref
128c2ecf20Sopenharmony_ci * reference count that indicates the number of current users of that node
138c2ecf20Sopenharmony_ci * in the list.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * The entire point is to provide an interface for iterating over a list
168c2ecf20Sopenharmony_ci * that is safe and allows for modification of the list during the
178c2ecf20Sopenharmony_ci * iteration (e.g. insertion and removal), including modification of the
188c2ecf20Sopenharmony_ci * current node on the list.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * It works using a 3rd object type - struct klist_iter - that is declared
218c2ecf20Sopenharmony_ci * and initialized before an iteration. klist_next() is used to acquire the
228c2ecf20Sopenharmony_ci * next element in the list. It returns NULL if there are no more items.
238c2ecf20Sopenharmony_ci * Internally, that routine takes the klist's lock, decrements the
248c2ecf20Sopenharmony_ci * reference count of the previous klist_node and increments the count of
258c2ecf20Sopenharmony_ci * the next klist_node. It then drops the lock and returns.
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * There are primitives for adding and removing nodes to/from a klist.
288c2ecf20Sopenharmony_ci * When deleting, klist_del() will simply decrement the reference count.
298c2ecf20Sopenharmony_ci * Only when the count goes to 0 is the node removed from the list.
308c2ecf20Sopenharmony_ci * klist_remove() will try to delete the node from the list and block until
318c2ecf20Sopenharmony_ci * it is actually removed. This is useful for objects (like devices) that
328c2ecf20Sopenharmony_ci * have been removed from the system and must be freed (but must wait until
338c2ecf20Sopenharmony_ci * all accessors have finished).
348c2ecf20Sopenharmony_ci */
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include <linux/klist.h>
378c2ecf20Sopenharmony_ci#include <linux/export.h>
388c2ecf20Sopenharmony_ci#include <linux/sched.h>
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/*
418c2ecf20Sopenharmony_ci * Use the lowest bit of n_klist to mark deleted nodes and exclude
428c2ecf20Sopenharmony_ci * dead ones from iteration.
438c2ecf20Sopenharmony_ci */
448c2ecf20Sopenharmony_ci#define KNODE_DEAD		1LU
458c2ecf20Sopenharmony_ci#define KNODE_KLIST_MASK	~KNODE_DEAD
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic struct klist *knode_klist(struct klist_node *knode)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	return (struct klist *)
508c2ecf20Sopenharmony_ci		((unsigned long)knode->n_klist & KNODE_KLIST_MASK);
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic bool knode_dead(struct klist_node *knode)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	return (unsigned long)knode->n_klist & KNODE_DEAD;
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic void knode_set_klist(struct klist_node *knode, struct klist *klist)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	knode->n_klist = klist;
618c2ecf20Sopenharmony_ci	/* no knode deserves to start its life dead */
628c2ecf20Sopenharmony_ci	WARN_ON(knode_dead(knode));
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic void knode_kill(struct klist_node *knode)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	/* and no knode should die twice ever either, see we're very humane */
688c2ecf20Sopenharmony_ci	WARN_ON(knode_dead(knode));
698c2ecf20Sopenharmony_ci	*(unsigned long *)&knode->n_klist |= KNODE_DEAD;
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci/**
738c2ecf20Sopenharmony_ci * klist_init - Initialize a klist structure.
748c2ecf20Sopenharmony_ci * @k: The klist we're initializing.
758c2ecf20Sopenharmony_ci * @get: The get function for the embedding object (NULL if none)
768c2ecf20Sopenharmony_ci * @put: The put function for the embedding object (NULL if none)
778c2ecf20Sopenharmony_ci *
788c2ecf20Sopenharmony_ci * Initialises the klist structure.  If the klist_node structures are
798c2ecf20Sopenharmony_ci * going to be embedded in refcounted objects (necessary for safe
808c2ecf20Sopenharmony_ci * deletion) then the get/put arguments are used to initialise
818c2ecf20Sopenharmony_ci * functions that take and release references on the embedding
828c2ecf20Sopenharmony_ci * objects.
838c2ecf20Sopenharmony_ci */
848c2ecf20Sopenharmony_civoid klist_init(struct klist *k, void (*get)(struct klist_node *),
858c2ecf20Sopenharmony_ci		void (*put)(struct klist_node *))
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&k->k_list);
888c2ecf20Sopenharmony_ci	spin_lock_init(&k->k_lock);
898c2ecf20Sopenharmony_ci	k->get = get;
908c2ecf20Sopenharmony_ci	k->put = put;
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_init);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic void add_head(struct klist *k, struct klist_node *n)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	spin_lock(&k->k_lock);
978c2ecf20Sopenharmony_ci	list_add(&n->n_node, &k->k_list);
988c2ecf20Sopenharmony_ci	spin_unlock(&k->k_lock);
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cistatic void add_tail(struct klist *k, struct klist_node *n)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	spin_lock(&k->k_lock);
1048c2ecf20Sopenharmony_ci	list_add_tail(&n->n_node, &k->k_list);
1058c2ecf20Sopenharmony_ci	spin_unlock(&k->k_lock);
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic void klist_node_init(struct klist *k, struct klist_node *n)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&n->n_node);
1118c2ecf20Sopenharmony_ci	kref_init(&n->n_ref);
1128c2ecf20Sopenharmony_ci	knode_set_klist(n, k);
1138c2ecf20Sopenharmony_ci	if (k->get)
1148c2ecf20Sopenharmony_ci		k->get(n);
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci/**
1188c2ecf20Sopenharmony_ci * klist_add_head - Initialize a klist_node and add it to front.
1198c2ecf20Sopenharmony_ci * @n: node we're adding.
1208c2ecf20Sopenharmony_ci * @k: klist it's going on.
1218c2ecf20Sopenharmony_ci */
1228c2ecf20Sopenharmony_civoid klist_add_head(struct klist_node *n, struct klist *k)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	klist_node_init(k, n);
1258c2ecf20Sopenharmony_ci	add_head(k, n);
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_add_head);
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci/**
1308c2ecf20Sopenharmony_ci * klist_add_tail - Initialize a klist_node and add it to back.
1318c2ecf20Sopenharmony_ci * @n: node we're adding.
1328c2ecf20Sopenharmony_ci * @k: klist it's going on.
1338c2ecf20Sopenharmony_ci */
1348c2ecf20Sopenharmony_civoid klist_add_tail(struct klist_node *n, struct klist *k)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	klist_node_init(k, n);
1378c2ecf20Sopenharmony_ci	add_tail(k, n);
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_add_tail);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci/**
1428c2ecf20Sopenharmony_ci * klist_add_behind - Init a klist_node and add it after an existing node
1438c2ecf20Sopenharmony_ci * @n: node we're adding.
1448c2ecf20Sopenharmony_ci * @pos: node to put @n after
1458c2ecf20Sopenharmony_ci */
1468c2ecf20Sopenharmony_civoid klist_add_behind(struct klist_node *n, struct klist_node *pos)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	struct klist *k = knode_klist(pos);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	klist_node_init(k, n);
1518c2ecf20Sopenharmony_ci	spin_lock(&k->k_lock);
1528c2ecf20Sopenharmony_ci	list_add(&n->n_node, &pos->n_node);
1538c2ecf20Sopenharmony_ci	spin_unlock(&k->k_lock);
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_add_behind);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci/**
1588c2ecf20Sopenharmony_ci * klist_add_before - Init a klist_node and add it before an existing node
1598c2ecf20Sopenharmony_ci * @n: node we're adding.
1608c2ecf20Sopenharmony_ci * @pos: node to put @n after
1618c2ecf20Sopenharmony_ci */
1628c2ecf20Sopenharmony_civoid klist_add_before(struct klist_node *n, struct klist_node *pos)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	struct klist *k = knode_klist(pos);
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	klist_node_init(k, n);
1678c2ecf20Sopenharmony_ci	spin_lock(&k->k_lock);
1688c2ecf20Sopenharmony_ci	list_add_tail(&n->n_node, &pos->n_node);
1698c2ecf20Sopenharmony_ci	spin_unlock(&k->k_lock);
1708c2ecf20Sopenharmony_ci}
1718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_add_before);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cistruct klist_waiter {
1748c2ecf20Sopenharmony_ci	struct list_head list;
1758c2ecf20Sopenharmony_ci	struct klist_node *node;
1768c2ecf20Sopenharmony_ci	struct task_struct *process;
1778c2ecf20Sopenharmony_ci	int woken;
1788c2ecf20Sopenharmony_ci};
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(klist_remove_lock);
1818c2ecf20Sopenharmony_cistatic LIST_HEAD(klist_remove_waiters);
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic void klist_release(struct kref *kref)
1848c2ecf20Sopenharmony_ci{
1858c2ecf20Sopenharmony_ci	struct klist_waiter *waiter, *tmp;
1868c2ecf20Sopenharmony_ci	struct klist_node *n = container_of(kref, struct klist_node, n_ref);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	WARN_ON(!knode_dead(n));
1898c2ecf20Sopenharmony_ci	list_del(&n->n_node);
1908c2ecf20Sopenharmony_ci	spin_lock(&klist_remove_lock);
1918c2ecf20Sopenharmony_ci	list_for_each_entry_safe(waiter, tmp, &klist_remove_waiters, list) {
1928c2ecf20Sopenharmony_ci		if (waiter->node != n)
1938c2ecf20Sopenharmony_ci			continue;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci		list_del(&waiter->list);
1968c2ecf20Sopenharmony_ci		waiter->woken = 1;
1978c2ecf20Sopenharmony_ci		mb();
1988c2ecf20Sopenharmony_ci		wake_up_process(waiter->process);
1998c2ecf20Sopenharmony_ci	}
2008c2ecf20Sopenharmony_ci	spin_unlock(&klist_remove_lock);
2018c2ecf20Sopenharmony_ci	knode_set_klist(n, NULL);
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic int klist_dec_and_del(struct klist_node *n)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	return kref_put(&n->n_ref, klist_release);
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_cistatic void klist_put(struct klist_node *n, bool kill)
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	struct klist *k = knode_klist(n);
2128c2ecf20Sopenharmony_ci	void (*put)(struct klist_node *) = k->put;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	spin_lock(&k->k_lock);
2158c2ecf20Sopenharmony_ci	if (kill)
2168c2ecf20Sopenharmony_ci		knode_kill(n);
2178c2ecf20Sopenharmony_ci	if (!klist_dec_and_del(n))
2188c2ecf20Sopenharmony_ci		put = NULL;
2198c2ecf20Sopenharmony_ci	spin_unlock(&k->k_lock);
2208c2ecf20Sopenharmony_ci	if (put)
2218c2ecf20Sopenharmony_ci		put(n);
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci/**
2258c2ecf20Sopenharmony_ci * klist_del - Decrement the reference count of node and try to remove.
2268c2ecf20Sopenharmony_ci * @n: node we're deleting.
2278c2ecf20Sopenharmony_ci */
2288c2ecf20Sopenharmony_civoid klist_del(struct klist_node *n)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	klist_put(n, true);
2318c2ecf20Sopenharmony_ci}
2328c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_del);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci/**
2358c2ecf20Sopenharmony_ci * klist_remove - Decrement the refcount of node and wait for it to go away.
2368c2ecf20Sopenharmony_ci * @n: node we're removing.
2378c2ecf20Sopenharmony_ci */
2388c2ecf20Sopenharmony_civoid klist_remove(struct klist_node *n)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	struct klist_waiter waiter;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	waiter.node = n;
2438c2ecf20Sopenharmony_ci	waiter.process = current;
2448c2ecf20Sopenharmony_ci	waiter.woken = 0;
2458c2ecf20Sopenharmony_ci	spin_lock(&klist_remove_lock);
2468c2ecf20Sopenharmony_ci	list_add(&waiter.list, &klist_remove_waiters);
2478c2ecf20Sopenharmony_ci	spin_unlock(&klist_remove_lock);
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	klist_del(n);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	for (;;) {
2528c2ecf20Sopenharmony_ci		set_current_state(TASK_UNINTERRUPTIBLE);
2538c2ecf20Sopenharmony_ci		if (waiter.woken)
2548c2ecf20Sopenharmony_ci			break;
2558c2ecf20Sopenharmony_ci		schedule();
2568c2ecf20Sopenharmony_ci	}
2578c2ecf20Sopenharmony_ci	__set_current_state(TASK_RUNNING);
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_remove);
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci/**
2628c2ecf20Sopenharmony_ci * klist_node_attached - Say whether a node is bound to a list or not.
2638c2ecf20Sopenharmony_ci * @n: Node that we're testing.
2648c2ecf20Sopenharmony_ci */
2658c2ecf20Sopenharmony_ciint klist_node_attached(struct klist_node *n)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	return (n->n_klist != NULL);
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_node_attached);
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci/**
2728c2ecf20Sopenharmony_ci * klist_iter_init_node - Initialize a klist_iter structure.
2738c2ecf20Sopenharmony_ci * @k: klist we're iterating.
2748c2ecf20Sopenharmony_ci * @i: klist_iter we're filling.
2758c2ecf20Sopenharmony_ci * @n: node to start with.
2768c2ecf20Sopenharmony_ci *
2778c2ecf20Sopenharmony_ci * Similar to klist_iter_init(), but starts the action off with @n,
2788c2ecf20Sopenharmony_ci * instead of with the list head.
2798c2ecf20Sopenharmony_ci */
2808c2ecf20Sopenharmony_civoid klist_iter_init_node(struct klist *k, struct klist_iter *i,
2818c2ecf20Sopenharmony_ci			  struct klist_node *n)
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	i->i_klist = k;
2848c2ecf20Sopenharmony_ci	i->i_cur = NULL;
2858c2ecf20Sopenharmony_ci	if (n && kref_get_unless_zero(&n->n_ref))
2868c2ecf20Sopenharmony_ci		i->i_cur = n;
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_iter_init_node);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci/**
2918c2ecf20Sopenharmony_ci * klist_iter_init - Iniitalize a klist_iter structure.
2928c2ecf20Sopenharmony_ci * @k: klist we're iterating.
2938c2ecf20Sopenharmony_ci * @i: klist_iter structure we're filling.
2948c2ecf20Sopenharmony_ci *
2958c2ecf20Sopenharmony_ci * Similar to klist_iter_init_node(), but start with the list head.
2968c2ecf20Sopenharmony_ci */
2978c2ecf20Sopenharmony_civoid klist_iter_init(struct klist *k, struct klist_iter *i)
2988c2ecf20Sopenharmony_ci{
2998c2ecf20Sopenharmony_ci	klist_iter_init_node(k, i, NULL);
3008c2ecf20Sopenharmony_ci}
3018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_iter_init);
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci/**
3048c2ecf20Sopenharmony_ci * klist_iter_exit - Finish a list iteration.
3058c2ecf20Sopenharmony_ci * @i: Iterator structure.
3068c2ecf20Sopenharmony_ci *
3078c2ecf20Sopenharmony_ci * Must be called when done iterating over list, as it decrements the
3088c2ecf20Sopenharmony_ci * refcount of the current node. Necessary in case iteration exited before
3098c2ecf20Sopenharmony_ci * the end of the list was reached, and always good form.
3108c2ecf20Sopenharmony_ci */
3118c2ecf20Sopenharmony_civoid klist_iter_exit(struct klist_iter *i)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	if (i->i_cur) {
3148c2ecf20Sopenharmony_ci		klist_put(i->i_cur, false);
3158c2ecf20Sopenharmony_ci		i->i_cur = NULL;
3168c2ecf20Sopenharmony_ci	}
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_iter_exit);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic struct klist_node *to_klist_node(struct list_head *n)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	return container_of(n, struct klist_node, n_node);
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci/**
3268c2ecf20Sopenharmony_ci * klist_prev - Ante up prev node in list.
3278c2ecf20Sopenharmony_ci * @i: Iterator structure.
3288c2ecf20Sopenharmony_ci *
3298c2ecf20Sopenharmony_ci * First grab list lock. Decrement the reference count of the previous
3308c2ecf20Sopenharmony_ci * node, if there was one. Grab the prev node, increment its reference
3318c2ecf20Sopenharmony_ci * count, drop the lock, and return that prev node.
3328c2ecf20Sopenharmony_ci */
3338c2ecf20Sopenharmony_cistruct klist_node *klist_prev(struct klist_iter *i)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	void (*put)(struct klist_node *) = i->i_klist->put;
3368c2ecf20Sopenharmony_ci	struct klist_node *last = i->i_cur;
3378c2ecf20Sopenharmony_ci	struct klist_node *prev;
3388c2ecf20Sopenharmony_ci	unsigned long flags;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	spin_lock_irqsave(&i->i_klist->k_lock, flags);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (last) {
3438c2ecf20Sopenharmony_ci		prev = to_klist_node(last->n_node.prev);
3448c2ecf20Sopenharmony_ci		if (!klist_dec_and_del(last))
3458c2ecf20Sopenharmony_ci			put = NULL;
3468c2ecf20Sopenharmony_ci	} else
3478c2ecf20Sopenharmony_ci		prev = to_klist_node(i->i_klist->k_list.prev);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	i->i_cur = NULL;
3508c2ecf20Sopenharmony_ci	while (prev != to_klist_node(&i->i_klist->k_list)) {
3518c2ecf20Sopenharmony_ci		if (likely(!knode_dead(prev))) {
3528c2ecf20Sopenharmony_ci			kref_get(&prev->n_ref);
3538c2ecf20Sopenharmony_ci			i->i_cur = prev;
3548c2ecf20Sopenharmony_ci			break;
3558c2ecf20Sopenharmony_ci		}
3568c2ecf20Sopenharmony_ci		prev = to_klist_node(prev->n_node.prev);
3578c2ecf20Sopenharmony_ci	}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&i->i_klist->k_lock, flags);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	if (put && last)
3628c2ecf20Sopenharmony_ci		put(last);
3638c2ecf20Sopenharmony_ci	return i->i_cur;
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_prev);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci/**
3688c2ecf20Sopenharmony_ci * klist_next - Ante up next node in list.
3698c2ecf20Sopenharmony_ci * @i: Iterator structure.
3708c2ecf20Sopenharmony_ci *
3718c2ecf20Sopenharmony_ci * First grab list lock. Decrement the reference count of the previous
3728c2ecf20Sopenharmony_ci * node, if there was one. Grab the next node, increment its reference
3738c2ecf20Sopenharmony_ci * count, drop the lock, and return that next node.
3748c2ecf20Sopenharmony_ci */
3758c2ecf20Sopenharmony_cistruct klist_node *klist_next(struct klist_iter *i)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	void (*put)(struct klist_node *) = i->i_klist->put;
3788c2ecf20Sopenharmony_ci	struct klist_node *last = i->i_cur;
3798c2ecf20Sopenharmony_ci	struct klist_node *next;
3808c2ecf20Sopenharmony_ci	unsigned long flags;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	spin_lock_irqsave(&i->i_klist->k_lock, flags);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	if (last) {
3858c2ecf20Sopenharmony_ci		next = to_klist_node(last->n_node.next);
3868c2ecf20Sopenharmony_ci		if (!klist_dec_and_del(last))
3878c2ecf20Sopenharmony_ci			put = NULL;
3888c2ecf20Sopenharmony_ci	} else
3898c2ecf20Sopenharmony_ci		next = to_klist_node(i->i_klist->k_list.next);
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	i->i_cur = NULL;
3928c2ecf20Sopenharmony_ci	while (next != to_klist_node(&i->i_klist->k_list)) {
3938c2ecf20Sopenharmony_ci		if (likely(!knode_dead(next))) {
3948c2ecf20Sopenharmony_ci			kref_get(&next->n_ref);
3958c2ecf20Sopenharmony_ci			i->i_cur = next;
3968c2ecf20Sopenharmony_ci			break;
3978c2ecf20Sopenharmony_ci		}
3988c2ecf20Sopenharmony_ci		next = to_klist_node(next->n_node.next);
3998c2ecf20Sopenharmony_ci	}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&i->i_klist->k_lock, flags);
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	if (put && last)
4048c2ecf20Sopenharmony_ci		put(last);
4058c2ecf20Sopenharmony_ci	return i->i_cur;
4068c2ecf20Sopenharmony_ci}
4078c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_next);
408