From 22762711479959754e005f5bb8e6abc37bf9e0ba Mon Sep 17 00:00:00 2001 From: Zev Weiss <zev@bewilderbeest.net> Date: Sat, 14 Apr 2018 01:16:58 -0500 Subject: fs: avoid fdput() after failed fdget() in vfs_dedupe_file_range() It's a fairly inconsequential bug, since fdput() won't actually try to fput() the file due to fd.flags (and thus FDPUT_FPUT) being zero in the failure case, but most other vfs code takes steps to avoid this. Signed-off-by: Zev Weiss <zev@bewilderbeest.net> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/read_write.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/read_write.c b/fs/read_write.c index c4eabbfc90df..e83bd9744b5d 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -2023,7 +2023,7 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same) ret = mnt_want_write_file(dst_file); if (ret) { info->status = ret; - goto next_loop; + goto next_fdput; } dst_off = info->dest_offset; @@ -2058,9 +2058,9 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same) next_file: mnt_drop_write_file(dst_file); -next_loop: +next_fdput: fdput(dst_fd); - +next_loop: if (fatal_signal_pending(current)) goto out; } -- cgit v1.2.3 From 3087147ba3376c5d7ea255bf5cf24c974a41f477 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Wed, 18 Apr 2018 00:14:40 -0400 Subject: msdos_rmdir(): kill BS comment it hadn't been checking for "busy" since 2.3.99-something and removing that leaves us with "check if it's empty" followed by call of fat_dir_emtpy() Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/fat/namei_msdos.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'fs') diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index 582ca731a6c9..484ce674e0cd 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c @@ -314,10 +314,6 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) int err; mutex_lock(&MSDOS_SB(sb)->s_lock); - /* - * Check whether the directory is not in use, then check - * whether it is empty. - */ err = fat_dir_empty(inode); if (err) goto out; -- cgit v1.2.3 From 1c18d2a15ea4752c7a0d1aa6ef5659a744255140 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Thu, 10 May 2018 15:09:41 -0400 Subject: it's SB_BORN, not MS_BORN... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/super.c b/fs/super.c index 5fa9a8d8d865..c9e34cd2b759 100644 --- a/fs/super.c +++ b/fs/super.c @@ -938,7 +938,7 @@ void emergency_remount(void) static void do_thaw_all_callback(struct super_block *sb) { down_write(&sb->s_umount); - if (sb->s_root && sb->s_flags & MS_BORN) { + if (sb->s_root && sb->s_flags & SB_BORN) { emergency_thaw_bdev(sb); thaw_super_locked(sb); } else { -- cgit v1.2.3 From 61fec493c9df7958f8417e1e2f6530a614ee619a Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Wed, 25 Apr 2018 10:52:25 -0400 Subject: get rid of dead code in d_find_alias() All "try disconnected alias if nothing else fits" logics in d_find_alias() got accidentally disabled by Neil a while ago; for most of the callers it was the right thing to do, so fixes belong in few callers that *do* want disconnected aliases. This just takes the now-dead code in d_find_alias() out. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/dcache.c | 83 +++++++++++++++++++++++++------------------------------------ 1 file changed, 34 insertions(+), 49 deletions(-) (limited to 'fs') diff --git a/fs/dcache.c b/fs/dcache.c index 86d2de63461e..e9476e94372a 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -907,6 +907,35 @@ repeat: } EXPORT_SYMBOL(dget_parent); +static struct dentry * __d_find_any_alias(struct inode *inode) +{ + struct dentry *alias; + + if (hlist_empty(&inode->i_dentry)) + return NULL; + alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); + __dget(alias); + return alias; +} + +/** + * d_find_any_alias - find any alias for a given inode + * @inode: inode to find an alias for + * + * If any aliases exist for the given inode, take and return a + * reference for one of them. If no aliases exist, return %NULL. + */ +struct dentry *d_find_any_alias(struct inode *inode) +{ + struct dentry *de; + + spin_lock(&inode->i_lock); + de = __d_find_any_alias(inode); + spin_unlock(&inode->i_lock); + return de; +} +EXPORT_SYMBOL(d_find_any_alias); + /** * d_find_alias - grab a hashed alias of inode * @inode: inode in question @@ -923,34 +952,19 @@ EXPORT_SYMBOL(dget_parent); */ static struct dentry *__d_find_alias(struct inode *inode) { - struct dentry *alias, *discon_alias; + struct dentry *alias; + + if (S_ISDIR(inode->i_mode)) + return __d_find_any_alias(inode); -again: - discon_alias = NULL; hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { spin_lock(&alias->d_lock); - if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) { - if (IS_ROOT(alias) && - (alias->d_flags & DCACHE_DISCONNECTED)) { - discon_alias = alias; - } else { - __dget_dlock(alias); - spin_unlock(&alias->d_lock); - return alias; - } - } - spin_unlock(&alias->d_lock); - } - if (discon_alias) { - alias = discon_alias; - spin_lock(&alias->d_lock); - if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) { + if (!d_unhashed(alias)) { __dget_dlock(alias); spin_unlock(&alias->d_lock); return alias; } spin_unlock(&alias->d_lock); - goto again; } return NULL; } @@ -1941,35 +1955,6 @@ struct dentry *d_make_root(struct inode *root_inode) } EXPORT_SYMBOL(d_make_root); -static struct dentry * __d_find_any_alias(struct inode *inode) -{ - struct dentry *alias; - - if (hlist_empty(&inode->i_dentry)) - return NULL; - alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); - __dget(alias); - return alias; -} - -/** - * d_find_any_alias - find any alias for a given inode - * @inode: inode to find an alias for - * - * If any aliases exist for the given inode, take and return a - * reference for one of them. If no aliases exist, return %NULL. - */ -struct dentry *d_find_any_alias(struct inode *inode) -{ - struct dentry *de; - - spin_lock(&inode->i_lock); - de = __d_find_any_alias(inode); - spin_unlock(&inode->i_lock); - return de; -} -EXPORT_SYMBOL(d_find_any_alias); - static struct dentry *__d_instantiate_anon(struct dentry *dentry, struct inode *inode, bool disconnected) -- cgit v1.2.3 From f6ddc16175f637915e27ded7588b59d187131ad0 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Wed, 25 Apr 2018 10:32:51 -0400 Subject: vfat: simplify checks in vfat_lookup() vfat_d_anon_disconn() is called only if alias->d_parent is equal to dentry->d_parent *and* it returns false unless alias->d_parent == alias. But in that case alias is the directory we are doing lookup in, and d_splice_alias() would've done the right thing. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/fat/namei_vfat.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'fs') diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 2649759c478a..4f4362d5a04c 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -697,15 +697,6 @@ static int vfat_find(struct inode *dir, const struct qstr *qname, return fat_search_long(dir, qname->name, len, sinfo); } -/* - * (nfsd's) anonymous disconnected dentry? - * NOTE: !IS_ROOT() is not anonymous (I.e. d_splice_alias() did the job). - */ -static int vfat_d_anon_disconn(struct dentry *dentry) -{ - return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); -} - static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { @@ -738,8 +729,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, * Checking "alias->d_parent == dentry->d_parent" to make sure * FS is not corrupted (especially double linked dir). */ - if (alias && alias->d_parent == dentry->d_parent && - !vfat_d_anon_disconn(alias)) { + if (alias && alias->d_parent == dentry->d_parent) { /* * This inode has non anonymous-DCACHE_DISCONNECTED * dentry. This means, the user did ->lookup() by an @@ -747,7 +737,6 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, * * Switch to new one for reason of locality if possible. */ - BUG_ON(d_unhashed(alias)); if (!S_ISDIR(inode->i_mode)) d_move(alias, dentry); iput(inode); -- cgit v1.2.3 From 2220c5b0a7fb7d7d00c9a0b1e5222a7ae1f35956 Mon Sep 17 00:00:00 2001 From: Al Viro <viro@zeniv.linux.org.uk> Date: Tue, 24 Apr 2018 21:22:04 -0400 Subject: make xattr_getsecurity() static many years overdue... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/xattr.c | 3 +-- include/linux/xattr.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/xattr.c b/fs/xattr.c index 61cd28ba25f3..28e1dfc27b95 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -229,7 +229,7 @@ out: } EXPORT_SYMBOL_GPL(vfs_setxattr); -ssize_t +static ssize_t xattr_getsecurity(struct inode *inode, const char *name, void *value, size_t size) { @@ -254,7 +254,6 @@ out: out_noalloc: return len; } -EXPORT_SYMBOL_GPL(xattr_getsecurity); /* * vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr diff --git a/include/linux/xattr.h b/include/linux/xattr.h index d70f77a4b62a..6dad031be3c2 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -46,7 +46,6 @@ struct xattr { size_t value_len; }; -ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t); ssize_t __vfs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t); ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t); ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); -- cgit v1.2.3 From 030c7e0bb723e3de6354d1a85df0543197efec1a Mon Sep 17 00:00:00 2001 From: Danilo Krummrich <danilokrummrich@dk-develop.de> Date: Mon, 23 Apr 2018 10:30:59 +0200 Subject: vfs: namei: use path_equal() in follow_dotdot() Use path_equal() to detect whether we're already in root. Signed-off-by: Danilo Krummrich <danilokrummrich@dk-develop.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/namei.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/namei.c b/fs/namei.c index 186bd2464fd5..6f0dc40f88c5 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1438,10 +1438,8 @@ static int path_parent_directory(struct path *path) static int follow_dotdot(struct nameidata *nd) { while(1) { - if (nd->path.dentry == nd->root.dentry && - nd->path.mnt == nd->root.mnt) { + if (path_equal(&nd->path, &nd->root)) break; - } if (nd->path.dentry != nd->path.mnt->mnt_root) { int ret = path_parent_directory(&nd->path); if (ret) -- cgit v1.2.3 From eb915375757cd32c5abf7aea4caa76fe7edf8ef4 Mon Sep 17 00:00:00 2001 From: Chengguang Xu <cgxu519@gmx.com> Date: Wed, 16 May 2018 13:34:52 +0800 Subject: vfs: delete unnecessary assignment in vfs_listxattr It seems the first error assignment in if branch is redundant. Signed-off-by: Chengguang Xu <cgxu519@gmx.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/xattr.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/xattr.c b/fs/xattr.c index 28e1dfc27b95..f9cb1db187b7 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -353,7 +353,6 @@ vfs_listxattr(struct dentry *dentry, char *list, size_t size) if (error) return error; if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) { - error = -EOPNOTSUPP; error = inode->i_op->listxattr(dentry, list, size); } else { error = security_inode_listsecurity(inode, list, size); -- cgit v1.2.3