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