diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-05-28 18:27:19 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-08-01 23:18:53 -0400 |
commit | c971e6a006175bd0f195c6346c4e8bc4089bec00 (patch) | |
tree | 7b5a8c5ec29f2e08fe09b8e7332f2288e247f495 /fs/fuse/dir.c | |
parent | b0c6108ecf64fce3987f80c1610472a56d480d9a (diff) |
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/dir.c')
-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, | |||
539 | { | 539 | { |
540 | struct fuse_entry_out outarg; | 540 | struct fuse_entry_out outarg; |
541 | struct inode *inode; | 541 | struct inode *inode; |
542 | struct dentry *d; | ||
542 | int err; | 543 | int err; |
543 | struct fuse_forget_link *forget; | 544 | struct fuse_forget_link *forget; |
544 | 545 | ||
@@ -570,11 +571,17 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, | |||
570 | } | 571 | } |
571 | kfree(forget); | 572 | kfree(forget); |
572 | 573 | ||
573 | err = d_instantiate_no_diralias(entry, inode); | 574 | d_drop(entry); |
574 | if (err) | 575 | d = d_splice_alias(inode, entry); |
575 | return err; | 576 | if (IS_ERR(d)) |
577 | return PTR_ERR(d); | ||
576 | 578 | ||
577 | fuse_change_entry_timeout(entry, &outarg); | 579 | if (d) { |
580 | fuse_change_entry_timeout(d, &outarg); | ||
581 | dput(d); | ||
582 | } else { | ||
583 | fuse_change_entry_timeout(entry, &outarg); | ||
584 | } | ||
578 | fuse_invalidate_attr(dir); | 585 | fuse_invalidate_attr(dir); |
579 | return 0; | 586 | return 0; |
580 | 587 | ||