8092f73c51567 (Thomas Gleixner 2019-06-03 07:45:04 +0200 1) // SPDX-License-Identifier: GPL-2.0-only
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 2) /*
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 3) * klist.c - Routines for manipulating klists.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 4) *
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 5) * Copyright (C) 2005 Patrick Mochel
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 6) *
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 7) * This klist interface provides a couple of structures that wrap around
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 8) * struct list_head to provide explicit list "head" (struct klist) and list
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 9) * "node" (struct klist_node) objects. For struct klist, a spinlock is
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 10) * included that protects access to the actual list itself. struct
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 11) * klist_node provides a pointer to the klist that owns it and a kref
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 12) * reference count that indicates the number of current users of that node
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 13) * in the list.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 14) *
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 15) * The entire point is to provide an interface for iterating over a list
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 16) * that is safe and allows for modification of the list during the
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 17) * iteration (e.g. insertion and removal), including modification of the
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 18) * current node on the list.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 19) *
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 20) * It works using a 3rd object type - struct klist_iter - that is declared
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 21) * and initialized before an iteration. klist_next() is used to acquire the
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 22) * next element in the list. It returns NULL if there are no more items.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 23) * Internally, that routine takes the klist's lock, decrements the
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 24) * reference count of the previous klist_node and increments the count of
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 25) * the next klist_node. It then drops the lock and returns.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 26) *
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 27) * There are primitives for adding and removing nodes to/from a klist.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 28) * When deleting, klist_del() will simply decrement the reference count.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 29) * Only when the count goes to 0 is the node removed from the list.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 30) * klist_remove() will try to delete the node from the list and block until
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 31) * it is actually removed. This is useful for objects (like devices) that
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 32) * have been removed from the system and must be freed (but must wait until
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 33) * all accessors have finished).
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 34) */
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 35)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 36) #include <linux/klist.h>
8bc3bcc93a2b4 (Paul Gortmaker 2011-11-16 21:29:17 -0500 37) #include <linux/export.h>
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 38) #include <linux/sched.h>
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 39)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 40) /*
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 41) * Use the lowest bit of n_klist to mark deleted nodes and exclude
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 42) * dead ones from iteration.
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 43) */
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 44) #define KNODE_DEAD 1LU
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 45) #define KNODE_KLIST_MASK ~KNODE_DEAD
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 46)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 47) static struct klist *knode_klist(struct klist_node *knode)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 48) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 49) return (struct klist *)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 50) ((unsigned long)knode->n_klist & KNODE_KLIST_MASK);
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 51) }
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 52)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 53) static bool knode_dead(struct klist_node *knode)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 54) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 55) return (unsigned long)knode->n_klist & KNODE_DEAD;
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 56) }
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 57)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 58) static void knode_set_klist(struct klist_node *knode, struct klist *klist)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 59) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 60) knode->n_klist = klist;
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 61) /* no knode deserves to start its life dead */
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 62) WARN_ON(knode_dead(knode));
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 63) }
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 64)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 65) static void knode_kill(struct klist_node *knode)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 66) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 67) /* and no knode should die twice ever either, see we're very humane */
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 68) WARN_ON(knode_dead(knode));
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 69) *(unsigned long *)&knode->n_klist |= KNODE_DEAD;
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 70) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 71)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 72) /**
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 73) * klist_init - Initialize a klist structure.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 74) * @k: The klist we're initializing.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 75) * @get: The get function for the embedding object (NULL if none)
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 76) * @put: The put function for the embedding object (NULL if none)
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 77) *
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 78) * Initialises the klist structure. If the klist_node structures are
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 79) * going to be embedded in refcounted objects (necessary for safe
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 80) * deletion) then the get/put arguments are used to initialise
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 81) * functions that take and release references on the embedding
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 82) * objects.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 83) */
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 84) void klist_init(struct klist *k, void (*get)(struct klist_node *),
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 85) void (*put)(struct klist_node *))
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 86) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 87) INIT_LIST_HEAD(&k->k_list);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 88) spin_lock_init(&k->k_lock);
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 89) k->get = get;
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 90) k->put = put;
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 91) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 92) EXPORT_SYMBOL_GPL(klist_init);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 93)
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 94) static void add_head(struct klist *k, struct klist_node *n)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 95) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 96) spin_lock(&k->k_lock);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 97) list_add(&n->n_node, &k->k_list);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 98) spin_unlock(&k->k_lock);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 99) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 100)
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 101) static void add_tail(struct klist *k, struct klist_node *n)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 102) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 103) spin_lock(&k->k_lock);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 104) list_add_tail(&n->n_node, &k->k_list);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 105) spin_unlock(&k->k_lock);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 106) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 107)
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 108) static void klist_node_init(struct klist *k, struct klist_node *n)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 109) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 110) INIT_LIST_HEAD(&n->n_node);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 111) kref_init(&n->n_ref);
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 112) knode_set_klist(n, k);
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 113) if (k->get)
34bb61f9ddabd (James Bottomley 2005-09-06 16:56:51 -0700 114) k->get(n);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 115) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 116)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 117) /**
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 118) * klist_add_head - Initialize a klist_node and add it to front.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 119) * @n: node we're adding.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 120) * @k: klist it's going on.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 121) */
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 122) void klist_add_head(struct klist_node *n, struct klist *k)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 123) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 124) klist_node_init(k, n);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 125) add_head(k, n);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 126) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 127) EXPORT_SYMBOL_GPL(klist_add_head);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 128)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 129) /**
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 130) * klist_add_tail - Initialize a klist_node and add it to back.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 131) * @n: node we're adding.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 132) * @k: klist it's going on.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 133) */
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 134) void klist_add_tail(struct klist_node *n, struct klist *k)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 135) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 136) klist_node_init(k, n);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 137) add_tail(k, n);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 138) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 139) EXPORT_SYMBOL_GPL(klist_add_tail);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 140)
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 141) /**
0f9859ca92c91 (Ken Helias 2014-08-06 16:09:18 -0700 142) * klist_add_behind - Init a klist_node and add it after an existing node
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 143) * @n: node we're adding.
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 144) * @pos: node to put @n after
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 145) */
0f9859ca92c91 (Ken Helias 2014-08-06 16:09:18 -0700 146) void klist_add_behind(struct klist_node *n, struct klist_node *pos)
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 147) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 148) struct klist *k = knode_klist(pos);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 149)
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 150) klist_node_init(k, n);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 151) spin_lock(&k->k_lock);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 152) list_add(&n->n_node, &pos->n_node);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 153) spin_unlock(&k->k_lock);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 154) }
0f9859ca92c91 (Ken Helias 2014-08-06 16:09:18 -0700 155) EXPORT_SYMBOL_GPL(klist_add_behind);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 156)
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 157) /**
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 158) * klist_add_before - Init a klist_node and add it before an existing node
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 159) * @n: node we're adding.
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 160) * @pos: node to put @n after
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 161) */
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 162) void klist_add_before(struct klist_node *n, struct klist_node *pos)
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 163) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 164) struct klist *k = knode_klist(pos);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 165)
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 166) klist_node_init(k, n);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 167) spin_lock(&k->k_lock);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 168) list_add_tail(&n->n_node, &pos->n_node);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 169) spin_unlock(&k->k_lock);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 170) }
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 171) EXPORT_SYMBOL_GPL(klist_add_before);
93dd40013f4f7 (Tejun Heo 2008-04-22 18:58:46 +0900 172)
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 173) struct klist_waiter {
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 174) struct list_head list;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 175) struct klist_node *node;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 176) struct task_struct *process;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 177) int woken;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 178) };
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 179)
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 180) static DEFINE_SPINLOCK(klist_remove_lock);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 181) static LIST_HEAD(klist_remove_waiters);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 182)
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 183) static void klist_release(struct kref *kref)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 184) {
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 185) struct klist_waiter *waiter, *tmp;
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 186) struct klist_node *n = container_of(kref, struct klist_node, n_ref);
7e9f4b2d3e21e (Alan Stern 2006-09-18 16:28:06 -0400 187)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 188) WARN_ON(!knode_dead(n));
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 189) list_del(&n->n_node);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 190) spin_lock(&klist_remove_lock);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 191) list_for_each_entry_safe(waiter, tmp, &klist_remove_waiters, list) {
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 192) if (waiter->node != n)
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 193) continue;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 194)
ac5a2962b02f5 (wang, biao 2013-05-16 09:50:13 +0800 195) list_del(&waiter->list);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 196) waiter->woken = 1;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 197) mb();
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 198) wake_up_process(waiter->process);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 199) }
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 200) spin_unlock(&klist_remove_lock);
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 201) knode_set_klist(n, NULL);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 202) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 203)
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 204) static int klist_dec_and_del(struct klist_node *n)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 205) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 206) return kref_put(&n->n_ref, klist_release);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 207) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 208)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 209) static void klist_put(struct klist_node *n, bool kill)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 210) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 211) struct klist *k = knode_klist(n);
7e9f4b2d3e21e (Alan Stern 2006-09-18 16:28:06 -0400 212) void (*put)(struct klist_node *) = k->put;
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 213)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 214) spin_lock(&k->k_lock);
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 215) if (kill)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 216) knode_kill(n);
7e9f4b2d3e21e (Alan Stern 2006-09-18 16:28:06 -0400 217) if (!klist_dec_and_del(n))
7e9f4b2d3e21e (Alan Stern 2006-09-18 16:28:06 -0400 218) put = NULL;
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 219) spin_unlock(&k->k_lock);
7e9f4b2d3e21e (Alan Stern 2006-09-18 16:28:06 -0400 220) if (put)
7e9f4b2d3e21e (Alan Stern 2006-09-18 16:28:06 -0400 221) put(n);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 222) }
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 223)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 224) /**
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 225) * klist_del - Decrement the reference count of node and try to remove.
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 226) * @n: node we're deleting.
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 227) */
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 228) void klist_del(struct klist_node *n)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 229) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 230) klist_put(n, true);
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 231) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 232) EXPORT_SYMBOL_GPL(klist_del);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 233)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 234) /**
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 235) * klist_remove - Decrement the refcount of node and wait for it to go away.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 236) * @n: node we're removing.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 237) */
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 238) void klist_remove(struct klist_node *n)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 239) {
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 240) struct klist_waiter waiter;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 241)
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 242) waiter.node = n;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 243) waiter.process = current;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 244) waiter.woken = 0;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 245) spin_lock(&klist_remove_lock);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 246) list_add(&waiter.list, &klist_remove_waiters);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 247) spin_unlock(&klist_remove_lock);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 248)
7e9f4b2d3e21e (Alan Stern 2006-09-18 16:28:06 -0400 249) klist_del(n);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 250)
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 251) for (;;) {
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 252) set_current_state(TASK_UNINTERRUPTIBLE);
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 253) if (waiter.woken)
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 254) break;
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 255) schedule();
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 256) }
210272a28465a (Matthew Wilcox 2008-10-16 14:57:54 -0600 257) __set_current_state(TASK_RUNNING);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 258) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 259) EXPORT_SYMBOL_GPL(klist_remove);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 260)
8b0c250be489d (Patrick Mochel 2005-03-24 12:58:57 -0800 261) /**
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 262) * klist_node_attached - Say whether a node is bound to a list or not.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 263) * @n: Node that we're testing.
8b0c250be489d (Patrick Mochel 2005-03-24 12:58:57 -0800 264) */
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 265) int klist_node_attached(struct klist_node *n)
8b0c250be489d (Patrick Mochel 2005-03-24 12:58:57 -0800 266) {
8b0c250be489d (Patrick Mochel 2005-03-24 12:58:57 -0800 267) return (n->n_klist != NULL);
8b0c250be489d (Patrick Mochel 2005-03-24 12:58:57 -0800 268) }
8b0c250be489d (Patrick Mochel 2005-03-24 12:58:57 -0800 269) EXPORT_SYMBOL_GPL(klist_node_attached);
8b0c250be489d (Patrick Mochel 2005-03-24 12:58:57 -0800 270)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 271) /**
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 272) * klist_iter_init_node - Initialize a klist_iter structure.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 273) * @k: klist we're iterating.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 274) * @i: klist_iter we're filling.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 275) * @n: node to start with.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 276) *
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 277) * Similar to klist_iter_init(), but starts the action off with @n,
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 278) * instead of with the list head.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 279) */
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 280) void klist_iter_init_node(struct klist *k, struct klist_iter *i,
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 281) struct klist_node *n)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 282) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 283) i->i_klist = k;
00cd29b799e34 (James Bottomley 2016-01-13 08:10:31 -0800 284) i->i_cur = NULL;
00cd29b799e34 (James Bottomley 2016-01-13 08:10:31 -0800 285) if (n && kref_get_unless_zero(&n->n_ref))
00cd29b799e34 (James Bottomley 2016-01-13 08:10:31 -0800 286) i->i_cur = n;
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 287) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 288) EXPORT_SYMBOL_GPL(klist_iter_init_node);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 289)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 290) /**
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 291) * klist_iter_init - Iniitalize a klist_iter structure.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 292) * @k: klist we're iterating.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 293) * @i: klist_iter structure we're filling.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 294) *
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 295) * Similar to klist_iter_init_node(), but start with the list head.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 296) */
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 297) void klist_iter_init(struct klist *k, struct klist_iter *i)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 298) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 299) klist_iter_init_node(k, i, NULL);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 300) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 301) EXPORT_SYMBOL_GPL(klist_iter_init);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 302)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 303) /**
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 304) * klist_iter_exit - Finish a list iteration.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 305) * @i: Iterator structure.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 306) *
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 307) * Must be called when done iterating over list, as it decrements the
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 308) * refcount of the current node. Necessary in case iteration exited before
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 309) * the end of the list was reached, and always good form.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 310) */
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 311) void klist_iter_exit(struct klist_iter *i)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 312) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 313) if (i->i_cur) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 314) klist_put(i->i_cur, false);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 315) i->i_cur = NULL;
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 316) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 317) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 318) EXPORT_SYMBOL_GPL(klist_iter_exit);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 319)
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 320) static struct klist_node *to_klist_node(struct list_head *n)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 321) {
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 322) return container_of(n, struct klist_node, n_node);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 323) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 324)
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 325) /**
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 326) * klist_prev - Ante up prev node in list.
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 327) * @i: Iterator structure.
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 328) *
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 329) * First grab list lock. Decrement the reference count of the previous
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 330) * node, if there was one. Grab the prev node, increment its reference
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 331) * count, drop the lock, and return that prev node.
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 332) */
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 333) struct klist_node *klist_prev(struct klist_iter *i)
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 334) {
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 335) void (*put)(struct klist_node *) = i->i_klist->put;
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 336) struct klist_node *last = i->i_cur;
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 337) struct klist_node *prev;
624fa7790f805 (Bart Van Assche 2018-06-22 14:54:49 -0700 338) unsigned long flags;
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 339)
624fa7790f805 (Bart Van Assche 2018-06-22 14:54:49 -0700 340) spin_lock_irqsave(&i->i_klist->k_lock, flags);
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 341)
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 342) if (last) {
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 343) prev = to_klist_node(last->n_node.prev);
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 344) if (!klist_dec_and_del(last))
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 345) put = NULL;
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 346) } else
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 347) prev = to_klist_node(i->i_klist->k_list.prev);
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 348)
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 349) i->i_cur = NULL;
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 350) while (prev != to_klist_node(&i->i_klist->k_list)) {
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 351) if (likely(!knode_dead(prev))) {
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 352) kref_get(&prev->n_ref);
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 353) i->i_cur = prev;
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 354) break;
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 355) }
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 356) prev = to_klist_node(prev->n_node.prev);
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 357) }
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 358)
624fa7790f805 (Bart Van Assche 2018-06-22 14:54:49 -0700 359) spin_unlock_irqrestore(&i->i_klist->k_lock, flags);
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 360)
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 361) if (put && last)
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 362) put(last);
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 363) return i->i_cur;
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 364) }
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 365) EXPORT_SYMBOL_GPL(klist_prev);
2e0fed7f7cdc4 (Andy Shevchenko 2015-07-27 18:03:59 +0300 366)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 367) /**
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 368) * klist_next - Ante up next node in list.
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 369) * @i: Iterator structure.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 370) *
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 371) * First grab list lock. Decrement the reference count of the previous
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 372) * node, if there was one. Grab the next node, increment its reference
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 373) * count, drop the lock, and return that next node.
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 374) */
c3bb7fadaf52d (Greg Kroah-Hartman 2008-04-30 16:43:45 -0700 375) struct klist_node *klist_next(struct klist_iter *i)
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 376) {
7e9f4b2d3e21e (Alan Stern 2006-09-18 16:28:06 -0400 377) void (*put)(struct klist_node *) = i->i_klist->put;
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 378) struct klist_node *last = i->i_cur;
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 379) struct klist_node *next;
624fa7790f805 (Bart Van Assche 2018-06-22 14:54:49 -0700 380) unsigned long flags;
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 381)
624fa7790f805 (Bart Van Assche 2018-06-22 14:54:49 -0700 382) spin_lock_irqsave(&i->i_klist->k_lock, flags);
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 383)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 384) if (last) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 385) next = to_klist_node(last->n_node.next);
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 386) if (!klist_dec_and_del(last))
7e9f4b2d3e21e (Alan Stern 2006-09-18 16:28:06 -0400 387) put = NULL;
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 388) } else
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 389) next = to_klist_node(i->i_klist->k_list.next);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 390)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 391) i->i_cur = NULL;
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 392) while (next != to_klist_node(&i->i_klist->k_list)) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 393) if (likely(!knode_dead(next))) {
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 394) kref_get(&next->n_ref);
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 395) i->i_cur = next;
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 396) break;
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 397) }
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 398) next = to_klist_node(next->n_node.next);
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 399) }
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 400)
624fa7790f805 (Bart Van Assche 2018-06-22 14:54:49 -0700 401) spin_unlock_irqrestore(&i->i_klist->k_lock, flags);
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 402)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 403) if (put && last)
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 404) put(last);
a1ed5b0cffe4b (Tejun Heo 2008-08-25 19:50:16 +0200 405) return i->i_cur;
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 406) }
9a19fea436160 (Patrick Mochel 2005-03-21 11:45:16 -0800 407) EXPORT_SYMBOL_GPL(klist_next);