All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brian Foster <bfoster@redhat.com>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: Niels de Vos <ndevos@redhat.com>,
	fuse-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org
Subject: Re: [fuse-devel] [PATCH] fuse: fix occasional dentry leak when readdirplus is used
Date: Tue, 16 Jul 2013 13:43:13 -0400	[thread overview]
Message-ID: <51E58631.7060003@redhat.com> (raw)
In-Reply-To: <20130716161458.GA19664@tucsk.piliscsaba.szeredi.hu>

On 07/16/2013 12:14 PM, Miklos Szeredi wrote:
> On Tue, Jul 16, 2013 at 09:15:16AM -0400, Brian Foster wrote:
>  
>> I'm not sure why it would need to have a valid inode. A dentry with a
>> NULL inode is valid, no?
> 
> It is valid, yes.  It's called a "negative" dentry, which caches the information
> that the file does not exist.
> 
>> I think the question is whether the above state (multiple, hashed dentries)
>> can be valid for whatever reason. It certainly looks suspicious.
> 
> That state is not valid.  So we certainly need to unhash the negative dentry
> first, before hashing a new one.  We could also reuse the old dentry, but that
> is just an optimization.
> 

Thanks Miklos.

> Below patch fixes several issues with that function.  Could you please give it a
> go?
> 

This patch looks good and fixes the issue for me. It might be good to
give Neils a chance to beat on it as well, but otherwise:

Tested-by: Brian Foster <bfoster@redhat.com>

Brian

> Thanks,
> Miklos
> 
> 
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index 0eda527..a8208c5 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -1223,28 +1223,45 @@ static int fuse_direntplus_link(struct file *file,
>  		if (name.name[1] == '.' && name.len == 2)
>  			return 0;
>  	}
> +
> +	if (invalid_nodeid(o->nodeid))
> +		return -EIO;
> +	if (!fuse_valid_type(o->attr.mode))
> +		return -EIO;
> +
>  	fc = get_fuse_conn(dir);
>  
>  	name.hash = full_name_hash(name.name, name.len);
>  	dentry = d_lookup(parent, &name);
> -	if (dentry && dentry->d_inode) {
> +	if (dentry) {
>  		inode = dentry->d_inode;
> -		if (get_node_id(inode) == o->nodeid) {
> +		if (!inode) {
> +			d_drop(dentry);
> +		} else if (get_node_id(inode) != o->nodeid ||
> +			   ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
> +			err = d_invalidate(dentry);
> +			if (err)
> +				goto out;
> +		} else if (is_bad_inode(inode)) {
> +			err = -EIO;
> +			goto out;
> +		} else {
>  			struct fuse_inode *fi;
>  			fi = get_fuse_inode(inode);
>  			spin_lock(&fc->lock);
>  			fi->nlookup++;
>  			spin_unlock(&fc->lock);
>  
> +			fuse_change_attributes(inode, &o->attr,
> +					       entry_attr_timeout(o),
> +					       attr_version);
> +
>  			/*
>  			 * The other branch to 'found' comes via fuse_iget()
>  			 * which bumps nlookup inside
>  			 */
>  			goto found;
>  		}
> -		err = d_invalidate(dentry);
> -		if (err)
> -			goto out;
>  		dput(dentry);
>  		dentry = NULL;
>  	}
> @@ -1259,25 +1276,30 @@ static int fuse_direntplus_link(struct file *file,
>  	if (!inode)
>  		goto out;
>  
> -	alias = d_materialise_unique(dentry, inode);
> -	err = PTR_ERR(alias);
> -	if (IS_ERR(alias))
> -		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);
> +	}
> +
>  	if (alias) {
>  		dput(dentry);
>  		dentry = alias;
>  	}
>  
>  found:
> -	fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o),
> -			       attr_version);
> -
>  	fuse_change_entry_timeout(dentry, o);
>  
>  	err = 0;
>  out:
> -	if (dentry)
> -		dput(dentry);
> +	dput(dentry);
>  	return err;
>  }
>  
> 


  reply	other threads:[~2013-07-16 17:46 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-15 12:59 [PATCH] fuse: fix occasional dentry leak when readdirplus is used Niels de Vos
2013-07-15 20:08 ` [fuse-devel] " Brian Foster
2013-07-16 10:39   ` Niels de Vos
2013-07-16 13:15     ` Brian Foster
2013-07-16 16:14       ` Miklos Szeredi
2013-07-16 17:43         ` Brian Foster [this message]
2013-07-17 11:20         ` Niels de Vos
2013-07-17 13:04           ` 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=51E58631.7060003@redhat.com \
    --to=bfoster@redhat.com \
    --cc=fuse-devel@lists.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=ndevos@redhat.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.