Unverified Commit 02389044 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!7068 kernfs: RCU protect kernfs_nodes and avoid kernfs_idr_lock in...

!7068  kernfs: RCU protect kernfs_nodes and avoid kernfs_idr_lock in kernfs_find_and_get_node_by_id()

Merge Pull Request from: @ci-robot 
 
PR sync from: Li Lingfeng <lilingfeng3@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/DK2VQ76A3OBF7BUQYZASOBFVMXFBA2FR/ 
 
https://gitee.com/openeuler/kernel/issues/I9MPZ8 
 
Link:https://gitee.com/openeuler/kernel/pulls/7068

 

Reviewed-by: default avatarZhang Peng <zhangpeng362@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents b05fe389 6a953678
Loading
Loading
Loading
Loading
+20 −11
Original line number Diff line number Diff line
@@ -529,6 +529,20 @@ void kernfs_get(struct kernfs_node *kn)
}
EXPORT_SYMBOL_GPL(kernfs_get);

static void kernfs_free_rcu(struct rcu_head *rcu)
{
	struct kernfs_node *kn = container_of(rcu, struct kernfs_node, rcu);

	kfree_const(kn->name);

	if (kn->iattr) {
		simple_xattrs_free(&kn->iattr->xattrs, NULL);
		kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
	}

	kmem_cache_free(kernfs_node_cache, kn);
}

/**
 * kernfs_put - put a reference count on a kernfs_node
 * @kn: the target kernfs_node
@@ -557,16 +571,11 @@ void kernfs_put(struct kernfs_node *kn)
	if (kernfs_type(kn) == KERNFS_LINK)
		kernfs_put(kn->symlink.target_kn);

	kfree_const(kn->name);

	if (kn->iattr) {
		simple_xattrs_free(&kn->iattr->xattrs, NULL);
		kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
	}
	spin_lock(&kernfs_idr_lock);
	idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
	spin_unlock(&kernfs_idr_lock);
	kmem_cache_free(kernfs_node_cache, kn);

	call_rcu(&kn->rcu, kernfs_free_rcu);

	kn = parent;
	if (kn) {
@@ -575,7 +584,7 @@ void kernfs_put(struct kernfs_node *kn)
	} else {
		/* just released the root kn, free @root too */
		idr_destroy(&root->ino_idr);
		kfree(root);
		kfree_rcu(root, rcu);
	}
}
EXPORT_SYMBOL_GPL(kernfs_put);
@@ -715,7 +724,7 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root,
	ino_t ino = kernfs_id_ino(id);
	u32 gen = kernfs_id_gen(id);

	spin_lock(&kernfs_idr_lock);
	rcu_read_lock();

	kn = idr_find(&root->ino_idr, (u32)ino);
	if (!kn)
@@ -739,10 +748,10 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root,
	if (unlikely(!__kernfs_active(kn) || !atomic_inc_not_zero(&kn->count)))
		goto err_unlock;

	spin_unlock(&kernfs_idr_lock);
	rcu_read_unlock();
	return kn;
err_unlock:
	spin_unlock(&kernfs_idr_lock);
	rcu_read_unlock();
	return NULL;
}

+2 −0
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ struct kernfs_root {
	struct rw_semaphore	kernfs_iattr_rwsem;
	struct rw_semaphore	kernfs_supers_rwsem;

	struct rcu_head 	rcu;

	KABI_RESERVE(1)
	KABI_RESERVE(2)
	KABI_RESERVE(3)
+2 −0
Original line number Diff line number Diff line
@@ -224,6 +224,8 @@ struct kernfs_node {
	unsigned short		flags;
	umode_t			mode;
	struct kernfs_iattrs	*iattr;

	struct rcu_head		rcu;
};

/*