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