mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 14:21:47 +00:00
kernfs: Add KERNFS_REMOVING flags
KERNFS_ACTIVATED tracks whether a given node has ever been activated. As a node was only deactivated on removal, this was used for 1. Drain optimization (removed by the previous patch). 2. To hide !activated nodes 3. To avoid double activations 4. Reject adding children to a node being removed 5. Skip activaing a node which is being removed. We want to decouple deactivation from removal so that nodes can be deactivated and hidden dynamically, which makes KERNFS_ACTIVATED useless for all of the above purposes. #1 is already gone. #2 and #3 can instead test whether the node is currently active. A new flag KERNFS_REMOVING is added to explicitly mark nodes which are being removed for #4 and #5. While this leaves KERNFS_ACTIVATED with no users, leave it be as it will be used in a following patch. Cc: Chengming Zhou <zhouchengming@bytedance.com> Tested-by: Chengming Zhou <zhouchengming@bytedance.com> Reviewed-by: Chengming Zhou <zhouchengming@bytedance.com> Signed-off-by: Tejun Heo <tj@kernel.org> Link: https://lore.kernel.org/r/20220828050440.734579-7-tj@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
2d7f9f8c18
commit
c25491747b
@ -705,13 +705,7 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root,
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* ACTIVATED is protected with kernfs_mutex but it was clear when
|
||||
* @kn was added to idr and we just wanna see it set. No need to
|
||||
* grab kernfs_mutex.
|
||||
*/
|
||||
if (unlikely(!(kn->flags & KERNFS_ACTIVATED) ||
|
||||
!atomic_inc_not_zero(&kn->count)))
|
||||
if (unlikely(!kernfs_active(kn) || !atomic_inc_not_zero(&kn->count)))
|
||||
goto err_unlock;
|
||||
|
||||
spin_unlock(&kernfs_idr_lock);
|
||||
@ -753,10 +747,7 @@ int kernfs_add_one(struct kernfs_node *kn)
|
||||
goto out_unlock;
|
||||
|
||||
ret = -ENOENT;
|
||||
if (parent->flags & KERNFS_EMPTY_DIR)
|
||||
goto out_unlock;
|
||||
|
||||
if ((parent->flags & KERNFS_ACTIVATED) && !kernfs_active(parent))
|
||||
if (parent->flags & (KERNFS_REMOVING | KERNFS_EMPTY_DIR))
|
||||
goto out_unlock;
|
||||
|
||||
kn->hash = kernfs_name_hash(kn->name, kn->ns);
|
||||
@ -1336,7 +1327,7 @@ void kernfs_activate(struct kernfs_node *kn)
|
||||
|
||||
pos = NULL;
|
||||
while ((pos = kernfs_next_descendant_post(pos, kn))) {
|
||||
if (pos->flags & KERNFS_ACTIVATED)
|
||||
if (kernfs_active(pos) || (pos->flags & KERNFS_REMOVING))
|
||||
continue;
|
||||
|
||||
WARN_ON_ONCE(pos->parent && RB_EMPTY_NODE(&pos->rb));
|
||||
@ -1368,11 +1359,13 @@ static void __kernfs_remove(struct kernfs_node *kn)
|
||||
|
||||
pr_debug("kernfs %s: removing\n", kn->name);
|
||||
|
||||
/* prevent any new usage under @kn by deactivating all nodes */
|
||||
/* prevent new usage by marking all nodes removing and deactivating */
|
||||
pos = NULL;
|
||||
while ((pos = kernfs_next_descendant_post(pos, kn)))
|
||||
while ((pos = kernfs_next_descendant_post(pos, kn))) {
|
||||
pos->flags |= KERNFS_REMOVING;
|
||||
if (kernfs_active(pos))
|
||||
atomic_add(KN_DEACTIVATED_BIAS, &pos->active);
|
||||
}
|
||||
|
||||
/* deactivate and unlink the subtree node-by-node */
|
||||
do {
|
||||
|
@ -112,6 +112,7 @@ enum kernfs_node_flag {
|
||||
KERNFS_SUICIDED = 0x0800,
|
||||
KERNFS_EMPTY_DIR = 0x1000,
|
||||
KERNFS_HAS_RELEASE = 0x2000,
|
||||
KERNFS_REMOVING = 0x4000,
|
||||
};
|
||||
|
||||
/* @flags for kernfs_create_root() */
|
||||
|
Loading…
Reference in New Issue
Block a user