Hi, Now in the -nmw GFS2 tree. Thanks,
Steve. On Tue, 2010-06-15 at 12:07 -0400, Bob Peterson wrote: > Hi, > > This patch fixes a problem in an error path when looking > up dinodes. There are two sister-functions, gfs2_inode_lookup > and gfs2_process_unlinked_inode. Both functions acquire and > hold the i_iopen glock for the dinode being looked up. The last > thing they try to do is hold the i_gl glock for the dinode. > If that glock fails for some reason, the error path was > incorrectly calling gfs2_glock_put for the i_iopen glock twice. > This resulted in the glock being prematurely freed. The > "minimum hold time" usually kept the glock in memory, but the > lock interface to dlm (aka lock_dlm) freed its memory for the > glock. In some circumstances, it would cause dlm's dlm_astd daemon > to try to call the bast function for the freed lock_dlm memory, > which resulted in a NULL pointer dereference. > > This problem was discovered while testing bugzilla bug #595397. > > Regards, > > Bob Peterson > Red Hat GFS > > Signed-off-by: Bob Peterson <[email protected]> > -- > fs/gfs2/inode.c | 6 +++--- > 1 files changed, 3 insertions(+), 3 deletions(-) > > diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c > index b5612cb..43e06ff 100644 > --- a/fs/gfs2/inode.c > +++ b/fs/gfs2/inode.c > @@ -197,8 +197,6 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, > goto fail_iopen; > ip->i_iopen_gh.gh_gl->gl_object = ip; > > - gfs2_glock_put(io_gl); > - > if ((type == DT_UNKNOWN) && (no_formal_ino == 0)) > goto gfs2_nfsbypass; > > @@ -224,6 +222,8 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, > } > > gfs2_nfsbypass: > + gfs2_glock_put(io_gl); > + > return inode; > fail_glock: > gfs2_glock_dq(&ip->i_iopen_gh); > @@ -292,7 +292,6 @@ void gfs2_process_unlinked_inode(struct super_block *sb, > u64 no_addr) > goto fail_iopen; > > ip->i_iopen_gh.gh_gl->gl_object = ip; > - gfs2_glock_put(io_gl); > > inode->i_mode = DT2IF(DT_UNKNOWN); > > @@ -310,6 +309,7 @@ void gfs2_process_unlinked_inode(struct super_block *sb, > u64 no_addr) > > /* Inode is now uptodate */ > gfs2_glock_dq_uninit(&gh); > + gfs2_glock_put(io_gl); > gfs2_set_iop(inode); > > /* The iput will cause it to be deleted. */
