^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * klist.c - Routines for manipulating klists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005 Patrick Mochel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This klist interface provides a couple of structures that wrap around
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * struct list_head to provide explicit list "head" (struct klist) and list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * "node" (struct klist_node) objects. For struct klist, a spinlock is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * included that protects access to the actual list itself. struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * klist_node provides a pointer to the klist that owns it and a kref
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * reference count that indicates the number of current users of that node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * in the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * The entire point is to provide an interface for iterating over a list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * that is safe and allows for modification of the list during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * iteration (e.g. insertion and removal), including modification of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * current node on the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * It works using a 3rd object type - struct klist_iter - that is declared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * and initialized before an iteration. klist_next() is used to acquire the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * next element in the list. It returns NULL if there are no more items.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Internally, that routine takes the klist's lock, decrements the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * reference count of the previous klist_node and increments the count of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * the next klist_node. It then drops the lock and returns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * There are primitives for adding and removing nodes to/from a klist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * When deleting, klist_del() will simply decrement the reference count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Only when the count goes to 0 is the node removed from the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * klist_remove() will try to delete the node from the list and block until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * it is actually removed. This is useful for objects (like devices) that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * have been removed from the system and must be freed (but must wait until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * all accessors have finished).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/klist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Use the lowest bit of n_klist to mark deleted nodes and exclude
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * dead ones from iteration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define KNODE_DEAD 1LU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define KNODE_KLIST_MASK ~KNODE_DEAD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static struct klist *knode_klist(struct klist_node *knode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return (struct klist *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ((unsigned long)knode->n_klist & KNODE_KLIST_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static bool knode_dead(struct klist_node *knode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return (unsigned long)knode->n_klist & KNODE_DEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static void knode_set_klist(struct klist_node *knode, struct klist *klist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) knode->n_klist = klist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* no knode deserves to start its life dead */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) WARN_ON(knode_dead(knode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static void knode_kill(struct klist_node *knode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* and no knode should die twice ever either, see we're very humane */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) WARN_ON(knode_dead(knode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *(unsigned long *)&knode->n_klist |= KNODE_DEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * klist_init - Initialize a klist structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * @k: The klist we're initializing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * @get: The get function for the embedding object (NULL if none)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * @put: The put function for the embedding object (NULL if none)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * Initialises the klist structure. If the klist_node structures are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * going to be embedded in refcounted objects (necessary for safe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * deletion) then the get/put arguments are used to initialise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * functions that take and release references on the embedding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * objects.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) void klist_init(struct klist *k, void (*get)(struct klist_node *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) void (*put)(struct klist_node *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) INIT_LIST_HEAD(&k->k_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) spin_lock_init(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) k->get = get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) k->put = put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) EXPORT_SYMBOL_GPL(klist_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static void add_head(struct klist *k, struct klist_node *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) spin_lock(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) list_add(&n->n_node, &k->k_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) spin_unlock(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void add_tail(struct klist *k, struct klist_node *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) spin_lock(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) list_add_tail(&n->n_node, &k->k_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) spin_unlock(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static void klist_node_init(struct klist *k, struct klist_node *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) INIT_LIST_HEAD(&n->n_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) kref_init(&n->n_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) knode_set_klist(n, k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (k->get)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) k->get(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * klist_add_head - Initialize a klist_node and add it to front.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @n: node we're adding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * @k: klist it's going on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) void klist_add_head(struct klist_node *n, struct klist *k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) klist_node_init(k, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) add_head(k, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) EXPORT_SYMBOL_GPL(klist_add_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * klist_add_tail - Initialize a klist_node and add it to back.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * @n: node we're adding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * @k: klist it's going on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) void klist_add_tail(struct klist_node *n, struct klist *k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) klist_node_init(k, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) add_tail(k, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) EXPORT_SYMBOL_GPL(klist_add_tail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * klist_add_behind - Init a klist_node and add it after an existing node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * @n: node we're adding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @pos: node to put @n after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) void klist_add_behind(struct klist_node *n, struct klist_node *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct klist *k = knode_klist(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) klist_node_init(k, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) spin_lock(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) list_add(&n->n_node, &pos->n_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) spin_unlock(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) EXPORT_SYMBOL_GPL(klist_add_behind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * klist_add_before - Init a klist_node and add it before an existing node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * @n: node we're adding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * @pos: node to put @n after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) void klist_add_before(struct klist_node *n, struct klist_node *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct klist *k = knode_klist(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) klist_node_init(k, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) spin_lock(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) list_add_tail(&n->n_node, &pos->n_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) spin_unlock(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) EXPORT_SYMBOL_GPL(klist_add_before);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct klist_waiter {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct klist_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct task_struct *process;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int woken;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static DEFINE_SPINLOCK(klist_remove_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static LIST_HEAD(klist_remove_waiters);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void klist_release(struct kref *kref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct klist_waiter *waiter, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct klist_node *n = container_of(kref, struct klist_node, n_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) WARN_ON(!knode_dead(n));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) list_del(&n->n_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) spin_lock(&klist_remove_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) list_for_each_entry_safe(waiter, tmp, &klist_remove_waiters, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (waiter->node != n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) list_del(&waiter->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) waiter->woken = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) wake_up_process(waiter->process);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) spin_unlock(&klist_remove_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) knode_set_klist(n, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int klist_dec_and_del(struct klist_node *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return kref_put(&n->n_ref, klist_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static void klist_put(struct klist_node *n, bool kill)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct klist *k = knode_klist(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) void (*put)(struct klist_node *) = k->put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) spin_lock(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (kill)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) knode_kill(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (!klist_dec_and_del(n))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) put = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) spin_unlock(&k->k_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (put)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) put(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * klist_del - Decrement the reference count of node and try to remove.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * @n: node we're deleting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) void klist_del(struct klist_node *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) klist_put(n, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) EXPORT_SYMBOL_GPL(klist_del);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * klist_remove - Decrement the refcount of node and wait for it to go away.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * @n: node we're removing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) void klist_remove(struct klist_node *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct klist_waiter waiter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) waiter.node = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) waiter.process = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) waiter.woken = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) spin_lock(&klist_remove_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) list_add(&waiter.list, &klist_remove_waiters);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) spin_unlock(&klist_remove_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) klist_del(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) set_current_state(TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (waiter.woken)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) EXPORT_SYMBOL_GPL(klist_remove);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * klist_node_attached - Say whether a node is bound to a list or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * @n: Node that we're testing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) int klist_node_attached(struct klist_node *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return (n->n_klist != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) EXPORT_SYMBOL_GPL(klist_node_attached);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * klist_iter_init_node - Initialize a klist_iter structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * @k: klist we're iterating.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * @i: klist_iter we're filling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * @n: node to start with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * Similar to klist_iter_init(), but starts the action off with @n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * instead of with the list head.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) void klist_iter_init_node(struct klist *k, struct klist_iter *i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct klist_node *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) i->i_klist = k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) i->i_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (n && kref_get_unless_zero(&n->n_ref))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) i->i_cur = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) EXPORT_SYMBOL_GPL(klist_iter_init_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * klist_iter_init - Iniitalize a klist_iter structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * @k: klist we're iterating.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * @i: klist_iter structure we're filling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * Similar to klist_iter_init_node(), but start with the list head.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) void klist_iter_init(struct klist *k, struct klist_iter *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) klist_iter_init_node(k, i, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) EXPORT_SYMBOL_GPL(klist_iter_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * klist_iter_exit - Finish a list iteration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * @i: Iterator structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * Must be called when done iterating over list, as it decrements the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * refcount of the current node. Necessary in case iteration exited before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * the end of the list was reached, and always good form.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) void klist_iter_exit(struct klist_iter *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (i->i_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) klist_put(i->i_cur, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) i->i_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) EXPORT_SYMBOL_GPL(klist_iter_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static struct klist_node *to_klist_node(struct list_head *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return container_of(n, struct klist_node, n_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * klist_prev - Ante up prev node in list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * @i: Iterator structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * First grab list lock. Decrement the reference count of the previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * node, if there was one. Grab the prev node, increment its reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * count, drop the lock, and return that prev node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct klist_node *klist_prev(struct klist_iter *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) void (*put)(struct klist_node *) = i->i_klist->put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct klist_node *last = i->i_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct klist_node *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) spin_lock_irqsave(&i->i_klist->k_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (last) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) prev = to_klist_node(last->n_node.prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (!klist_dec_and_del(last))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) put = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) prev = to_klist_node(i->i_klist->k_list.prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) i->i_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) while (prev != to_klist_node(&i->i_klist->k_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (likely(!knode_dead(prev))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) kref_get(&prev->n_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) i->i_cur = prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) prev = to_klist_node(prev->n_node.prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) spin_unlock_irqrestore(&i->i_klist->k_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (put && last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) put(last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return i->i_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) EXPORT_SYMBOL_GPL(klist_prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * klist_next - Ante up next node in list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * @i: Iterator structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * First grab list lock. Decrement the reference count of the previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * node, if there was one. Grab the next node, increment its reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * count, drop the lock, and return that next node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct klist_node *klist_next(struct klist_iter *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) void (*put)(struct klist_node *) = i->i_klist->put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct klist_node *last = i->i_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct klist_node *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) spin_lock_irqsave(&i->i_klist->k_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (last) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) next = to_klist_node(last->n_node.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (!klist_dec_and_del(last))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) put = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) next = to_klist_node(i->i_klist->k_list.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) i->i_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) while (next != to_klist_node(&i->i_klist->k_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (likely(!knode_dead(next))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) kref_get(&next->n_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) i->i_cur = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) next = to_klist_node(next->n_node.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) spin_unlock_irqrestore(&i->i_klist->k_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (put && last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) put(last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return i->i_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) EXPORT_SYMBOL_GPL(klist_next);