mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 08:45:26 -05:00
ecryptfs: get rid of pointless mount references in ecryptfs dentries
->lower_path.mnt has the same value for all dentries on given ecryptfs instance and if somebody goes for mountpoint-crossing variant where that would not be true, we can deal with that when it happens (and _not_ with duplicating these reference into each dentry). As it is, we are better off just sticking a reference into ecryptfs-private part of superblock and keeping it pinned until ->kill_sb(). That way we can stick a reference to underlying dentry right into ->d_fsdata of ecryptfs one, getting rid of indirection through struct ecryptfs_dentry_info, along with the entire struct ecryptfs_dentry_info machinery. [kudos to Dan Carpenter for spotting a bug in ecryptfs_get_tree() part] Reviewed-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
@@ -59,14 +59,6 @@ static int ecryptfs_d_revalidate(struct inode *dir, const struct qstr *name,
|
||||
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
|
||||
@@ -75,11 +67,7 @@ static void ecryptfs_dentry_free_rcu(struct rcu_head *head)
|
||||
*/
|
||||
static void ecryptfs_d_release(struct dentry *dentry)
|
||||
{
|
||||
struct ecryptfs_dentry_info *p = dentry->d_fsdata;
|
||||
if (p) {
|
||||
path_put(&p->lower_path);
|
||||
call_rcu(&p->rcu, ecryptfs_dentry_free_rcu);
|
||||
}
|
||||
dput(dentry->d_fsdata);
|
||||
}
|
||||
|
||||
const struct dentry_operations ecryptfs_dops = {
|
||||
|
||||
@@ -258,13 +258,6 @@ struct ecryptfs_inode_info {
|
||||
struct ecryptfs_crypt_stat crypt_stat;
|
||||
};
|
||||
|
||||
/* dentry private data. Each dentry must keep track of a lower
|
||||
* vfsmount too. */
|
||||
struct ecryptfs_dentry_info {
|
||||
struct path lower_path;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
/**
|
||||
* ecryptfs_global_auth_tok - A key used to encrypt all new files under the mountpoint
|
||||
* @flags: Status flags
|
||||
@@ -348,6 +341,7 @@ struct ecryptfs_mount_crypt_stat {
|
||||
/* superblock private data. */
|
||||
struct ecryptfs_sb_info {
|
||||
struct super_block *wsi_sb;
|
||||
struct vfsmount *lower_mnt;
|
||||
struct ecryptfs_mount_crypt_stat mount_crypt_stat;
|
||||
};
|
||||
|
||||
@@ -494,22 +488,25 @@ ecryptfs_set_superblock_lower(struct super_block *sb,
|
||||
}
|
||||
|
||||
static inline void
|
||||
ecryptfs_set_dentry_private(struct dentry *dentry,
|
||||
struct ecryptfs_dentry_info *dentry_info)
|
||||
ecryptfs_set_dentry_lower(struct dentry *dentry,
|
||||
struct dentry *lower_dentry)
|
||||
{
|
||||
dentry->d_fsdata = dentry_info;
|
||||
dentry->d_fsdata = lower_dentry;
|
||||
}
|
||||
|
||||
static inline struct dentry *
|
||||
ecryptfs_dentry_to_lower(struct dentry *dentry)
|
||||
{
|
||||
return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry;
|
||||
return dentry->d_fsdata;
|
||||
}
|
||||
|
||||
static inline const struct path *
|
||||
ecryptfs_dentry_to_lower_path(struct dentry *dentry)
|
||||
static inline struct path
|
||||
ecryptfs_lower_path(struct dentry *dentry)
|
||||
{
|
||||
return &((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path;
|
||||
return (struct path){
|
||||
.mnt = ecryptfs_superblock_to_private(dentry->d_sb)->lower_mnt,
|
||||
.dentry = ecryptfs_dentry_to_lower(dentry)
|
||||
};
|
||||
}
|
||||
|
||||
#define ecryptfs_printk(type, fmt, arg...) \
|
||||
@@ -532,7 +529,6 @@ extern unsigned int ecryptfs_number_of_users;
|
||||
|
||||
extern struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
|
||||
extern struct kmem_cache *ecryptfs_file_info_cache;
|
||||
extern struct kmem_cache *ecryptfs_dentry_info_cache;
|
||||
extern struct kmem_cache *ecryptfs_inode_info_cache;
|
||||
extern struct kmem_cache *ecryptfs_sb_info_cache;
|
||||
extern struct kmem_cache *ecryptfs_header_cache;
|
||||
@@ -557,7 +553,6 @@ int ecryptfs_encrypt_and_encode_filename(
|
||||
size_t *encoded_name_size,
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
|
||||
const char *name, size_t name_size);
|
||||
struct dentry *ecryptfs_lower_dentry(struct dentry *this_dentry);
|
||||
void ecryptfs_dump_hex(char *data, int bytes);
|
||||
int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
|
||||
int sg_size);
|
||||
|
||||
@@ -33,13 +33,12 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
|
||||
struct iov_iter *to)
|
||||
{
|
||||
ssize_t rc;
|
||||
const struct path *path;
|
||||
struct file *file = iocb->ki_filp;
|
||||
|
||||
rc = generic_file_read_iter(iocb, to);
|
||||
if (rc >= 0) {
|
||||
path = ecryptfs_dentry_to_lower_path(file->f_path.dentry);
|
||||
touch_atime(path);
|
||||
struct path path = ecryptfs_lower_path(file->f_path.dentry);
|
||||
touch_atime(&path);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -59,12 +58,11 @@ static ssize_t ecryptfs_splice_read_update_atime(struct file *in, loff_t *ppos,
|
||||
size_t len, unsigned int flags)
|
||||
{
|
||||
ssize_t rc;
|
||||
const struct path *path;
|
||||
|
||||
rc = filemap_splice_read(in, ppos, pipe, len, flags);
|
||||
if (rc >= 0) {
|
||||
path = ecryptfs_dentry_to_lower_path(in->f_path.dentry);
|
||||
touch_atime(path);
|
||||
struct path path = ecryptfs_lower_path(in->f_path.dentry);
|
||||
touch_atime(&path);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -283,6 +281,7 @@ static int ecryptfs_dir_open(struct inode *inode, struct file *file)
|
||||
* ecryptfs_lookup() */
|
||||
struct ecryptfs_file_info *file_info;
|
||||
struct file *lower_file;
|
||||
struct path path;
|
||||
|
||||
/* Released in ecryptfs_release or end of function if failure */
|
||||
file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
|
||||
@@ -292,8 +291,8 @@ static int ecryptfs_dir_open(struct inode *inode, struct file *file)
|
||||
"Error attempting to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
lower_file = dentry_open(ecryptfs_dentry_to_lower_path(ecryptfs_dentry),
|
||||
file->f_flags, current_cred());
|
||||
path = ecryptfs_lower_path(ecryptfs_dentry);
|
||||
lower_file = dentry_open(&path, file->f_flags, current_cred());
|
||||
if (IS_ERR(lower_file)) {
|
||||
printk(KERN_ERR "%s: Error attempting to initialize "
|
||||
"the lower file for the dentry with name "
|
||||
|
||||
@@ -327,24 +327,15 @@ static int ecryptfs_i_size_read(struct dentry *dentry, struct inode *inode)
|
||||
static struct dentry *ecryptfs_lookup_interpose(struct dentry *dentry,
|
||||
struct dentry *lower_dentry)
|
||||
{
|
||||
const struct path *path = ecryptfs_dentry_to_lower_path(dentry->d_parent);
|
||||
struct dentry *lower_parent = ecryptfs_dentry_to_lower(dentry->d_parent);
|
||||
struct inode *inode, *lower_inode;
|
||||
struct ecryptfs_dentry_info *dentry_info;
|
||||
int rc = 0;
|
||||
|
||||
dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL);
|
||||
if (!dentry_info) {
|
||||
dput(lower_dentry);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
fsstack_copy_attr_atime(d_inode(dentry->d_parent),
|
||||
d_inode(path->dentry));
|
||||
d_inode(lower_parent));
|
||||
BUG_ON(!d_count(lower_dentry));
|
||||
|
||||
ecryptfs_set_dentry_private(dentry, dentry_info);
|
||||
dentry_info->lower_path.mnt = mntget(path->mnt);
|
||||
dentry_info->lower_path.dentry = lower_dentry;
|
||||
ecryptfs_set_dentry_lower(dentry, lower_dentry);
|
||||
|
||||
/*
|
||||
* negative dentry can go positive under us here - its parent is not
|
||||
@@ -1022,10 +1013,10 @@ static int ecryptfs_getattr(struct mnt_idmap *idmap,
|
||||
{
|
||||
struct dentry *dentry = path->dentry;
|
||||
struct kstat lower_stat;
|
||||
struct path lower_path = ecryptfs_lower_path(dentry);
|
||||
int rc;
|
||||
|
||||
rc = vfs_getattr_nosec(ecryptfs_dentry_to_lower_path(dentry),
|
||||
&lower_stat, request_mask, flags);
|
||||
rc = vfs_getattr_nosec(&lower_path, &lower_stat, request_mask, flags);
|
||||
if (!rc) {
|
||||
fsstack_copy_attr_all(d_inode(dentry),
|
||||
ecryptfs_inode_to_lower(d_inode(dentry)));
|
||||
|
||||
@@ -106,15 +106,14 @@ static int ecryptfs_init_lower_file(struct dentry *dentry,
|
||||
struct file **lower_file)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
const struct path *path = ecryptfs_dentry_to_lower_path(dentry);
|
||||
struct path path = ecryptfs_lower_path(dentry);
|
||||
int rc;
|
||||
|
||||
rc = ecryptfs_privileged_open(lower_file, path->dentry, path->mnt,
|
||||
cred);
|
||||
rc = ecryptfs_privileged_open(lower_file, path.dentry, path.mnt, cred);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Error opening lower file "
|
||||
"for lower_dentry [0x%p] and lower_mnt [0x%p]; "
|
||||
"rc = [%d]\n", path->dentry, path->mnt, rc);
|
||||
"rc = [%d]\n", path.dentry, path.mnt, rc);
|
||||
(*lower_file) = NULL;
|
||||
}
|
||||
return rc;
|
||||
@@ -437,7 +436,6 @@ static int ecryptfs_get_tree(struct fs_context *fc)
|
||||
struct ecryptfs_fs_context *ctx = fc->fs_private;
|
||||
struct ecryptfs_sb_info *sbi = fc->s_fs_info;
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
|
||||
struct ecryptfs_dentry_info *root_info;
|
||||
const char *err = "Getting sb failed";
|
||||
struct inode *inode;
|
||||
struct path path;
|
||||
@@ -543,14 +541,8 @@ static int ecryptfs_get_tree(struct fs_context *fc)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
rc = -ENOMEM;
|
||||
root_info = kmem_cache_zalloc(ecryptfs_dentry_info_cache, GFP_KERNEL);
|
||||
if (!root_info)
|
||||
goto out_free;
|
||||
|
||||
/* ->kill_sb() will take care of root_info */
|
||||
ecryptfs_set_dentry_private(s->s_root, root_info);
|
||||
root_info->lower_path = path;
|
||||
ecryptfs_set_dentry_lower(s->s_root, path.dentry);
|
||||
ecryptfs_superblock_to_private(s)->lower_mnt = path.mnt;
|
||||
|
||||
s->s_flags |= SB_ACTIVE;
|
||||
fc->root = dget(s->s_root);
|
||||
@@ -580,6 +572,7 @@ static void ecryptfs_kill_block_super(struct super_block *sb)
|
||||
kill_anon_super(sb);
|
||||
if (!sb_info)
|
||||
return;
|
||||
mntput(sb_info->lower_mnt);
|
||||
ecryptfs_destroy_mount_crypt_stat(&sb_info->mount_crypt_stat);
|
||||
kmem_cache_free(ecryptfs_sb_info_cache, sb_info);
|
||||
}
|
||||
@@ -667,11 +660,6 @@ static struct ecryptfs_cache_info {
|
||||
.name = "ecryptfs_file_cache",
|
||||
.size = sizeof(struct ecryptfs_file_info),
|
||||
},
|
||||
{
|
||||
.cache = &ecryptfs_dentry_info_cache,
|
||||
.name = "ecryptfs_dentry_info_cache",
|
||||
.size = sizeof(struct ecryptfs_dentry_info),
|
||||
},
|
||||
{
|
||||
.cache = &ecryptfs_inode_info_cache,
|
||||
.name = "ecryptfs_inode_cache",
|
||||
|
||||
Reference in New Issue
Block a user