Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2edbfbf1 authored by Al Viro's avatar Al Viro
Browse files

ecryptfs: don't leave RCU pathwalk immediately



If the underlying dentry doesn't have ->d_revalidate(), there's no need to
force dropping out of RCU mode.  All we need for that is to make freeing
ecryptfs_dentry_info RCU-delayed.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3a93e17c
Loading
Loading
Loading
Loading
+16 −14
Original line number Diff line number Diff line
@@ -44,15 +44,15 @@
 */
static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)
{
	struct dentry *lower_dentry;
	int rc = 1;
	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
	int rc;

	if (!(lower_dentry->d_flags & DCACHE_OP_REVALIDATE))
		return 1;

	if (flags & LOOKUP_RCU)
		return -ECHILD;

	lower_dentry = ecryptfs_dentry_to_lower(dentry);
	if (!(lower_dentry->d_flags & DCACHE_OP_REVALIDATE))
		goto out;
	rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
	if (dentry->d_inode) {
		struct inode *lower_inode =
@@ -60,12 +60,17 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)

		fsstack_copy_attr_all(dentry->d_inode, lower_inode);
	}
out:
	return rc;
}

struct kmem_cache *ecryptfs_dentry_info_cache;

static void ecryptfs_dentry_free_rcu(struct rcu_head *head)
{
	kmem_cache_free(ecryptfs_dentry_info_cache,
		container_of(head, struct ecryptfs_dentry_info, rcu));
}

/**
 * ecryptfs_d_release
 * @dentry: The ecryptfs dentry
@@ -74,15 +79,12 @@ struct kmem_cache *ecryptfs_dentry_info_cache;
 */
static void ecryptfs_d_release(struct dentry *dentry)
{
	if (ecryptfs_dentry_to_private(dentry)) {
		if (ecryptfs_dentry_to_lower(dentry)) {
			dput(ecryptfs_dentry_to_lower(dentry));
			mntput(ecryptfs_dentry_to_lower_mnt(dentry));
		}
		kmem_cache_free(ecryptfs_dentry_info_cache,
				ecryptfs_dentry_to_private(dentry));
	struct ecryptfs_dentry_info *p = dentry->d_fsdata;
	if (p) {
		if (p->lower_path.dentry)
			path_put(&p->lower_path);
		call_rcu(&p->rcu, ecryptfs_dentry_free_rcu);
	}
	return;
}

const struct dentry_operations ecryptfs_dops = {
+4 −1
Original line number Diff line number Diff line
@@ -261,7 +261,10 @@ struct ecryptfs_inode_info {
 * vfsmount too. */
struct ecryptfs_dentry_info {
	struct path lower_path;
	union {
		struct ecryptfs_crypt_stat *crypt_stat;
		struct rcu_head rcu;
	};
};

/**