VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
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);