Blame view

lib/klist.c 10.3 KB
9a19fea43   Patrick Mochel   [PATCH] Add initi...
1
  /*
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
2
   * klist.c - Routines for manipulating klists.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
3
   *
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
4
   * Copyright (C) 2005 Patrick Mochel
9a19fea43   Patrick Mochel   [PATCH] Add initi...
5
   *
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
6
   * This file is released under the GPL v2.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
7
   *
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
8
9
10
11
12
13
14
   * This klist interface provides a couple of structures that wrap around
   * struct list_head to provide explicit list "head" (struct klist) and list
   * "node" (struct klist_node) objects. For struct klist, a spinlock is
   * included that protects access to the actual list itself. struct
   * klist_node provides a pointer to the klist that owns it and a kref
   * reference count that indicates the number of current users of that node
   * in the list.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
15
   *
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
16
17
18
19
   * The entire point is to provide an interface for iterating over a list
   * that is safe and allows for modification of the list during the
   * iteration (e.g. insertion and removal), including modification of the
   * current node on the list.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
20
   *
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
21
22
23
24
25
26
   * It works using a 3rd object type - struct klist_iter - that is declared
   * and initialized before an iteration. klist_next() is used to acquire the
   * next element in the list. It returns NULL if there are no more items.
   * Internally, that routine takes the klist's lock, decrements the
   * reference count of the previous klist_node and increments the count of
   * the next klist_node. It then drops the lock and returns.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
27
   *
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
28
29
30
31
32
33
34
   * There are primitives for adding and removing nodes to/from a klist.
   * When deleting, klist_del() will simply decrement the reference count.
   * Only when the count goes to 0 is the node removed from the list.
   * klist_remove() will try to delete the node from the list and block until
   * it is actually removed. This is useful for objects (like devices) that
   * have been removed from the system and must be freed (but must wait until
   * all accessors have finished).
9a19fea43   Patrick Mochel   [PATCH] Add initi...
35
36
37
   */
  
  #include <linux/klist.h>
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
38
  #include <linux/export.h>
210272a28   Matthew Wilcox   driver core: Remo...
39
  #include <linux/sched.h>
9a19fea43   Patrick Mochel   [PATCH] Add initi...
40

a1ed5b0cf   Tejun Heo   klist: don't iter...
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  /*
   * Use the lowest bit of n_klist to mark deleted nodes and exclude
   * dead ones from iteration.
   */
  #define KNODE_DEAD		1LU
  #define KNODE_KLIST_MASK	~KNODE_DEAD
  
  static struct klist *knode_klist(struct klist_node *knode)
  {
  	return (struct klist *)
  		((unsigned long)knode->n_klist & KNODE_KLIST_MASK);
  }
  
  static bool knode_dead(struct klist_node *knode)
  {
  	return (unsigned long)knode->n_klist & KNODE_DEAD;
  }
  
  static void knode_set_klist(struct klist_node *knode, struct klist *klist)
  {
  	knode->n_klist = klist;
  	/* no knode deserves to start its life dead */
  	WARN_ON(knode_dead(knode));
  }
  
  static void knode_kill(struct klist_node *knode)
  {
  	/* and no knode should die twice ever either, see we're very humane */
  	WARN_ON(knode_dead(knode));
  	*(unsigned long *)&knode->n_klist |= KNODE_DEAD;
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
72
73
  
  /**
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
74
75
76
77
   * klist_init - Initialize a klist structure.
   * @k: The klist we're initializing.
   * @get: The get function for the embedding object (NULL if none)
   * @put: The put function for the embedding object (NULL if none)
34bb61f9d   James Bottomley   [PATCH] fix klist...
78
79
80
81
82
83
   *
   * Initialises the klist structure.  If the klist_node structures are
   * going to be embedded in refcounted objects (necessary for safe
   * deletion) then the get/put arguments are used to initialise
   * functions that take and release references on the embedding
   * objects.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
84
   */
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
85
  void klist_init(struct klist *k, void (*get)(struct klist_node *),
34bb61f9d   James Bottomley   [PATCH] fix klist...
86
  		void (*put)(struct klist_node *))
9a19fea43   Patrick Mochel   [PATCH] Add initi...
87
88
89
  {
  	INIT_LIST_HEAD(&k->k_list);
  	spin_lock_init(&k->k_lock);
34bb61f9d   James Bottomley   [PATCH] fix klist...
90
91
  	k->get = get;
  	k->put = put;
9a19fea43   Patrick Mochel   [PATCH] Add initi...
92
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
93
  EXPORT_SYMBOL_GPL(klist_init);
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
94
  static void add_head(struct klist *k, struct klist_node *n)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
95
96
97
98
99
  {
  	spin_lock(&k->k_lock);
  	list_add(&n->n_node, &k->k_list);
  	spin_unlock(&k->k_lock);
  }
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
100
  static void add_tail(struct klist *k, struct klist_node *n)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
101
102
103
104
105
  {
  	spin_lock(&k->k_lock);
  	list_add_tail(&n->n_node, &k->k_list);
  	spin_unlock(&k->k_lock);
  }
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
106
  static void klist_node_init(struct klist *k, struct klist_node *n)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
107
108
  {
  	INIT_LIST_HEAD(&n->n_node);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
109
  	kref_init(&n->n_ref);
a1ed5b0cf   Tejun Heo   klist: don't iter...
110
  	knode_set_klist(n, k);
34bb61f9d   James Bottomley   [PATCH] fix klist...
111
112
  	if (k->get)
  		k->get(n);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
113
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
114
  /**
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
115
116
117
   * klist_add_head - Initialize a klist_node and add it to front.
   * @n: node we're adding.
   * @k: klist it's going on.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
118
   */
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
119
  void klist_add_head(struct klist_node *n, struct klist *k)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
120
121
122
123
  {
  	klist_node_init(k, n);
  	add_head(k, n);
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
124
  EXPORT_SYMBOL_GPL(klist_add_head);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
125
  /**
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
126
127
128
   * klist_add_tail - Initialize a klist_node and add it to back.
   * @n: node we're adding.
   * @k: klist it's going on.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
129
   */
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
130
  void klist_add_tail(struct klist_node *n, struct klist *k)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
131
132
133
134
  {
  	klist_node_init(k, n);
  	add_tail(k, n);
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
135
  EXPORT_SYMBOL_GPL(klist_add_tail);
93dd40013   Tejun Heo   klist: implement ...
136
  /**
0f9859ca9   Ken Helias   klist: use same n...
137
   * klist_add_behind - Init a klist_node and add it after an existing node
93dd40013   Tejun Heo   klist: implement ...
138
139
140
   * @n: node we're adding.
   * @pos: node to put @n after
   */
0f9859ca9   Ken Helias   klist: use same n...
141
  void klist_add_behind(struct klist_node *n, struct klist_node *pos)
93dd40013   Tejun Heo   klist: implement ...
142
  {
a1ed5b0cf   Tejun Heo   klist: don't iter...
143
  	struct klist *k = knode_klist(pos);
93dd40013   Tejun Heo   klist: implement ...
144
145
146
147
148
149
  
  	klist_node_init(k, n);
  	spin_lock(&k->k_lock);
  	list_add(&n->n_node, &pos->n_node);
  	spin_unlock(&k->k_lock);
  }
0f9859ca9   Ken Helias   klist: use same n...
150
  EXPORT_SYMBOL_GPL(klist_add_behind);
93dd40013   Tejun Heo   klist: implement ...
151
152
153
154
155
156
157
158
  
  /**
   * klist_add_before - Init a klist_node and add it before an existing node
   * @n: node we're adding.
   * @pos: node to put @n after
   */
  void klist_add_before(struct klist_node *n, struct klist_node *pos)
  {
a1ed5b0cf   Tejun Heo   klist: don't iter...
159
  	struct klist *k = knode_klist(pos);
93dd40013   Tejun Heo   klist: implement ...
160
161
162
163
164
165
166
  
  	klist_node_init(k, n);
  	spin_lock(&k->k_lock);
  	list_add_tail(&n->n_node, &pos->n_node);
  	spin_unlock(&k->k_lock);
  }
  EXPORT_SYMBOL_GPL(klist_add_before);
210272a28   Matthew Wilcox   driver core: Remo...
167
168
169
170
171
172
173
174
175
  struct klist_waiter {
  	struct list_head list;
  	struct klist_node *node;
  	struct task_struct *process;
  	int woken;
  };
  
  static DEFINE_SPINLOCK(klist_remove_lock);
  static LIST_HEAD(klist_remove_waiters);
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
176
  static void klist_release(struct kref *kref)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
177
  {
210272a28   Matthew Wilcox   driver core: Remo...
178
  	struct klist_waiter *waiter, *tmp;
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
179
  	struct klist_node *n = container_of(kref, struct klist_node, n_ref);
7e9f4b2d3   Alan Stern   Driver core: Don'...
180

a1ed5b0cf   Tejun Heo   klist: don't iter...
181
  	WARN_ON(!knode_dead(n));
9a19fea43   Patrick Mochel   [PATCH] Add initi...
182
  	list_del(&n->n_node);
210272a28   Matthew Wilcox   driver core: Remo...
183
184
185
186
  	spin_lock(&klist_remove_lock);
  	list_for_each_entry_safe(waiter, tmp, &klist_remove_waiters, list) {
  		if (waiter->node != n)
  			continue;
ac5a2962b   wang, biao   klist: del waiter...
187
  		list_del(&waiter->list);
210272a28   Matthew Wilcox   driver core: Remo...
188
189
190
  		waiter->woken = 1;
  		mb();
  		wake_up_process(waiter->process);
210272a28   Matthew Wilcox   driver core: Remo...
191
192
  	}
  	spin_unlock(&klist_remove_lock);
a1ed5b0cf   Tejun Heo   klist: don't iter...
193
  	knode_set_klist(n, NULL);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
194
  }
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
195
  static int klist_dec_and_del(struct klist_node *n)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
196
197
198
  {
  	return kref_put(&n->n_ref, klist_release);
  }
a1ed5b0cf   Tejun Heo   klist: don't iter...
199
  static void klist_put(struct klist_node *n, bool kill)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
200
  {
a1ed5b0cf   Tejun Heo   klist: don't iter...
201
  	struct klist *k = knode_klist(n);
7e9f4b2d3   Alan Stern   Driver core: Don'...
202
  	void (*put)(struct klist_node *) = k->put;
9a19fea43   Patrick Mochel   [PATCH] Add initi...
203
204
  
  	spin_lock(&k->k_lock);
a1ed5b0cf   Tejun Heo   klist: don't iter...
205
206
  	if (kill)
  		knode_kill(n);
7e9f4b2d3   Alan Stern   Driver core: Don'...
207
208
  	if (!klist_dec_and_del(n))
  		put = NULL;
9a19fea43   Patrick Mochel   [PATCH] Add initi...
209
  	spin_unlock(&k->k_lock);
7e9f4b2d3   Alan Stern   Driver core: Don'...
210
211
  	if (put)
  		put(n);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
212
  }
a1ed5b0cf   Tejun Heo   klist: don't iter...
213
214
215
216
217
218
219
220
221
  
  /**
   * klist_del - Decrement the reference count of node and try to remove.
   * @n: node we're deleting.
   */
  void klist_del(struct klist_node *n)
  {
  	klist_put(n, true);
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
222
  EXPORT_SYMBOL_GPL(klist_del);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
223
  /**
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
224
225
   * klist_remove - Decrement the refcount of node and wait for it to go away.
   * @n: node we're removing.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
226
   */
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
227
  void klist_remove(struct klist_node *n)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
228
  {
210272a28   Matthew Wilcox   driver core: Remo...
229
230
231
232
233
234
235
236
  	struct klist_waiter waiter;
  
  	waiter.node = n;
  	waiter.process = current;
  	waiter.woken = 0;
  	spin_lock(&klist_remove_lock);
  	list_add(&waiter.list, &klist_remove_waiters);
  	spin_unlock(&klist_remove_lock);
7e9f4b2d3   Alan Stern   Driver core: Don'...
237
  	klist_del(n);
210272a28   Matthew Wilcox   driver core: Remo...
238
239
240
241
242
243
244
245
  
  	for (;;) {
  		set_current_state(TASK_UNINTERRUPTIBLE);
  		if (waiter.woken)
  			break;
  		schedule();
  	}
  	__set_current_state(TASK_RUNNING);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
246
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
247
  EXPORT_SYMBOL_GPL(klist_remove);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
248
  /**
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
249
250
   * klist_node_attached - Say whether a node is bound to a list or not.
   * @n: Node that we're testing.
8b0c250be   Patrick Mochel   [PATCH] add klist...
251
   */
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
252
  int klist_node_attached(struct klist_node *n)
8b0c250be   Patrick Mochel   [PATCH] add klist...
253
254
255
  {
  	return (n->n_klist != NULL);
  }
8b0c250be   Patrick Mochel   [PATCH] add klist...
256
  EXPORT_SYMBOL_GPL(klist_node_attached);
8b0c250be   Patrick Mochel   [PATCH] add klist...
257
  /**
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
258
259
260
261
   * klist_iter_init_node - Initialize a klist_iter structure.
   * @k: klist we're iterating.
   * @i: klist_iter we're filling.
   * @n: node to start with.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
262
   *
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
263
264
   * Similar to klist_iter_init(), but starts the action off with @n,
   * instead of with the list head.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
265
   */
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
266
267
  void klist_iter_init_node(struct klist *k, struct klist_iter *i,
  			  struct klist_node *n)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
268
269
  {
  	i->i_klist = k;
00cd29b79   James Bottomley   klist: fix starti...
270
271
272
  	i->i_cur = NULL;
  	if (n && kref_get_unless_zero(&n->n_ref))
  		i->i_cur = n;
9a19fea43   Patrick Mochel   [PATCH] Add initi...
273
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
274
  EXPORT_SYMBOL_GPL(klist_iter_init_node);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
275
  /**
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
276
277
278
   * klist_iter_init - Iniitalize a klist_iter structure.
   * @k: klist we're iterating.
   * @i: klist_iter structure we're filling.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
279
   *
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
280
   * Similar to klist_iter_init_node(), but start with the list head.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
281
   */
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
282
  void klist_iter_init(struct klist *k, struct klist_iter *i)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
283
284
285
  {
  	klist_iter_init_node(k, i, NULL);
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
286
  EXPORT_SYMBOL_GPL(klist_iter_init);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
287
  /**
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
288
289
   * klist_iter_exit - Finish a list iteration.
   * @i: Iterator structure.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
290
   *
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
291
292
293
   * Must be called when done iterating over list, as it decrements the
   * refcount of the current node. Necessary in case iteration exited before
   * the end of the list was reached, and always good form.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
294
   */
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
295
  void klist_iter_exit(struct klist_iter *i)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
296
297
  {
  	if (i->i_cur) {
a1ed5b0cf   Tejun Heo   klist: don't iter...
298
  		klist_put(i->i_cur, false);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
299
300
301
  		i->i_cur = NULL;
  	}
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
302
  EXPORT_SYMBOL_GPL(klist_iter_exit);
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
303
  static struct klist_node *to_klist_node(struct list_head *n)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
304
305
306
  {
  	return container_of(n, struct klist_node, n_node);
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
307
  /**
2e0fed7f7   Andy Shevchenko   klist: implement ...
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
   * klist_prev - Ante up prev node in list.
   * @i: Iterator structure.
   *
   * First grab list lock. Decrement the reference count of the previous
   * node, if there was one. Grab the prev node, increment its reference
   * count, drop the lock, and return that prev node.
   */
  struct klist_node *klist_prev(struct klist_iter *i)
  {
  	void (*put)(struct klist_node *) = i->i_klist->put;
  	struct klist_node *last = i->i_cur;
  	struct klist_node *prev;
  
  	spin_lock(&i->i_klist->k_lock);
  
  	if (last) {
  		prev = to_klist_node(last->n_node.prev);
  		if (!klist_dec_and_del(last))
  			put = NULL;
  	} else
  		prev = to_klist_node(i->i_klist->k_list.prev);
  
  	i->i_cur = NULL;
  	while (prev != to_klist_node(&i->i_klist->k_list)) {
  		if (likely(!knode_dead(prev))) {
  			kref_get(&prev->n_ref);
  			i->i_cur = prev;
  			break;
  		}
  		prev = to_klist_node(prev->n_node.prev);
  	}
  
  	spin_unlock(&i->i_klist->k_lock);
  
  	if (put && last)
  		put(last);
  	return i->i_cur;
  }
  EXPORT_SYMBOL_GPL(klist_prev);
  
  /**
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
349
350
   * klist_next - Ante up next node in list.
   * @i: Iterator structure.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
351
   *
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
352
353
354
   * First grab list lock. Decrement the reference count of the previous
   * node, if there was one. Grab the next node, increment its reference
   * count, drop the lock, and return that next node.
9a19fea43   Patrick Mochel   [PATCH] Add initi...
355
   */
c3bb7fada   Greg Kroah-Hartman   klist: fix coding...
356
  struct klist_node *klist_next(struct klist_iter *i)
9a19fea43   Patrick Mochel   [PATCH] Add initi...
357
  {
7e9f4b2d3   Alan Stern   Driver core: Don'...
358
  	void (*put)(struct klist_node *) = i->i_klist->put;
a1ed5b0cf   Tejun Heo   klist: don't iter...
359
360
  	struct klist_node *last = i->i_cur;
  	struct klist_node *next;
9a19fea43   Patrick Mochel   [PATCH] Add initi...
361
362
  
  	spin_lock(&i->i_klist->k_lock);
a1ed5b0cf   Tejun Heo   klist: don't iter...
363
364
365
366
  
  	if (last) {
  		next = to_klist_node(last->n_node.next);
  		if (!klist_dec_and_del(last))
7e9f4b2d3   Alan Stern   Driver core: Don'...
367
  			put = NULL;
9a19fea43   Patrick Mochel   [PATCH] Add initi...
368
  	} else
a1ed5b0cf   Tejun Heo   klist: don't iter...
369
  		next = to_klist_node(i->i_klist->k_list.next);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
370

a1ed5b0cf   Tejun Heo   klist: don't iter...
371
372
373
374
375
376
377
378
  	i->i_cur = NULL;
  	while (next != to_klist_node(&i->i_klist->k_list)) {
  		if (likely(!knode_dead(next))) {
  			kref_get(&next->n_ref);
  			i->i_cur = next;
  			break;
  		}
  		next = to_klist_node(next->n_node.next);
9a19fea43   Patrick Mochel   [PATCH] Add initi...
379
  	}
a1ed5b0cf   Tejun Heo   klist: don't iter...
380

9a19fea43   Patrick Mochel   [PATCH] Add initi...
381
  	spin_unlock(&i->i_klist->k_lock);
a1ed5b0cf   Tejun Heo   klist: don't iter...
382
383
384
385
  
  	if (put && last)
  		put(last);
  	return i->i_cur;
9a19fea43   Patrick Mochel   [PATCH] Add initi...
386
  }
9a19fea43   Patrick Mochel   [PATCH] Add initi...
387
  EXPORT_SYMBOL_GPL(klist_next);