18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/**
38c2ecf20Sopenharmony_ci * eCryptfs: Linux filesystem encryption layer
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 1997-2003 Erez Zadok
68c2ecf20Sopenharmony_ci * Copyright (C) 2001-2003 Stony Brook University
78c2ecf20Sopenharmony_ci * Copyright (C) 2004-2006 International Business Machines Corp.
88c2ecf20Sopenharmony_ci *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/dcache.h>
128c2ecf20Sopenharmony_ci#include <linux/namei.h>
138c2ecf20Sopenharmony_ci#include <linux/mount.h>
148c2ecf20Sopenharmony_ci#include <linux/fs_stack.h>
158c2ecf20Sopenharmony_ci#include <linux/slab.h>
168c2ecf20Sopenharmony_ci#include "ecryptfs_kernel.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/**
198c2ecf20Sopenharmony_ci * ecryptfs_d_revalidate - revalidate an ecryptfs dentry
208c2ecf20Sopenharmony_ci * @dentry: The ecryptfs dentry
218c2ecf20Sopenharmony_ci * @flags: lookup flags
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * Called when the VFS needs to revalidate a dentry. This
248c2ecf20Sopenharmony_ci * is called whenever a name lookup finds a dentry in the
258c2ecf20Sopenharmony_ci * dcache. Most filesystems leave this as NULL, because all their
268c2ecf20Sopenharmony_ci * dentries in the dcache are valid.
278c2ecf20Sopenharmony_ci *
288c2ecf20Sopenharmony_ci * Returns 1 if valid, 0 otherwise.
298c2ecf20Sopenharmony_ci *
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_cistatic int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
348c2ecf20Sopenharmony_ci	int rc = 1;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	if (flags & LOOKUP_RCU)
378c2ecf20Sopenharmony_ci		return -ECHILD;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	if (lower_dentry->d_flags & DCACHE_OP_REVALIDATE)
408c2ecf20Sopenharmony_ci		rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	if (d_really_is_positive(dentry)) {
438c2ecf20Sopenharmony_ci		struct inode *inode = d_inode(dentry);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci		fsstack_copy_attr_all(inode, ecryptfs_inode_to_lower(inode));
468c2ecf20Sopenharmony_ci		if (!inode->i_nlink)
478c2ecf20Sopenharmony_ci			return 0;
488c2ecf20Sopenharmony_ci	}
498c2ecf20Sopenharmony_ci	return rc;
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistruct kmem_cache *ecryptfs_dentry_info_cache;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic void ecryptfs_dentry_free_rcu(struct rcu_head *head)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	kmem_cache_free(ecryptfs_dentry_info_cache,
578c2ecf20Sopenharmony_ci		container_of(head, struct ecryptfs_dentry_info, rcu));
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/**
618c2ecf20Sopenharmony_ci * ecryptfs_d_release
628c2ecf20Sopenharmony_ci * @dentry: The ecryptfs dentry
638c2ecf20Sopenharmony_ci *
648c2ecf20Sopenharmony_ci * Called when a dentry is really deallocated.
658c2ecf20Sopenharmony_ci */
668c2ecf20Sopenharmony_cistatic void ecryptfs_d_release(struct dentry *dentry)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	struct ecryptfs_dentry_info *p = dentry->d_fsdata;
698c2ecf20Sopenharmony_ci	if (p) {
708c2ecf20Sopenharmony_ci		path_put(&p->lower_path);
718c2ecf20Sopenharmony_ci		call_rcu(&p->rcu, ecryptfs_dentry_free_rcu);
728c2ecf20Sopenharmony_ci	}
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ciconst struct dentry_operations ecryptfs_dops = {
768c2ecf20Sopenharmony_ci	.d_revalidate = ecryptfs_d_revalidate,
778c2ecf20Sopenharmony_ci	.d_release = ecryptfs_d_release,
788c2ecf20Sopenharmony_ci};
79