aboutsummaryrefslogtreecommitdiffstats
path: root/lib/klist.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/klist.c')
-rw-r--r--lib/klist.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/lib/klist.c b/lib/klist.c
index a70c836c5c4c..bb2f3551d50a 100644
--- a/lib/klist.c
+++ b/lib/klist.c
@@ -42,12 +42,23 @@
42/** 42/**
43 * klist_init - Initialize a klist structure. 43 * klist_init - Initialize a klist structure.
44 * @k: The klist we're initializing. 44 * @k: The klist we're initializing.
45 * @get: The get function for the embedding object (NULL if none)
46 * @put: The put function for the embedding object (NULL if none)
47 *
48 * Initialises the klist structure. If the klist_node structures are
49 * going to be embedded in refcounted objects (necessary for safe
50 * deletion) then the get/put arguments are used to initialise
51 * functions that take and release references on the embedding
52 * objects.
45 */ 53 */
46 54
47void klist_init(struct klist * k) 55void klist_init(struct klist * k, void (*get)(struct klist_node *),
56 void (*put)(struct klist_node *))
48{ 57{
49 INIT_LIST_HEAD(&k->k_list); 58 INIT_LIST_HEAD(&k->k_list);
50 spin_lock_init(&k->k_lock); 59 spin_lock_init(&k->k_lock);
60 k->get = get;
61 k->put = put;
51} 62}
52 63
53EXPORT_SYMBOL_GPL(klist_init); 64EXPORT_SYMBOL_GPL(klist_init);
@@ -74,6 +85,8 @@ static void klist_node_init(struct klist * k, struct klist_node * n)
74 init_completion(&n->n_removed); 85 init_completion(&n->n_removed);
75 kref_init(&n->n_ref); 86 kref_init(&n->n_ref);
76 n->n_klist = k; 87 n->n_klist = k;
88 if (k->get)
89 k->get(n);
77} 90}
78 91
79 92
@@ -110,9 +123,12 @@ EXPORT_SYMBOL_GPL(klist_add_tail);
110static void klist_release(struct kref * kref) 123static void klist_release(struct kref * kref)
111{ 124{
112 struct klist_node * n = container_of(kref, struct klist_node, n_ref); 125 struct klist_node * n = container_of(kref, struct klist_node, n_ref);
126 void (*put)(struct klist_node *) = n->n_klist->put;
113 list_del(&n->n_node); 127 list_del(&n->n_node);
114 complete(&n->n_removed); 128 complete(&n->n_removed);
115 n->n_klist = NULL; 129 n->n_klist = NULL;
130 if (put)
131 put(n);
116} 132}
117 133
118static int klist_dec_and_del(struct klist_node * n) 134static int klist_dec_and_del(struct klist_node * n)