X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=lib%2Fklist.c;h=9c94f0b163a11a713299f97876012296f63d51d7;hb=fa791f5bdfa026a9abe1b48934943fd39f1e300b;hp=a70c836c5c4c2617f6929407034a8706b57c4886;hpb=f65e77693aa5a1cf688fc378bc6913a56f9ff7b7;p=powerpc.git diff --git a/lib/klist.c b/lib/klist.c index a70c836c5c..9c94f0b163 100644 --- a/lib/klist.c +++ b/lib/klist.c @@ -42,12 +42,23 @@ /** * 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) + * + * 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. */ -void klist_init(struct klist * k) +void klist_init(struct klist * k, void (*get)(struct klist_node *), + void (*put)(struct klist_node *)) { INIT_LIST_HEAD(&k->k_list); spin_lock_init(&k->k_lock); + k->get = get; + k->put = put; } EXPORT_SYMBOL_GPL(klist_init); @@ -74,6 +85,8 @@ static void klist_node_init(struct klist * k, struct klist_node * n) init_completion(&n->n_removed); kref_init(&n->n_ref); n->n_klist = k; + if (k->get) + k->get(n); } @@ -110,9 +123,12 @@ EXPORT_SYMBOL_GPL(klist_add_tail); static void klist_release(struct kref * kref) { struct klist_node * n = container_of(kref, struct klist_node, n_ref); + void (*put)(struct klist_node *) = n->n_klist->put; list_del(&n->n_node); complete(&n->n_removed); n->n_klist = NULL; + if (put) + put(n); } static int klist_dec_and_del(struct klist_node * n) @@ -183,6 +199,8 @@ void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_ i->i_klist = k; i->i_head = &k->k_list; i->i_cur = n; + if (n) + kref_get(&n->n_ref); } EXPORT_SYMBOL_GPL(klist_iter_init_node);