162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * klist.c - Routines for manipulating klists.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2005 Patrick Mochel
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * This klist interface provides a couple of structures that wrap around
862306a36Sopenharmony_ci * struct list_head to provide explicit list "head" (struct klist) and list
962306a36Sopenharmony_ci * "node" (struct klist_node) objects. For struct klist, a spinlock is
1062306a36Sopenharmony_ci * included that protects access to the actual list itself. struct
1162306a36Sopenharmony_ci * klist_node provides a pointer to the klist that owns it and a kref
1262306a36Sopenharmony_ci * reference count that indicates the number of current users of that node
1362306a36Sopenharmony_ci * in the list.
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * The entire point is to provide an interface for iterating over a list
1662306a36Sopenharmony_ci * that is safe and allows for modification of the list during the
1762306a36Sopenharmony_ci * iteration (e.g. insertion and removal), including modification of the
1862306a36Sopenharmony_ci * current node on the list.
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci * It works using a 3rd object type - struct klist_iter - that is declared
2162306a36Sopenharmony_ci * and initialized before an iteration. klist_next() is used to acquire the
2262306a36Sopenharmony_ci * next element in the list. It returns NULL if there are no more items.
2362306a36Sopenharmony_ci * Internally, that routine takes the klist's lock, decrements the
2462306a36Sopenharmony_ci * reference count of the previous klist_node and increments the count of
2562306a36Sopenharmony_ci * the next klist_node. It then drops the lock and returns.
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci * There are primitives for adding and removing nodes to/from a klist.
2862306a36Sopenharmony_ci * When deleting, klist_del() will simply decrement the reference count.
2962306a36Sopenharmony_ci * Only when the count goes to 0 is the node removed from the list.
3062306a36Sopenharmony_ci * klist_remove() will try to delete the node from the list and block until
3162306a36Sopenharmony_ci * it is actually removed. This is useful for objects (like devices) that
3262306a36Sopenharmony_ci * have been removed from the system and must be freed (but must wait until
3362306a36Sopenharmony_ci * all accessors have finished).
3462306a36Sopenharmony_ci */
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#include <linux/klist.h>
3762306a36Sopenharmony_ci#include <linux/export.h>
3862306a36Sopenharmony_ci#include <linux/sched.h>
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/*
4162306a36Sopenharmony_ci * Use the lowest bit of n_klist to mark deleted nodes and exclude
4262306a36Sopenharmony_ci * dead ones from iteration.
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_ci#define KNODE_DEAD		1LU
4562306a36Sopenharmony_ci#define KNODE_KLIST_MASK	~KNODE_DEAD
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic struct klist *knode_klist(struct klist_node *knode)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	return (struct klist *)
5062306a36Sopenharmony_ci		((unsigned long)knode->n_klist & KNODE_KLIST_MASK);
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistatic bool knode_dead(struct klist_node *knode)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	return (unsigned long)knode->n_klist & KNODE_DEAD;
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic void knode_set_klist(struct klist_node *knode, struct klist *klist)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	knode->n_klist = klist;
6162306a36Sopenharmony_ci	/* no knode deserves to start its life dead */
6262306a36Sopenharmony_ci	WARN_ON(knode_dead(knode));
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic void knode_kill(struct klist_node *knode)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	/* and no knode should die twice ever either, see we're very humane */
6862306a36Sopenharmony_ci	WARN_ON(knode_dead(knode));
6962306a36Sopenharmony_ci	*(unsigned long *)&knode->n_klist |= KNODE_DEAD;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/**
7362306a36Sopenharmony_ci * klist_init - Initialize a klist structure.
7462306a36Sopenharmony_ci * @k: The klist we're initializing.
7562306a36Sopenharmony_ci * @get: The get function for the embedding object (NULL if none)
7662306a36Sopenharmony_ci * @put: The put function for the embedding object (NULL if none)
7762306a36Sopenharmony_ci *
7862306a36Sopenharmony_ci * Initialises the klist structure.  If the klist_node structures are
7962306a36Sopenharmony_ci * going to be embedded in refcounted objects (necessary for safe
8062306a36Sopenharmony_ci * deletion) then the get/put arguments are used to initialise
8162306a36Sopenharmony_ci * functions that take and release references on the embedding
8262306a36Sopenharmony_ci * objects.
8362306a36Sopenharmony_ci */
8462306a36Sopenharmony_civoid klist_init(struct klist *k, void (*get)(struct klist_node *),
8562306a36Sopenharmony_ci		void (*put)(struct klist_node *))
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	INIT_LIST_HEAD(&k->k_list);
8862306a36Sopenharmony_ci	spin_lock_init(&k->k_lock);
8962306a36Sopenharmony_ci	k->get = get;
9062306a36Sopenharmony_ci	k->put = put;
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_init);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic void add_head(struct klist *k, struct klist_node *n)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	spin_lock(&k->k_lock);
9762306a36Sopenharmony_ci	list_add(&n->n_node, &k->k_list);
9862306a36Sopenharmony_ci	spin_unlock(&k->k_lock);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic void add_tail(struct klist *k, struct klist_node *n)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	spin_lock(&k->k_lock);
10462306a36Sopenharmony_ci	list_add_tail(&n->n_node, &k->k_list);
10562306a36Sopenharmony_ci	spin_unlock(&k->k_lock);
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistatic void klist_node_init(struct klist *k, struct klist_node *n)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	INIT_LIST_HEAD(&n->n_node);
11162306a36Sopenharmony_ci	kref_init(&n->n_ref);
11262306a36Sopenharmony_ci	knode_set_klist(n, k);
11362306a36Sopenharmony_ci	if (k->get)
11462306a36Sopenharmony_ci		k->get(n);
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci/**
11862306a36Sopenharmony_ci * klist_add_head - Initialize a klist_node and add it to front.
11962306a36Sopenharmony_ci * @n: node we're adding.
12062306a36Sopenharmony_ci * @k: klist it's going on.
12162306a36Sopenharmony_ci */
12262306a36Sopenharmony_civoid klist_add_head(struct klist_node *n, struct klist *k)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	klist_node_init(k, n);
12562306a36Sopenharmony_ci	add_head(k, n);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_add_head);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci/**
13062306a36Sopenharmony_ci * klist_add_tail - Initialize a klist_node and add it to back.
13162306a36Sopenharmony_ci * @n: node we're adding.
13262306a36Sopenharmony_ci * @k: klist it's going on.
13362306a36Sopenharmony_ci */
13462306a36Sopenharmony_civoid klist_add_tail(struct klist_node *n, struct klist *k)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	klist_node_init(k, n);
13762306a36Sopenharmony_ci	add_tail(k, n);
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_add_tail);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci/**
14262306a36Sopenharmony_ci * klist_add_behind - Init a klist_node and add it after an existing node
14362306a36Sopenharmony_ci * @n: node we're adding.
14462306a36Sopenharmony_ci * @pos: node to put @n after
14562306a36Sopenharmony_ci */
14662306a36Sopenharmony_civoid klist_add_behind(struct klist_node *n, struct klist_node *pos)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	struct klist *k = knode_klist(pos);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	klist_node_init(k, n);
15162306a36Sopenharmony_ci	spin_lock(&k->k_lock);
15262306a36Sopenharmony_ci	list_add(&n->n_node, &pos->n_node);
15362306a36Sopenharmony_ci	spin_unlock(&k->k_lock);
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_add_behind);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci/**
15862306a36Sopenharmony_ci * klist_add_before - Init a klist_node and add it before an existing node
15962306a36Sopenharmony_ci * @n: node we're adding.
16062306a36Sopenharmony_ci * @pos: node to put @n after
16162306a36Sopenharmony_ci */
16262306a36Sopenharmony_civoid klist_add_before(struct klist_node *n, struct klist_node *pos)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct klist *k = knode_klist(pos);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	klist_node_init(k, n);
16762306a36Sopenharmony_ci	spin_lock(&k->k_lock);
16862306a36Sopenharmony_ci	list_add_tail(&n->n_node, &pos->n_node);
16962306a36Sopenharmony_ci	spin_unlock(&k->k_lock);
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_add_before);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistruct klist_waiter {
17462306a36Sopenharmony_ci	struct list_head list;
17562306a36Sopenharmony_ci	struct klist_node *node;
17662306a36Sopenharmony_ci	struct task_struct *process;
17762306a36Sopenharmony_ci	int woken;
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic DEFINE_SPINLOCK(klist_remove_lock);
18162306a36Sopenharmony_cistatic LIST_HEAD(klist_remove_waiters);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cistatic void klist_release(struct kref *kref)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	struct klist_waiter *waiter, *tmp;
18662306a36Sopenharmony_ci	struct klist_node *n = container_of(kref, struct klist_node, n_ref);
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	WARN_ON(!knode_dead(n));
18962306a36Sopenharmony_ci	list_del(&n->n_node);
19062306a36Sopenharmony_ci	spin_lock(&klist_remove_lock);
19162306a36Sopenharmony_ci	list_for_each_entry_safe(waiter, tmp, &klist_remove_waiters, list) {
19262306a36Sopenharmony_ci		if (waiter->node != n)
19362306a36Sopenharmony_ci			continue;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci		list_del(&waiter->list);
19662306a36Sopenharmony_ci		waiter->woken = 1;
19762306a36Sopenharmony_ci		mb();
19862306a36Sopenharmony_ci		wake_up_process(waiter->process);
19962306a36Sopenharmony_ci	}
20062306a36Sopenharmony_ci	spin_unlock(&klist_remove_lock);
20162306a36Sopenharmony_ci	knode_set_klist(n, NULL);
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistatic int klist_dec_and_del(struct klist_node *n)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	return kref_put(&n->n_ref, klist_release);
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic void klist_put(struct klist_node *n, bool kill)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	struct klist *k = knode_klist(n);
21262306a36Sopenharmony_ci	void (*put)(struct klist_node *) = k->put;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	spin_lock(&k->k_lock);
21562306a36Sopenharmony_ci	if (kill)
21662306a36Sopenharmony_ci		knode_kill(n);
21762306a36Sopenharmony_ci	if (!klist_dec_and_del(n))
21862306a36Sopenharmony_ci		put = NULL;
21962306a36Sopenharmony_ci	spin_unlock(&k->k_lock);
22062306a36Sopenharmony_ci	if (put)
22162306a36Sopenharmony_ci		put(n);
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci/**
22562306a36Sopenharmony_ci * klist_del - Decrement the reference count of node and try to remove.
22662306a36Sopenharmony_ci * @n: node we're deleting.
22762306a36Sopenharmony_ci */
22862306a36Sopenharmony_civoid klist_del(struct klist_node *n)
22962306a36Sopenharmony_ci{
23062306a36Sopenharmony_ci	klist_put(n, true);
23162306a36Sopenharmony_ci}
23262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_del);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci/**
23562306a36Sopenharmony_ci * klist_remove - Decrement the refcount of node and wait for it to go away.
23662306a36Sopenharmony_ci * @n: node we're removing.
23762306a36Sopenharmony_ci */
23862306a36Sopenharmony_civoid klist_remove(struct klist_node *n)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	struct klist_waiter waiter;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	waiter.node = n;
24362306a36Sopenharmony_ci	waiter.process = current;
24462306a36Sopenharmony_ci	waiter.woken = 0;
24562306a36Sopenharmony_ci	spin_lock(&klist_remove_lock);
24662306a36Sopenharmony_ci	list_add(&waiter.list, &klist_remove_waiters);
24762306a36Sopenharmony_ci	spin_unlock(&klist_remove_lock);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	klist_del(n);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	for (;;) {
25262306a36Sopenharmony_ci		set_current_state(TASK_UNINTERRUPTIBLE);
25362306a36Sopenharmony_ci		if (waiter.woken)
25462306a36Sopenharmony_ci			break;
25562306a36Sopenharmony_ci		schedule();
25662306a36Sopenharmony_ci	}
25762306a36Sopenharmony_ci	__set_current_state(TASK_RUNNING);
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_remove);
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci/**
26262306a36Sopenharmony_ci * klist_node_attached - Say whether a node is bound to a list or not.
26362306a36Sopenharmony_ci * @n: Node that we're testing.
26462306a36Sopenharmony_ci */
26562306a36Sopenharmony_ciint klist_node_attached(struct klist_node *n)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	return (n->n_klist != NULL);
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_node_attached);
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci/**
27262306a36Sopenharmony_ci * klist_iter_init_node - Initialize a klist_iter structure.
27362306a36Sopenharmony_ci * @k: klist we're iterating.
27462306a36Sopenharmony_ci * @i: klist_iter we're filling.
27562306a36Sopenharmony_ci * @n: node to start with.
27662306a36Sopenharmony_ci *
27762306a36Sopenharmony_ci * Similar to klist_iter_init(), but starts the action off with @n,
27862306a36Sopenharmony_ci * instead of with the list head.
27962306a36Sopenharmony_ci */
28062306a36Sopenharmony_civoid klist_iter_init_node(struct klist *k, struct klist_iter *i,
28162306a36Sopenharmony_ci			  struct klist_node *n)
28262306a36Sopenharmony_ci{
28362306a36Sopenharmony_ci	i->i_klist = k;
28462306a36Sopenharmony_ci	i->i_cur = NULL;
28562306a36Sopenharmony_ci	if (n && kref_get_unless_zero(&n->n_ref))
28662306a36Sopenharmony_ci		i->i_cur = n;
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_iter_init_node);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci/**
29162306a36Sopenharmony_ci * klist_iter_init - Iniitalize a klist_iter structure.
29262306a36Sopenharmony_ci * @k: klist we're iterating.
29362306a36Sopenharmony_ci * @i: klist_iter structure we're filling.
29462306a36Sopenharmony_ci *
29562306a36Sopenharmony_ci * Similar to klist_iter_init_node(), but start with the list head.
29662306a36Sopenharmony_ci */
29762306a36Sopenharmony_civoid klist_iter_init(struct klist *k, struct klist_iter *i)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	klist_iter_init_node(k, i, NULL);
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_iter_init);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci/**
30462306a36Sopenharmony_ci * klist_iter_exit - Finish a list iteration.
30562306a36Sopenharmony_ci * @i: Iterator structure.
30662306a36Sopenharmony_ci *
30762306a36Sopenharmony_ci * Must be called when done iterating over list, as it decrements the
30862306a36Sopenharmony_ci * refcount of the current node. Necessary in case iteration exited before
30962306a36Sopenharmony_ci * the end of the list was reached, and always good form.
31062306a36Sopenharmony_ci */
31162306a36Sopenharmony_civoid klist_iter_exit(struct klist_iter *i)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	if (i->i_cur) {
31462306a36Sopenharmony_ci		klist_put(i->i_cur, false);
31562306a36Sopenharmony_ci		i->i_cur = NULL;
31662306a36Sopenharmony_ci	}
31762306a36Sopenharmony_ci}
31862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_iter_exit);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cistatic struct klist_node *to_klist_node(struct list_head *n)
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	return container_of(n, struct klist_node, n_node);
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci/**
32662306a36Sopenharmony_ci * klist_prev - Ante up prev node in list.
32762306a36Sopenharmony_ci * @i: Iterator structure.
32862306a36Sopenharmony_ci *
32962306a36Sopenharmony_ci * First grab list lock. Decrement the reference count of the previous
33062306a36Sopenharmony_ci * node, if there was one. Grab the prev node, increment its reference
33162306a36Sopenharmony_ci * count, drop the lock, and return that prev node.
33262306a36Sopenharmony_ci */
33362306a36Sopenharmony_cistruct klist_node *klist_prev(struct klist_iter *i)
33462306a36Sopenharmony_ci{
33562306a36Sopenharmony_ci	void (*put)(struct klist_node *) = i->i_klist->put;
33662306a36Sopenharmony_ci	struct klist_node *last = i->i_cur;
33762306a36Sopenharmony_ci	struct klist_node *prev;
33862306a36Sopenharmony_ci	unsigned long flags;
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	spin_lock_irqsave(&i->i_klist->k_lock, flags);
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	if (last) {
34362306a36Sopenharmony_ci		prev = to_klist_node(last->n_node.prev);
34462306a36Sopenharmony_ci		if (!klist_dec_and_del(last))
34562306a36Sopenharmony_ci			put = NULL;
34662306a36Sopenharmony_ci	} else
34762306a36Sopenharmony_ci		prev = to_klist_node(i->i_klist->k_list.prev);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	i->i_cur = NULL;
35062306a36Sopenharmony_ci	while (prev != to_klist_node(&i->i_klist->k_list)) {
35162306a36Sopenharmony_ci		if (likely(!knode_dead(prev))) {
35262306a36Sopenharmony_ci			kref_get(&prev->n_ref);
35362306a36Sopenharmony_ci			i->i_cur = prev;
35462306a36Sopenharmony_ci			break;
35562306a36Sopenharmony_ci		}
35662306a36Sopenharmony_ci		prev = to_klist_node(prev->n_node.prev);
35762306a36Sopenharmony_ci	}
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	spin_unlock_irqrestore(&i->i_klist->k_lock, flags);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	if (put && last)
36262306a36Sopenharmony_ci		put(last);
36362306a36Sopenharmony_ci	return i->i_cur;
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_prev);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci/**
36862306a36Sopenharmony_ci * klist_next - Ante up next node in list.
36962306a36Sopenharmony_ci * @i: Iterator structure.
37062306a36Sopenharmony_ci *
37162306a36Sopenharmony_ci * First grab list lock. Decrement the reference count of the previous
37262306a36Sopenharmony_ci * node, if there was one. Grab the next node, increment its reference
37362306a36Sopenharmony_ci * count, drop the lock, and return that next node.
37462306a36Sopenharmony_ci */
37562306a36Sopenharmony_cistruct klist_node *klist_next(struct klist_iter *i)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	void (*put)(struct klist_node *) = i->i_klist->put;
37862306a36Sopenharmony_ci	struct klist_node *last = i->i_cur;
37962306a36Sopenharmony_ci	struct klist_node *next;
38062306a36Sopenharmony_ci	unsigned long flags;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	spin_lock_irqsave(&i->i_klist->k_lock, flags);
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	if (last) {
38562306a36Sopenharmony_ci		next = to_klist_node(last->n_node.next);
38662306a36Sopenharmony_ci		if (!klist_dec_and_del(last))
38762306a36Sopenharmony_ci			put = NULL;
38862306a36Sopenharmony_ci	} else
38962306a36Sopenharmony_ci		next = to_klist_node(i->i_klist->k_list.next);
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	i->i_cur = NULL;
39262306a36Sopenharmony_ci	while (next != to_klist_node(&i->i_klist->k_list)) {
39362306a36Sopenharmony_ci		if (likely(!knode_dead(next))) {
39462306a36Sopenharmony_ci			kref_get(&next->n_ref);
39562306a36Sopenharmony_ci			i->i_cur = next;
39662306a36Sopenharmony_ci			break;
39762306a36Sopenharmony_ci		}
39862306a36Sopenharmony_ci		next = to_klist_node(next->n_node.next);
39962306a36Sopenharmony_ci	}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	spin_unlock_irqrestore(&i->i_klist->k_lock, flags);
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	if (put && last)
40462306a36Sopenharmony_ci		put(last);
40562306a36Sopenharmony_ci	return i->i_cur;
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(klist_next);
408