From mboxrd@z Thu Jan 1 00:00:00 1970 From: Steven Whitehouse Date: Wed, 30 Apr 2008 10:08:45 +0100 Subject: [Cluster-devel] [PATCH][GFS2] filesystem consistency error from do_strip In-Reply-To: <1209490548.25554.15.camel@technetium.msp.redhat.com> References: <1209490548.25554.15.camel@technetium.msp.redhat.com> Message-ID: <1209546525.3635.468.camel@quoit> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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); > >