[Ocfs2-devel] [Ocfs2-users] ocfs or configfs bug ?

Sunil Mushran sunil.mushran at oracle.com
Wed May 18 11:36:59 PDT 2011


On 05/18/2011 04:12 AM, Joel Becker wrote:
> On Wed, May 18, 2011 at 03:49:56AM -0700, Joel Becker wrote:
>> 	sysfs_mutex is peppered everywhere.  It's rather ugly, I think.
>> I am thinking about how the code reads.  I admit I also don't like that
>> sysfs_mutex serializes all accesses to the sysfs directory tree, but I'd
>> be OK with that as a stopgap solution if the code only read better.
> 	Can you test this?
>
> Joel


So it did run for far longer. But then hit the following.

http://oss.oracle.com/~smushran/configfs_oops_20110518.txt

BTW, this is not new. I was running into it earlier too. Albeit
less frequently than readdir.


>  From 24307aa1e707b31613be92deaba7990e16bc1aec Mon Sep 17 00:00:00 2001
> From: Joel Becker<jlbec at evilplan.org>
> Date: Wed, 18 May 2011 04:08:16 -0700
> Subject: [PATCH] configfs: Fix race between configfs_readdir() and configfs_d_iput()
>
> configfs_readdir() will use the existing inode numbers of inodes in the
> dcache, but it makes them up for attribute files that aren't currently
> instantiated.  There is a race where a closing attribute file can be
> tearing down at the same time as configfs_readdir() is trying to get its
> inode number.
>
> We want to get the inode number of open attribute files, because they
> should match while instantiated.  We can't lock down the transition
> where dentry->d_inode is set to NULL, so we just check for NULL there.
> We can, however, ensure that an inode we find isn't iput() in
> configfs_d_iput() until after we've accessed it.
>
> Signed-off-by: Joel Becker<jlbec at evilplan.org>
> ---
>   fs/configfs/dir.c |   33 ++++++++++++++++++++++++++++-----
>   1 files changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
> index b11d734..9a37a9b 100644
> --- a/fs/configfs/dir.c
> +++ b/fs/configfs/dir.c
> @@ -53,11 +53,14 @@ DEFINE_SPINLOCK(configfs_dirent_lock);
>   static void configfs_d_iput(struct dentry * dentry,
>   			    struct inode * inode)
>   {
> -	struct configfs_dirent * sd = dentry->d_fsdata;
> +	struct configfs_dirent *sd = dentry->d_fsdata;
>
>   	if (sd) {
>   		BUG_ON(sd->s_dentry != dentry);
> +		/* Coordinate with configfs_readdir */
> +		spin_lock(&configfs_dirent_lock);
>   		sd->s_dentry = NULL;
> +		spin_unlock(&configfs_dirent_lock);
>   		configfs_put(sd);
>   	}
>   	iput(inode);
> @@ -1546,7 +1549,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
>   	struct configfs_dirent * parent_sd = dentry->d_fsdata;
>   	struct configfs_dirent *cursor = filp->private_data;
>   	struct list_head *p, *q =&cursor->s_sibling;
> -	ino_t ino;
> +	ino_t ino = 0;
>   	int i = filp->f_pos;
>
>   	switch (i) {
> @@ -1574,6 +1577,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
>   				struct configfs_dirent *next;
>   				const char * name;
>   				int len;
> +				struct inode *inode = NULL;
>
>   				next = list_entry(p, struct configfs_dirent,
>   						   s_sibling);
> @@ -1582,9 +1586,28 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
>
>   				name = configfs_get_name(next);
>   				len = strlen(name);
> -				if (next->s_dentry)
> -					ino = next->s_dentry->d_inode->i_ino;
> -				else
> +
> +				/*
> +				 * We'll have a dentry and an inode for
> +				 * PINNED items and for open attribute
> +				 * files.  We lock here to prevent a race
> +				 * with configfs_d_iput() clearing
> +				 * s_dentry before calling iput().
> +				 *
> +				 * Why do we go to the trouble?  If
> +				 * someone has an attribute file open,
> +				 * the inode number should match until
> +				 * they close it.  Beyond that, we don't
> +				 * care.
> +				 */
> +				spin_lock(&configfs_dirent_lock);
> +				dentry = next->s_dentry;
> +				if (dentry)
> +					inode = dentry->d_inode;
> +				if (inode)
> +					ino = inode->i_ino;
> +				spin_unlock(&configfs_dirent_lock);
> +				if (!inode)
>   					ino = iunique(configfs_sb, 2);
>
>   				if (filldir(dirent, name, len, filp->f_pos, ino,




More information about the Ocfs2-devel mailing list