diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-29 00:27:19 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-08-02 05:18:53 +0200 |
commit | c971e6a006175bd0f195c6346c4e8bc4089bec00 (patch) | |
tree | 7b5a8c5ec29f2e08fe09b8e7332f2288e247f495 /fs/fuse | |
parent | nfs_instantiate(): prevent multiple aliases for directory inode (diff) | |
download | linux-c971e6a006175bd0f195c6346c4e8bc4089bec00.tar.xz linux-c971e6a006175bd0f195c6346c4e8bc4089bec00.zip |
kill d_instantiate_no_diralias()
The only user is fuse_create_new_entry(), and there it's used to
mitigate the same mkdir/open-by-handle race as in nfs_mkdir().
The same solution applies - unhash the mkdir argument, then
call d_splice_alias() and if that returns a reference to preexisting
alias, dput() and report success. ->mkdir() argument left unhashed
negative with the preexisting alias moved in the right place is just
fine from the ->mkdir() callers point of view.
Cc: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/dir.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 56231b31f806..4bbae6ac75c3 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -539,6 +539,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, { struct fuse_entry_out outarg; struct inode *inode; + struct dentry *d; int err; struct fuse_forget_link *forget; @@ -570,11 +571,17 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, } kfree(forget); - err = d_instantiate_no_diralias(entry, inode); - if (err) - return err; + d_drop(entry); + d = d_splice_alias(inode, entry); + if (IS_ERR(d)) + return PTR_ERR(d); - fuse_change_entry_timeout(entry, &outarg); + if (d) { + fuse_change_entry_timeout(d, &outarg); + dput(d); + } else { + fuse_change_entry_timeout(entry, &outarg); + } fuse_invalidate_attr(dir); return 0; |