aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-11-27 10:12:05 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-11-30 10:36:56 -0500
commitdcf3dd852f554bb0016aa23892596717cc123a26 (patch)
tree643785eb26407b7f4690ad804434b93636ae01ab /fs
parent300c7d75f3a5e8edd3e390ccd56b808f3fb14e33 (diff)
[GFS2] Fix recursive locking in gfs2_getattr
The readdirplus NFS operation can result in gfs2_getattr being called with the glock already held. In this case we do not want to try and grab the lock again. This fixes Red Hat bugzilla #215727 Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/ops_inode.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index fd9fee2ceeac..fbe38c1ab54e 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -992,6 +992,12 @@ out:
992 * @dentry: The dentry to stat 992 * @dentry: The dentry to stat
993 * @stat: The inode's stats 993 * @stat: The inode's stats
994 * 994 *
995 * This may be called from the VFS directly, or from within GFS2 with the
996 * inode locked, so we look to see if the glock is already locked and only
997 * lock the glock if its not already been done. Note that its the NFS
998 * readdirplus operation which causes this to be called (from filldir)
999 * with the glock already held.
1000 *
995 * Returns: errno 1001 * Returns: errno
996 */ 1002 */
997 1003
@@ -1002,14 +1008,20 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
1002 struct gfs2_inode *ip = GFS2_I(inode); 1008 struct gfs2_inode *ip = GFS2_I(inode);
1003 struct gfs2_holder gh; 1009 struct gfs2_holder gh;
1004 int error; 1010 int error;
1011 int unlock = 0;
1005 1012
1006 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); 1013 if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
1007 if (!error) { 1014 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
1008 generic_fillattr(inode, stat); 1015 if (error)
1009 gfs2_glock_dq_uninit(&gh); 1016 return error;
1017 unlock = 1;
1010 } 1018 }
1011 1019
1012 return error; 1020 generic_fillattr(inode, stat);
1021 if (unlock);
1022 gfs2_glock_dq_uninit(&gh);
1023
1024 return 0;
1013} 1025}
1014 1026
1015static int gfs2_setxattr(struct dentry *dentry, const char *name, 1027static int gfs2_setxattr(struct dentry *dentry, const char *name,