[Cluster-devel] [PATCH][GFS2] filesystem consistency error from do_strip

Steven Whitehouse swhiteho at redhat.com
Wed Apr 30 09:08:45 UTC 2008


Hi,

This is now in the -nmw git tree. Thanks,

Steve.

On Tue, 2008-04-29 at 12:35 -0500, Bob Peterson wrote:
> Hi,
> 
> This patch fixes a GFS2 filesystem consistency error reported from
> function do_strip.  The problem was caused by a timing window
> that allowed two vfs inodes to be created in memory that point
> to the same file.  The problem is fixed by making the vfs's
> iget_test, iget_set mechanism check and set a new bit in the
> in-core gfs2_inode structure while the vfs inode spin_lock is held.
> 
> Regards,
> 
> Bob Peterson
> Red Hat Clustering & GFS
> --
>  fs/gfs2/glops.c     |    2 +-
>  fs/gfs2/incore.h    |    1 +
>  fs/gfs2/inode.c     |   10 +++++-----
>  fs/gfs2/meta_io.c   |    6 ++++--
>  fs/gfs2/ops_super.c |   16 +++++++++-------
>  5 files changed, 20 insertions(+), 15 deletions(-)
> 
> diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
> index d31bada..07d84d1 100644
> --- a/fs/gfs2/glops.c
> +++ b/fs/gfs2/glops.c
> @@ -249,7 +249,7 @@ static int inode_go_lock(struct gfs2_holder *gh)
>  	struct gfs2_inode *ip = gl->gl_object;
>  	int error = 0;
>  
> -	if (!ip)
> +	if (!ip || (gh->gh_flags & GL_SKIP))
>  		return 0;
>  
>  	if (test_bit(GIF_INVALID, &ip->i_flags)) {
> diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
> index 9c2c0b9..eabe5ea 100644
> --- a/fs/gfs2/incore.h
> +++ b/fs/gfs2/incore.h
> @@ -236,6 +236,7 @@ enum {
>  	GIF_INVALID		= 0,
>  	GIF_QD_LOCKED		= 1,
>  	GIF_SW_PAGED		= 3,
> +	GIF_USER                = 4, /* user inode, not metadata addr space */
>  };
>  
>  struct gfs2_dinode_host {
> diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> index 3a9ef52..09453d0 100644
> --- a/fs/gfs2/inode.c
> +++ b/fs/gfs2/inode.c
> @@ -47,8 +47,7 @@ static int iget_test(struct inode *inode, void *opaque)
>  	struct gfs2_inode *ip = GFS2_I(inode);
>  	u64 *no_addr = opaque;
>  
> -	if (ip->i_no_addr == *no_addr &&
> -	    inode->i_private != NULL)
> +	if (ip->i_no_addr == *no_addr && test_bit(GIF_USER, &ip->i_flags))
>  		return 1;
>  
>  	return 0;
> @@ -61,6 +60,7 @@ static int iget_set(struct inode *inode, void *opaque)
>  
>  	inode->i_ino = (unsigned long)*no_addr;
>  	ip->i_no_addr = *no_addr;
> +	set_bit(GIF_USER, &ip->i_flags);
>  	return 0;
>  }
>  
> @@ -86,7 +86,7 @@ static int iget_skip_test(struct inode *inode, void *opaque)
>  	struct gfs2_inode *ip = GFS2_I(inode);
>  	struct gfs2_skip_data *data = opaque;
>  
> -	if (ip->i_no_addr == data->no_addr && inode->i_private != NULL){
> +	if (ip->i_no_addr == data->no_addr && test_bit(GIF_USER, &ip->i_flags)){
>  		if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){
>  			data->skipped = 1;
>  			return 0;
> @@ -105,6 +105,7 @@ static int iget_skip_set(struct inode *inode, void *opaque)
>  		return 1;
>  	inode->i_ino = (unsigned long)(data->no_addr);
>  	ip->i_no_addr = data->no_addr;
> +	set_bit(GIF_USER, &ip->i_flags);
>  	return 0;
>  }
>  
> @@ -166,7 +167,7 @@ void gfs2_set_iop(struct inode *inode)
>   * Returns: A VFS inode, or an error
>   */
>  
> -struct inode *gfs2_inode_lookup(struct super_block *sb, 
> +struct inode *gfs2_inode_lookup(struct super_block *sb,
>  				unsigned int type,
>  				u64 no_addr,
>  				u64 no_formal_ino, int skip_freeing)
> @@ -187,7 +188,6 @@ struct inode *gfs2_inode_lookup(struct super_block *sb,
>  
>  	if (inode->i_state & I_NEW) {
>  		struct gfs2_sbd *sdp = GFS2_SB(inode);
> -		inode->i_private = ip;
>  		ip->i_no_formal_ino = no_formal_ino;
>  
>  		error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
> diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
> index 85aea27..78d75f8 100644
> --- a/fs/gfs2/meta_io.c
> +++ b/fs/gfs2/meta_io.c
> @@ -1,6 +1,6 @@
>  /*
>   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
> - * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
> + * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
>   *
>   * This copyrighted material is made available to anyone wishing to use,
>   * modify, copy, or redistribute it subject to the terms and conditions
> @@ -69,13 +69,15 @@ static const struct address_space_operations aspace_aops = {
>  struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp)
>  {
>  	struct inode *aspace;
> +	struct gfs2_inode *ip;
>  
>  	aspace = new_inode(sdp->sd_vfs);
>  	if (aspace) {
>  		mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS);
>  		aspace->i_mapping->a_ops = &aspace_aops;
>  		aspace->i_size = ~0ULL;
> -		aspace->i_private = NULL;
> +		ip = GFS2_I(aspace);
> +		clear_bit(GIF_USER, &ip->i_flags);
>  		insert_inode_hash(aspace);
>  	}
>  	return aspace;
> diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
> index 2278c68..0b7cc92 100644
> --- a/fs/gfs2/ops_super.c
> +++ b/fs/gfs2/ops_super.c
> @@ -1,6 +1,6 @@
>  /*
>   * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
> - * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
> + * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
>   *
>   * This copyrighted material is made available to anyone wishing to use,
>   * modify, copy, or redistribute it subject to the terms and conditions
> @@ -52,7 +52,7 @@ static int gfs2_write_inode(struct inode *inode, int sync)
>  	struct gfs2_inode *ip = GFS2_I(inode);
>  
>  	/* Check this is a "normal" inode */
> -	if (inode->i_private) {
> +	if (test_bit(GIF_USER, &ip->i_flags)) {
>  		if (current->flags & PF_MEMALLOC)
>  			return 0;
>  		if (sync)
> @@ -297,8 +297,9 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
>   */
>  static void gfs2_drop_inode(struct inode *inode)
>  {
> -	if (inode->i_private && inode->i_nlink) {
> -		struct gfs2_inode *ip = GFS2_I(inode);
> +	struct gfs2_inode *ip = GFS2_I(inode);
> +
> +	if (test_bit(GIF_USER, &ip->i_flags) && inode->i_nlink) {
>  		struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
>  		if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags))
>  			clear_nlink(inode);
> @@ -314,12 +315,13 @@ static void gfs2_drop_inode(struct inode *inode)
>  
>  static void gfs2_clear_inode(struct inode *inode)
>  {
> +	struct gfs2_inode *ip = GFS2_I(inode);
> +
>  	/* This tells us its a "real" inode and not one which only
>  	 * serves to contain an address space (see rgrp.c, meta_io.c)
>  	 * which therefore doesn't have its own glocks.
>  	 */
> -	if (inode->i_private) {
> -		struct gfs2_inode *ip = GFS2_I(inode);
> +	if (test_bit(GIF_USER, &ip->i_flags)) {
>  		ip->i_gl->gl_object = NULL;
>  		gfs2_glock_schedule_for_reclaim(ip->i_gl);
>  		gfs2_glock_put(ip->i_gl);
> @@ -419,7 +421,7 @@ static void gfs2_delete_inode(struct inode *inode)
>  	struct gfs2_holder gh;
>  	int error;
>  
> -	if (!inode->i_private)
> +	if (!test_bit(GIF_USER, &ip->i_flags))
>  		goto out;
>  
>  	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
> 
> 




More information about the Cluster-devel mailing list