public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "J. Bruce Fields" <bfields@fieldses.org>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: rwheeler@redhat.com, avati@redhat.com, viro@ZenIV.linux.org.uk,
	bfoster@redhat.com, dhowells@redhat.com, eparis@redhat.com,
	raven@themaw.net, linux-fsdevel@vger.kernel.org,
	linux-kernel@vger.kernel.org, mszeredi@suse.cz
Subject: Re: [PATCH 08/10] fuse: use d_materialise_unique()
Date: Thu, 5 Sep 2013 17:29:54 -0400	[thread overview]
Message-ID: <20130905212954.GC24805@fieldses.org> (raw)
In-Reply-To: <1378303556-7220-9-git-send-email-miklos@szeredi.hu>

On Wed, Sep 04, 2013 at 04:05:54PM +0200, Miklos Szeredi wrote:
> From: Miklos Szeredi <mszeredi@suse.cz>
> 
> Use d_materialise_unique() instead of d_splice_alias().  This allows dentry
> subtrees to be moved to a new place if there moved, even if something is
> referencing a dentry in the subtree (open fd, cwd, etc..).
> 
> This will also allow us to drop a subtree if it is found to be replaced by
> something else.  In this case the disconnected subtree can later be
> reconnected to its new location.
> 
> d_materialise_unique() ensures that a directory entry only ever has one
> alias.  We keep fc->inst_mutex around the calls for d_materialise_unique()
> on directories to prevent a race with mkdir "stealing" the inode.

One worry I have with d_materialise_unique is the

	anon->d_flags &= ~DCACHE_DISCONNECTED

at the end of __d_materialise_dentry.  The export code depends on
DCACHE_DISCONNECTED not being cleared until it's verified that the
dentry is connected all the way back up to the root of the filesystem,
and it looks like this can clear DCACHE_DISCONNECTED sooner than that.
This hasn't been an issue since all the exportable filesystems use
d_splice_alias().

I think maybe this is just a bug and we could safely delete that line.

--b.

> 
> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
> ---
>  fs/fuse/dir.c | 69 ++++++++++++++++++++++-------------------------------------
>  1 file changed, 26 insertions(+), 43 deletions(-)
> 
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index 72a5d5b..131d14b 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -267,26 +267,6 @@ int fuse_valid_type(int m)
>  		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
>  }
>  
> -/*
> - * Add a directory inode to a dentry, ensuring that no other dentry
> - * refers to this inode.  Called with fc->inst_mutex.
> - */
> -static struct dentry *fuse_d_add_directory(struct dentry *entry,
> -					   struct inode *inode)
> -{
> -	struct dentry *alias = d_find_alias(inode);
> -	if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
> -		/* This tries to shrink the subtree below alias */
> -		fuse_invalidate_entry(alias);
> -		dput(alias);
> -		if (!hlist_empty(&inode->i_dentry))
> -			return ERR_PTR(-EBUSY);
> -	} else {
> -		dput(alias);
> -	}
> -	return d_splice_alias(inode, entry);
> -}
> -
>  int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
>  		     struct fuse_entry_out *outarg, struct inode **inode)
>  {
> @@ -345,6 +325,24 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
>  	return err;
>  }
>  
> +static struct dentry *fuse_materialise_dentry(struct dentry *dentry,
> +					      struct inode *inode)
> +{
> +	struct dentry *newent;
> +
> +	if (inode && S_ISDIR(inode->i_mode)) {
> +		struct fuse_conn *fc = get_fuse_conn(inode);
> +
> +		mutex_lock(&fc->inst_mutex);
> +		newent = d_materialise_unique(dentry, inode);
> +		mutex_unlock(&fc->inst_mutex);
> +	} else {
> +		newent = d_materialise_unique(dentry, inode);
> +	}
> +
> +	return newent;
> +}
> +
>  static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
>  				  unsigned int flags)
>  {
> @@ -352,7 +350,6 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
>  	struct fuse_entry_out outarg;
>  	struct inode *inode;
>  	struct dentry *newent;
> -	struct fuse_conn *fc = get_fuse_conn(dir);
>  	bool outarg_valid = true;
>  
>  	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
> @@ -368,16 +365,10 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
>  	if (inode && get_node_id(inode) == FUSE_ROOT_ID)
>  		goto out_iput;
>  
> -	if (inode && S_ISDIR(inode->i_mode)) {
> -		mutex_lock(&fc->inst_mutex);
> -		newent = fuse_d_add_directory(entry, inode);
> -		mutex_unlock(&fc->inst_mutex);
> -		err = PTR_ERR(newent);
> -		if (IS_ERR(newent))
> -			goto out_iput;
> -	} else {
> -		newent = d_splice_alias(inode, entry);
> -	}
> +	newent = fuse_materialise_dentry(entry, inode);
> +	err = PTR_ERR(newent);
> +	if (IS_ERR(newent))
> +		goto out_err;
>  
>  	entry = newent ? newent : entry;
>  	if (outarg_valid)
> @@ -1275,18 +1266,10 @@ static int fuse_direntplus_link(struct file *file,
>  	if (!inode)
>  		goto out;
>  
> -	if (S_ISDIR(inode->i_mode)) {
> -		mutex_lock(&fc->inst_mutex);
> -		alias = fuse_d_add_directory(dentry, inode);
> -		mutex_unlock(&fc->inst_mutex);
> -		err = PTR_ERR(alias);
> -		if (IS_ERR(alias)) {
> -			iput(inode);
> -			goto out;
> -		}
> -	} else {
> -		alias = d_splice_alias(inode, dentry);
> -	}
> +	alias = fuse_materialise_dentry(dentry, inode);
> +	err = PTR_ERR(alias);
> +	if (IS_ERR(alias))
> +		goto out;
>  
>  	if (alias) {
>  		dput(dentry);
> -- 
> 1.8.1.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

  reply	other threads:[~2013-09-05 21:30 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-04 14:05 [PATCH 00/10] [v3] safely drop directory dentry on failed revalidate Miklos Szeredi
2013-09-04 14:05 ` [PATCH 01/10] vfs: add d_walk() Miklos Szeredi
2013-09-04 18:12   ` Al Viro
2013-09-04 14:05 ` [PATCH 02/10] vfs: check submounts and drop atomically Miklos Szeredi
2013-09-04 17:58   ` Al Viro
2013-09-05  9:11     ` Miklos Szeredi
2013-09-04 14:05 ` [PATCH 03/10] vfs: check unlinked ancestors before mount Miklos Szeredi
2013-09-04 14:05 ` [PATCH 04/10] afs: use check_submounts_and_drop() Miklos Szeredi
2013-09-04 14:05 ` [PATCH 05/10] gfs2: " Miklos Szeredi
2013-09-04 14:05 ` [PATCH 06/10] nfs: " Miklos Szeredi
2013-09-04 14:05 ` [PATCH 07/10] sysfs: " Miklos Szeredi
2013-09-04 15:17   ` Greg Kroah-Hartman
2013-09-04 14:05 ` [PATCH 08/10] fuse: use d_materialise_unique() Miklos Szeredi
2013-09-05 21:29   ` J. Bruce Fields [this message]
2013-09-04 14:05 ` [PATCH 09/10] fuse: clean up return in fuse_dentry_revalidate() Miklos Szeredi
2013-09-04 14:05 ` [PATCH 10/10] fuse: drop dentry on failed revalidate Miklos Szeredi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130905212954.GC24805@fieldses.org \
    --to=bfields@fieldses.org \
    --cc=avati@redhat.com \
    --cc=bfoster@redhat.com \
    --cc=dhowells@redhat.com \
    --cc=eparis@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=mszeredi@suse.cz \
    --cc=raven@themaw.net \
    --cc=rwheeler@redhat.com \
    --cc=viro@ZenIV.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox