linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: Ian Kent <raven@themaw.net>
Cc: torvalds@linux-foundation.org, viro@ZenIV.linux.org.uk,
	miklos@szeredi.hu, jesper@krogh.cc, linux-kernel@vger.kernel.org,
	linux-fsdevel@vger.kernel.org, jmoyer@redhat.com
Subject: Re: Linux 2.6.26-rc4
Date: Thu, 5 Jun 2008 15:30:19 -0700	[thread overview]
Message-ID: <20080605153019.77d61199.akpm@linux-foundation.org> (raw)
In-Reply-To: <1212651099.3047.44.camel@raven.themaw.net>

On Thu, 05 Jun 2008 15:31:37 +0800
Ian Kent <raven@themaw.net> wrote:

> 
> On Tue, 2008-06-03 at 08:01 -0700, Linus Torvalds wrote:
> > 
> > On Tue, 3 Jun 2008, Ian Kent wrote:
> > > > 
> > > > > I think it must be autofs4 doing something weird.  Like this in
> > > > > autofs4_lookup_unhashed():
> > > > > 
> > > > > 			/*
> > > > > 			 * Make the rehashed dentry negative so the VFS
> > > > > 			 * behaves as it should.
> > > > > 			 */
> > > > > 			if (inode) {
> > > > > 				dentry->d_inode = NULL;
> > 
> > Uhhuh. Yeah, that's not allowed.
> > 
> > A dentry inode can start _out_ as NULL, but it can never later become NULL 
> > again until it is totally unused.
> 
> Here is a patch for autofs4 to, hopefully, resolve this.
> 
> Keep in mind this doesn't address any other autofs4 issues but I it
> should allow us to identify if this was in fact the root cause of the
> problem Jesper reported.
> 
> autofs4 - leave rehashed dentry positive
> 
> From: Ian Kent <raven@themaw.net>
> 
> Correct the error of making a positive dentry negative after it has been
> instantiated.
> 
> This involves removing the code in autofs4_lookup_unhashed() that
> makes the dentry negative and updating autofs4_dir_symlink() and
> autofs4_dir_mkdir() to recognise they have been given a postive
> dentry (previously the dentry was always negative) and deal with
> it. In addition the dentry info struct initialization, autofs4_init_ino(),
> and the symlink free function, ino_lnkfree(), have been made aware
> of this possible re-use. This is needed because the current case
> re-uses a dentry in order to preserve it's flags as described in
> commit f50b6f8691cae2e0064c499dd3ef3f31142987f0.
> 
> ...
>
> ...
>
> diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
> index edf5b6b..6ce603b 100644
> --- a/fs/autofs4/root.c
> +++ b/fs/autofs4/root.c
> @@ -555,24 +555,8 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct
>  			goto next;
>  
>  		if (d_unhashed(dentry)) {
> -			struct inode *inode = dentry->d_inode;
> -
> -			ino = autofs4_dentry_ino(dentry);
>  			list_del_init(&ino->rehash);
>  			dget(dentry);
> -			/*
> -			 * Make the rehashed dentry negative so the VFS
> -			 * behaves as it should.
> -			 */
> -			if (inode) {
> -				dentry->d_inode = NULL;
> -				list_del_init(&dentry->d_alias);
> -				spin_unlock(&dentry->d_lock);
> -				spin_unlock(&sbi->rehash_lock);
> -				spin_unlock(&dcache_lock);
> -				iput(inode);
> -				return dentry;
> -			}
>  			spin_unlock(&dentry->d_lock);
>  			spin_unlock(&sbi->rehash_lock);
>  			spin_unlock(&dcache_lock);
> @@ -728,35 +712,50 @@ static int autofs4_dir_symlink(struct inode *dir,
>  		return -EACCES;
>  
>  	ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555);
> -	if (ino == NULL)
> +	if (!ino)
>  		return -ENOSPC;

Should have been ENOMEM, I guess.

> -	ino->size = strlen(symname);
> -	ino->u.symlink = cp = kmalloc(ino->size + 1, GFP_KERNEL);
> -
> -	if (cp == NULL) {
> -		kfree(ino);
> +	cp = kmalloc(ino->size + 1, GFP_KERNEL);
> +	if (!cp) {
> +		if (!dentry->d_fsdata)
> +			kfree(ino);

OK, so here we work out that autofs4_init_ino() had to allocate a new
autofs_info and if so, free it here.  It took me a moment..

>  		return -ENOSPC;

ENOMEM?

>  	}
>  
>  	strcpy(cp, symname);
>  
> -	inode = autofs4_get_inode(dir->i_sb, ino);
> -	d_add(dentry, inode);
> +	inode = dentry->d_inode;
> +	if (inode)
> +		d_rehash(dentry);
> +	else {
> +		inode = autofs4_get_inode(dir->i_sb, ino);
> +		if (!inode) {
> +			kfree(cp);
> +			if (!dentry->d_fsdata)
> +				kfree(ino);
> +			return -ENOSPC;
> +		}
> +
> +		d_add(dentry, inode);
>  
> -	if (dir == dir->i_sb->s_root->d_inode)
> -		dentry->d_op = &autofs4_root_dentry_operations;
> -	else
> -		dentry->d_op = &autofs4_dentry_operations;
> +		if (dir == dir->i_sb->s_root->d_inode)
> +			dentry->d_op = &autofs4_root_dentry_operations;
> +		else
> +			dentry->d_op = &autofs4_dentry_operations;
> +
> +		dentry->d_fsdata = ino;
> +		ino->dentry = dentry;
> +		ino->inode = inode;
> +	}
> +	dget(dentry);
>  
> -	dentry->d_fsdata = ino;
> -	ino->dentry = dget(dentry);
>  	atomic_inc(&ino->count);
>  	p_ino = autofs4_dentry_ino(dentry->d_parent);
>  	if (p_ino && dentry->d_parent != dentry)
>  		atomic_inc(&p_ino->count);
> -	ino->inode = inode;
>  
> +	ino->u.symlink = cp;
> +	ino->size = strlen(symname);
>  	dir->i_mtime = CURRENT_TIME;

This all seems a bit ungainly.  I assume that on entry to
autofs4_dir_symlink(), ino->size is equal to strlen(symname)?  If it's
not, that strcpy() will overrun.

But if ino->size _is_ equal to strlen(symname) then why did we just
recalculate the same thing?

I'm suspecting we can zap a lump of code and just do

	cp = kstrdup(symname, GFP_KERNEL);

Anyway, please check that.

>  	return 0;
> @@ -866,24 +865,38 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
>  		dentry, dentry->d_name.len, dentry->d_name.name);
>  
>  	ino = autofs4_init_ino(ino, sbi, S_IFDIR | 0555);
> -	if (ino == NULL)
> +	if (!ino)
>  		return -ENOSPC;

ENOMEM?

> -	inode = autofs4_get_inode(dir->i_sb, ino);
> -	d_add(dentry, inode);
> +	inode = dentry->d_inode;
> +	if (inode)
> +		d_rehash(dentry);
> +	else {
> +		inode = autofs4_get_inode(dir->i_sb, ino);
> +		if (!inode) {
> +			if (!dentry->d_fsdata)
> +				kfree(ino);
> +			return -ENOSPC;
> +		}
>  
> -	if (dir == dir->i_sb->s_root->d_inode)
> -		dentry->d_op = &autofs4_root_dentry_operations;
> -	else
> -		dentry->d_op = &autofs4_dentry_operations;
> +		d_add(dentry, inode);
> +
> +		if (dir == dir->i_sb->s_root->d_inode)
> +			dentry->d_op = &autofs4_root_dentry_operations;
> +		else
> +			dentry->d_op = &autofs4_dentry_operations;
> +
> +		dentry->d_fsdata = ino;
> +		ino->dentry = dentry;
> +		ino->inode = inode;
> +	}
> +	dget(dentry);

This all looks very similar to the code in autofs4_dir_symlink().  Some
refactoring might be needed at some stage?

> -	dentry->d_fsdata = ino;
> -	ino->dentry = dget(dentry);
>  	atomic_inc(&ino->count);
>  	p_ino = autofs4_dentry_ino(dentry->d_parent);
>  	if (p_ino && dentry->d_parent != dentry)
>  		atomic_inc(&p_ino->count);
> -	ino->inode = inode;
> +
>  	inc_nlink(dir);
>  	dir->i_mtime = CURRENT_TIME;
>  
> 

  parent reply	other threads:[~2008-06-05 22:31 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <alpine.LFD.1.10.0805261127030.2958@woody.linux-foundation.org>
2008-06-03  9:49 ` Linux 2.6.26-rc4 Jesper Krogh
2008-06-03  9:57   ` Al Viro
2008-06-03 10:04     ` Jesper Krogh
2008-06-03 10:13       ` Miklos Szeredi
2008-06-03 10:37         ` Miklos Szeredi
2008-06-03 10:48           ` Al Viro
2008-06-03 13:31             ` Ian Kent
2008-06-03 13:32               ` Ian Kent
2008-06-03 10:40         ` Al Viro
2008-06-03 10:45           ` Miklos Szeredi
2008-06-03 10:52             ` Al Viro
2008-06-03 13:27               ` Ian Kent
2008-06-03 15:01                 ` Linus Torvalds
2008-06-03 16:07                   ` Ian Kent
2008-06-03 16:35                     ` Linus Torvalds
2008-06-03 16:41                       ` Al Viro
2008-06-03 16:50                         ` Al Viro
2008-06-03 17:28                           ` Ian Kent
2008-06-03 17:41                             ` Al Viro
2008-06-03 17:41                               ` Ian Kent
2008-06-03 17:50                                 ` Al Viro
2008-06-03 17:49                                   ` Ian Kent
2008-06-03 16:59                         ` Linus Torvalds
2008-06-03 17:30                           ` Ian Kent
2008-06-03 17:13                       ` Ian Kent
2008-06-03 17:30                         ` Al Viro
2008-06-03 17:38                           ` Ian Kent
2008-06-03 17:46                           ` Jeff Moyer
2008-06-03 19:18                             ` Al Viro
2008-06-03 19:53                               ` Jeff Moyer
2008-06-03 23:00                                 ` Al Viro
2008-06-04  2:42                                   ` Ian Kent
2008-06-04  5:34                                     ` Miklos Szeredi
2008-06-04  5:41                                       ` Ian Kent
2008-06-10  4:57                                     ` Ian Kent
2008-06-10  6:28                                       ` Jesper Krogh
2008-06-10  6:40                                         ` Ian Kent
2008-06-10  9:09                                           ` Ian Kent
2008-06-12  3:03                                           ` Ian Kent
2008-06-12  7:02                                             ` Jesper Krogh
2008-06-12 11:21                                               ` Ian Kent
2008-06-12 11:19                                             ` Ian Kent
2008-06-04  1:36                               ` Ian Kent
2008-06-05  7:31                   ` Ian Kent
2008-06-05 21:29                     ` Linus Torvalds
2008-06-05 21:34                       ` Jesper Krogh
2008-06-06  2:39                       ` Ian Kent
2008-06-05 22:30                     ` Andrew Morton [this message]
2008-06-06  2:47                       ` Ian Kent
2008-06-27  4:18                       ` Ian Kent
2008-06-06  6:23                     ` Jesper Krogh
2008-06-06  8:21                       ` Ian Kent
2008-06-06  8:25                         ` Ian Kent
2008-06-03 10:35     ` Al Viro

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=20080605153019.77d61199.akpm@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=jesper@krogh.cc \
    --cc=jmoyer@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=raven@themaw.net \
    --cc=torvalds@linux-foundation.org \
    --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;
as well as URLs for NNTP newsgroup(s).