diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/klist.c | 18 |
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 | ||
47 | void klist_init(struct klist * k) | 55 | void 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 | ||
53 | EXPORT_SYMBOL_GPL(klist_init); | 64 | EXPORT_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); | |||
110 | static void klist_release(struct kref * kref) | 123 | static 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 | ||
118 | static int klist_dec_and_del(struct klist_node * n) | 134 | static int klist_dec_and_del(struct klist_node * n) |