From 8314d37f97d3a29f51557aee4f12dbfdf3630200 Mon Sep 17 00:00:00 2001 From: tl Date: Tue, 20 Aug 2024 15:24:45 +0800 Subject: [PATCH] sharefs revert Signed-off-by: tl --- fs/sharefs/authentication.c | 4 +- fs/sharefs/authentication.h | 5 +- fs/sharefs/dentry.c | 106 +----------------------------------- fs/sharefs/file.c | 16 +----- fs/sharefs/inode.c | 99 ++++++++------------------------- fs/sharefs/lookup.c | 34 +++++------- fs/sharefs/sharefs.h | 21 +++---- fs/sharefs/super.c | 8 ++- 8 files changed, 61 insertions(+), 232 deletions(-) diff --git a/fs/sharefs/authentication.c b/fs/sharefs/authentication.c index 8986fcbcc894..bc6e825092fa 100644 --- a/fs/sharefs/authentication.c +++ b/fs/sharefs/authentication.c @@ -75,7 +75,8 @@ void sharefs_root_inode_perm_init(struct inode *root_inode) hii->perm = SHAREFS_PERM_FIX; } -const struct cred *sharefs_override_file_fsids(struct inode *dir) +#ifdef CONFIG_SHAREFS_SUPPORT_OVERRIDE +const struct cred *sharefs_override_file_fsids(struct inode *dir, __u16 *_perm) { struct cred *cred = NULL; cred = prepare_creds(); @@ -94,3 +95,4 @@ void sharefs_revert_fsids(const struct cred *old_cred) revert_creds(old_cred); put_cred(cur_cred); } +#endif diff --git a/fs/sharefs/authentication.h b/fs/sharefs/authentication.h index 0a096d1ee710..e598fa883c0a 100644 --- a/fs/sharefs/authentication.h +++ b/fs/sharefs/authentication.h @@ -40,8 +40,11 @@ extern void sharefs_exit_configfs(void); void sharefs_root_inode_perm_init(struct inode *root_inode); void fixup_perm_from_level(struct inode *dir, struct dentry *dentry); -const struct cred *sharefs_override_file_fsids(struct inode *dir); +#ifdef CONFIG_SHAREFS_SUPPORT_OVERRIDE +const struct cred *sharefs_override_file_fsids(struct inode *dir, + __u16 *_perm); void sharefs_revert_fsids(const struct cred *old_cred); +#endif static inline bool is_read_only_auth(__u16 perm) { diff --git a/fs/sharefs/dentry.c b/fs/sharefs/dentry.c index c1a4c30f30fe..dee29cace6b7 100644 --- a/fs/sharefs/dentry.c +++ b/fs/sharefs/dentry.c @@ -10,7 +10,6 @@ */ #include "sharefs.h" -#include "authentication.h" /* * returns: 0: tell VFS to invalidate dentry in share directory @@ -30,7 +29,7 @@ static void sharefs_d_release(struct dentry *dentry) */ if (SHAREFS_D(dentry)) { /* release and reset the lower paths */ - sharefs_reset_lower_path(dentry); + sharefs_put_reset_lower_path(dentry); free_dentry_private_data(dentry); } return; @@ -40,106 +39,3 @@ const struct dentry_operations sharefs_dops = { .d_revalidate = sharefs_d_revalidate, .d_release = sharefs_d_release, }; - -static int try_to_create_lower_path(struct dentry *d, struct path *lower_path) -{ - int err; - struct path lower_dir_path; - struct qstr this; - struct dentry *parent; - struct dentry *lower_dentry; - struct inode *lower_dir_inode; - - parent = dget_parent(d); - err = sharefs_get_lower_path(parent, &lower_dir_path, 0); - dput(parent); - if (err) - return err; - /* instantiate a new negative dentry */ - this.name = d->d_name.name; - this.len = strlen(d->d_name.name); - this.hash = full_name_hash(lower_dir_path.dentry, this.name, this.len); - lower_dentry = d_alloc(lower_dir_path.dentry, &this); - if (!lower_dentry) { - err = -ENOMEM; - goto out; - } - lower_dir_inode = d_inode(lower_dir_path.dentry); - if (lower_dir_inode->i_op && lower_dir_inode->i_op->lookup) - lower_dir_inode->i_op->lookup(lower_dir_inode, lower_dentry, 0); - - spin_lock(&SHAREFS_D(d)->lock); - lower_path->dentry = lower_dentry; - lower_path->mnt = lower_dir_path.mnt; - spin_unlock(&SHAREFS_D(d)->lock); - -out: - sharefs_put_lower_path(parent, &lower_dir_path); - return err; -} - -/* Returns struct path. Caller must path_put it. */ -int sharefs_get_lower_path(struct dentry *d, struct path *lower_path, - bool try_to_create) -{ - int err = -ENOMEM; - char *path_buf; - char *path_name = NULL; - struct path lower_root_path; - const struct cred *saved_cred = NULL; - - if (unlikely(!d)) - goto out; - - path_buf = kmalloc(PATH_MAX, GFP_KERNEL); - if (unlikely(!path_buf)) - goto out; - path_name = dentry_path_raw(d, path_buf, PATH_MAX); - if (IS_ERR(path_name)) { - err = PTR_ERR(path_name); - goto out_free; - } - - sharefs_get_lower_root_path(d, &lower_root_path); - saved_cred = sharefs_override_file_fsids(d_inode(lower_root_path.dentry)); - if (!saved_cred) { - sharefs_put_lower_path(d, &lower_root_path); - goto out_free; - } - spin_lock(&SHAREFS_D(d)->lock); - err = vfs_path_lookup(lower_root_path.dentry, lower_root_path.mnt, - path_name, LOOKUP_CREATE, lower_path); - spin_unlock(&SHAREFS_D(d)->lock); - sharefs_revert_fsids(saved_cred); - sharefs_put_lower_path(d, &lower_root_path); - - if (err != -ENOENT || !try_to_create) - goto out_free; - err = try_to_create_lower_path(d, lower_path); - -out_free: - kfree(path_buf); -out: - return err; -} - -int sharefs_get_lower_inode(struct dentry *d, struct inode **lower_inode) -{ - int err = 0; - struct path lower_path; - - err = sharefs_get_lower_path(d, &lower_path, 0); - if (err) - goto out; - - *lower_inode = d_inode(lower_path.dentry); - if ((*lower_inode)->i_flags & S_DEAD) { - err = -ENOENT; - } else if (!igrab(*lower_inode)) { - err = -ESTALE; - } - - sharefs_put_lower_path(d, &lower_path); -out: - return err; -} \ No newline at end of file diff --git a/fs/sharefs/file.c b/fs/sharefs/file.c index 1aa44baf67e5..f04963d57a4a 100644 --- a/fs/sharefs/file.c +++ b/fs/sharefs/file.c @@ -31,7 +31,6 @@ static int sharefs_open(struct inode *inode, struct file *file) int err = 0; struct file *lower_file = NULL; struct path lower_path; - struct inode *lower_inode = NULL; /* don't open unhashed/deleted files */ if (d_unhashed(file->f_path.dentry)) { @@ -47,9 +46,7 @@ static int sharefs_open(struct inode *inode, struct file *file) } /* open lower object and link sharefs's file struct to lower's */ - err = sharefs_get_lower_path(file->f_path.dentry, &lower_path, 0); - if (err) - goto out_free; + sharefs_get_lower_path(file->f_path.dentry, &lower_path); lower_file = dentry_open(&lower_path, file->f_flags, current_cred()); path_put(&lower_path); if (IS_ERR(lower_file)) { @@ -63,21 +60,16 @@ static int sharefs_open(struct inode *inode, struct file *file) sharefs_set_lower_file(file, lower_file); } -out_free: if (err) { kfree(SHAREFS_F(file)); } else { kuid_t uid = inode->i_uid; kgid_t gid = inode->i_gid; mode_t mode = inode->i_mode; - err = sharefs_get_lower_inode(file->f_path.dentry, &lower_inode); - if (err) - goto out_err; - fsstack_copy_attr_all(inode, lower_inode); + fsstack_copy_attr_all(inode, sharefs_lower_inode(inode)); inode->i_uid = uid; inode->i_gid = gid; inode->i_mode = mode; - iput(lower_inode); } out_err: return err; @@ -124,9 +116,7 @@ static int sharefs_fsync(struct file *file, loff_t start, loff_t end, if (err) goto out; lower_file = sharefs_lower_file(file); - err = sharefs_get_lower_path(dentry, &lower_path, 0); - if (err) - goto out; + sharefs_get_lower_path(dentry, &lower_path); err = vfs_fsync_range(lower_file, start, end, datasync); sharefs_put_lower_path(dentry, &lower_path); out: diff --git a/fs/sharefs/inode.c b/fs/sharefs/inode.c index e5cb396263e2..7bd08abe79ea 100644 --- a/fs/sharefs/inode.c +++ b/fs/sharefs/inode.c @@ -20,9 +20,7 @@ static int sharefs_getattr(const struct path *path, struct kstat *stat, struct path lower_path; int ret; - ret = sharefs_get_lower_path(path->dentry, &lower_path, 0); - if (ret) - return ret; + sharefs_get_lower_path(path->dentry, &lower_path); ret = vfs_getattr(&lower_path, stat, request_mask, flags); stat->ino = d_inode(path->dentry)->i_ino; stat->uid = d_inode(path->dentry)->i_uid; @@ -41,14 +39,8 @@ static ssize_t sharefs_listxattr(struct dentry *dentry, char *buffer, size_t buf struct dentry *lower_dentry; struct path lower_path; - err = sharefs_get_lower_path(dentry, &lower_path, 0); - if (err) - return err; + sharefs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; - if (d_inode(lower_dentry)->i_flags & S_DEAD) { - err = -ENOENT; - goto out; - } if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) { err = -EOPNOTSUPP; goto out; @@ -93,23 +85,17 @@ static int sharefs_create(struct inode *dir, struct dentry *dentry, struct dentry *lower_parent_dentry = NULL; struct path lower_path; const struct cred *saved_cred = NULL; - struct inode *lower_inode = NULL; + __u16 child_perm; - saved_cred = sharefs_override_file_fsids(dir); + saved_cred = sharefs_override_file_fsids(dir, &child_perm); if (!saved_cred) { err = -ENOMEM; return err; } - err = sharefs_get_lower_path(dentry, &lower_path, 1); - if (err) - goto out_revert; + sharefs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; lower_parent_dentry = lock_parent(lower_dentry); - if (unlikely(!lower_parent_dentry)) { - err = -ENOENT; - goto out; - } err = vfs_create(d_inode(lower_parent_dentry), lower_dentry, mode, want_excl); if (err) @@ -117,17 +103,12 @@ static int sharefs_create(struct inode *dir, struct dentry *dentry, err = sharefs_interpose(dentry, dir->i_sb, &lower_path); if (err) goto out; - err = sharefs_get_lower_inode(dentry, &lower_inode); - if (err) - goto out; - fsstack_copy_attr_times(dir, lower_inode); + fsstack_copy_attr_times(dir, sharefs_lower_inode(dir)); fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry)); - iput(lower_inode); out: unlock_dir(lower_parent_dentry); sharefs_put_lower_path(dentry, &lower_path); -out_revert: sharefs_revert_fsids(saved_cred); return err; } @@ -139,23 +120,17 @@ static int sharefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) struct dentry *lower_parent_dentry = NULL; struct path lower_path; const struct cred *saved_cred = NULL; - struct inode *lower_inode = NULL; + __u16 child_perm; - saved_cred = sharefs_override_file_fsids(dir); + saved_cred = sharefs_override_file_fsids(dir, &child_perm); if (!saved_cred) { err = -ENOMEM; return err; } - err = sharefs_get_lower_path(dentry, &lower_path, 1); - if (err) - goto out_revert; + sharefs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; lower_parent_dentry = lock_parent(lower_dentry); - if (unlikely(!lower_parent_dentry)) { - err = -ENOENT; - goto out; - } err = vfs_mkdir(d_inode(lower_parent_dentry), lower_dentry, mode); if (err) goto out; @@ -164,19 +139,14 @@ static int sharefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) if (err) goto out; - err = sharefs_get_lower_inode(dentry, &lower_inode); - if (err) - goto out; - fsstack_copy_attr_times(dir, lower_inode); + fsstack_copy_attr_times(dir, sharefs_lower_inode(dir)); fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry)); /* update number of links on parent directory */ - set_nlink(dir, lower_inode->i_nlink); - iput(lower_inode); + set_nlink(dir, sharefs_lower_inode(dir)->i_nlink); out: unlock_dir(lower_parent_dentry); sharefs_put_lower_path(dentry, &lower_path); -out_revert: sharefs_revert_fsids(saved_cred); return err; } @@ -185,20 +155,11 @@ static int sharefs_unlink(struct inode *dir, struct dentry *dentry) { int err; struct dentry *lower_dentry = NULL; - struct inode *lower_dir_inode = NULL; - struct inode *lower_inode = NULL; + struct inode *lower_dir_inode = sharefs_lower_inode(dir); struct dentry *lower_dir_dentry = NULL; struct path lower_path; - err = sharefs_get_lower_inode(dentry->d_parent, &lower_dir_inode); - if (err) - return err; - err = sharefs_get_lower_inode(dentry, &lower_inode); - if (err) - goto put; - err = sharefs_get_lower_path(dentry, &lower_path, 0); - if (err) - goto put_dir; + sharefs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; dget(lower_dentry); lower_dir_dentry = lock_parent(lower_dentry); @@ -207,7 +168,8 @@ static int sharefs_unlink(struct inode *dir, struct dentry *dentry) goto out; fsstack_copy_attr_times(dir, lower_dir_inode); fsstack_copy_inode_size(dir, lower_dir_inode); - set_nlink(dentry->d_inode, lower_inode->i_nlink); + set_nlink(dentry->d_inode, + sharefs_lower_inode(dentry->d_inode)->i_nlink); dentry->d_inode->i_ctime = dir->i_ctime; d_drop(dentry); @@ -215,10 +177,6 @@ static int sharefs_unlink(struct inode *dir, struct dentry *dentry) unlock_dir(lower_dir_dentry); dput(lower_dentry); sharefs_put_lower_path(dentry, &lower_path); -put_dir: - iput(lower_inode); -put: - iput(lower_dir_inode); return err; } @@ -229,9 +187,7 @@ static int sharefs_rmdir(struct inode *dir, struct dentry *dentry) struct dentry *lower_dir_dentry; struct path lower_path; - err = sharefs_get_lower_path(dentry, &lower_path, 0); - if (err) - return err; + sharefs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; lower_dir_dentry = lock_parent(lower_dentry); err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); @@ -266,14 +222,8 @@ static int sharefs_rename(struct inode *old_dir, struct dentry *old_dentry, if (flags) return -EINVAL; - err = sharefs_get_lower_path(old_dentry, &lower_old_path, 0); - if (err) - return err; - err = sharefs_get_lower_path(new_dentry, &lower_new_path, 1); - if (err) { - sharefs_put_lower_path(old_dentry, &lower_old_path); - return err; - } + sharefs_get_lower_path(old_dentry, &lower_old_path); + sharefs_get_lower_path(new_dentry, &lower_new_path); lower_old_dentry = lower_old_path.dentry; lower_new_dentry = lower_new_path.dentry; lower_old_dir_dentry = dget_parent(lower_old_dentry); @@ -332,15 +282,11 @@ static int sharefs_setattr(struct dentry *dentry, struct iattr *ia) err = setattr_prepare(dentry, ia); if (err) - return err; + goto out_err; - err = sharefs_get_lower_path(dentry, &lower_path, 0); - if (err) - return err; + sharefs_get_lower_path(dentry, &lower_path); lower_dentry = lower_path.dentry; - err = sharefs_get_lower_inode(dentry, &lower_inode); - if (err) - goto out_err; + lower_inode = sharefs_lower_inode(inode); /* prepare our own lower struct iattr (with the lower file) */ memcpy(&lower_ia, ia, sizeof(lower_ia)); @@ -393,9 +339,8 @@ static int sharefs_setattr(struct dentry *dentry, struct iattr *ia) */ out: - iput(lower_inode); -out_err: sharefs_put_lower_path(dentry, &lower_path); +out_err: return err; } #endif diff --git a/fs/sharefs/lookup.c b/fs/sharefs/lookup.c index 9d5536c83161..0b0c30ef46f1 100644 --- a/fs/sharefs/lookup.c +++ b/fs/sharefs/lookup.c @@ -141,7 +141,6 @@ struct inode *sharefs_iget(struct super_block *sb, struct inode *lower_inode) fsstack_copy_inode_size(inode, lower_inode); unlock_new_inode(inode); - iput(lower_inode); return inode; } @@ -200,14 +199,14 @@ int sharefs_interpose(struct dentry *dentry, struct super_block *sb, */ static struct dentry *__sharefs_lookup(struct dentry *dentry, unsigned int flags, - struct path *lower_parent_path, - struct path *lower_path) + struct path *lower_parent_path) { int err = 0; struct vfsmount *lower_dir_mnt; struct dentry *lower_dir_dentry = NULL; struct dentry *lower_dentry; const char *name; + struct path lower_path; struct qstr this; struct dentry *ret_dentry = NULL; @@ -215,7 +214,7 @@ static struct dentry *__sharefs_lookup(struct dentry *dentry, d_set_d_op(dentry, &sharefs_dops); if (IS_ROOT(dentry)) - return NULL; + goto out; name = dentry->d_name.name; @@ -225,12 +224,12 @@ static struct dentry *__sharefs_lookup(struct dentry *dentry, /* Use vfs_path_lookup to check if the dentry exists or not */ err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0, - lower_path); + &lower_path); /* no error: handle positive dentries */ if (!err) { - sharefs_set_lower_path(dentry, lower_path); + sharefs_set_lower_path(dentry, &lower_path); ret_dentry = - __sharefs_interpose(dentry, dentry->d_sb, lower_path); + __sharefs_interpose(dentry, dentry->d_sb, &lower_path); if (IS_ERR(ret_dentry)) { err = PTR_ERR(ret_dentry); /* path_put underlying path on error */ @@ -268,9 +267,9 @@ static struct dentry *__sharefs_lookup(struct dentry *dentry, lower_dentry, flags); setup_lower: - lower_path->dentry = lower_dentry; - lower_path->mnt = mntget(lower_dir_mnt); - sharefs_set_lower_path(dentry, lower_path); + lower_path.dentry = lower_dentry; + lower_path.mnt = mntget(lower_dir_mnt); + sharefs_set_lower_path(dentry, &lower_path); /* * If the intent is to create a file, then don't return an error, so @@ -291,31 +290,29 @@ struct dentry *sharefs_lookup(struct inode *dir, struct dentry *dentry, { int err; struct dentry *ret, *parent; - struct path lower_path; struct path lower_parent_path; #ifdef CONFIG_SHAREFS_SUPPORT_OVERRIDE const struct cred *saved_cred = NULL; + __u16 permission; #endif + parent = dget_parent(dentry); - err = sharefs_get_lower_path(parent, &lower_parent_path, 0); - if (err) { - dput(parent); - return ERR_PTR(err); - } + sharefs_get_lower_path(parent, &lower_parent_path); #ifdef CONFIG_SHAREFS_SUPPORT_OVERRIDE - saved_cred = sharefs_override_file_fsids(dir); + saved_cred = sharefs_override_file_fsids(dir, &permission); if (!saved_cred) { ret = ERR_PTR(-ENOMEM); goto out_err; } #endif + /* allocate dentry private data. We free it in ->d_release */ err = new_dentry_private_data(dentry); if (err) { ret = ERR_PTR(err); goto out; } - ret = __sharefs_lookup(dentry, flags, &lower_parent_path, &lower_path); + ret = __sharefs_lookup(dentry, flags, &lower_parent_path); if (IS_ERR(ret)) { sharefs_err("sharefs_lookup error!"); goto out; @@ -330,7 +327,6 @@ struct dentry *sharefs_lookup(struct inode *dir, struct dentry *dentry, fsstack_copy_attr_atime(d_inode(parent), sharefs_lower_inode(d_inode(parent))); fixup_perm_from_level(d_inode(parent), dentry); - sharefs_put_lower_path(dentry, &lower_path); out: #ifdef CONFIG_SHAREFS_SUPPORT_OVERRIDE sharefs_revert_fsids(saved_cred); diff --git a/fs/sharefs/sharefs.h b/fs/sharefs/sharefs.h index 7b5540b09d33..143f047b235f 100644 --- a/fs/sharefs/sharefs.h +++ b/fs/sharefs/sharefs.h @@ -91,9 +91,6 @@ extern int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, struct path *path); extern int sharefs_parse_options(struct sharefs_sb_info *sbi, const char *data); -extern int sharefs_get_lower_inode(struct dentry *d, struct inode **lower_path); -extern int sharefs_get_lower_path(struct dentry *d, struct path *lower_path, - bool try_to_create); /* * inode to private data @@ -157,18 +154,16 @@ static inline void pathcpy(struct path *dst, const struct path *src) dst->dentry = src->dentry; dst->mnt = src->mnt; } - -static inline void sharefs_get_lower_root_path(const struct dentry *dent, - struct path *lower_root_path) +/* Returns struct path. Caller must path_put it. */ +static inline void sharefs_get_lower_path(const struct dentry *dent, + struct path *lower_path) { - struct super_block *sb = dent->d_sb; - - spin_lock(&SHAREFS_D(sb->s_root)->lock); - pathcpy(lower_root_path, &SHAREFS_D(sb->s_root)->lower_path); - path_get(lower_root_path); - spin_unlock(&SHAREFS_D(sb->s_root)->lock); + spin_lock(&SHAREFS_D(dent)->lock); + pathcpy(lower_path, &SHAREFS_D(dent)->lower_path); + path_get(lower_path); + spin_unlock(&SHAREFS_D(dent)->lock); + return; } - static inline void sharefs_put_lower_path(const struct dentry *dent, struct path *lower_path) { diff --git a/fs/sharefs/super.c b/fs/sharefs/super.c index b7cd611adcfd..bbe65944647f 100644 --- a/fs/sharefs/super.c +++ b/fs/sharefs/super.c @@ -99,9 +99,7 @@ static int sharefs_statfs(struct dentry *dentry, struct kstatfs *buf) int err; struct path lower_path; - err = sharefs_get_lower_path(dentry, &lower_path, 0); - if (err) - return err; + sharefs_get_lower_path(dentry, &lower_path); err = vfs_statfs(&lower_path, buf); sharefs_put_lower_path(dentry, &lower_path); @@ -119,13 +117,17 @@ static int sharefs_statfs(struct dentry *dentry, struct kstatfs *buf) */ static void sharefs_evict_inode(struct inode *inode) { + struct inode *lower_inode; + truncate_inode_pages(&inode->i_data, 0); clear_inode(inode); /* * Decrement a reference to a lower_inode, which was incremented * by our read_inode when it was created initially. */ + lower_inode = sharefs_lower_inode(inode); sharefs_set_lower_inode(inode, NULL); + iput(lower_inode); } void __sharefs_log(const char *level, const bool ratelimited, -- Gitee