diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-11-27 10:12:05 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-11-30 10:36:56 -0500 |
commit | dcf3dd852f554bb0016aa23892596717cc123a26 (patch) | |
tree | 643785eb26407b7f4690ad804434b93636ae01ab /fs/gfs2/ops_inode.c | |
parent | 300c7d75f3a5e8edd3e390ccd56b808f3fb14e33 (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/gfs2/ops_inode.c')
-rw-r--r-- | fs/gfs2/ops_inode.c | 22 |
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 | ||
1015 | static int gfs2_setxattr(struct dentry *dentry, const char *name, | 1027 | static int gfs2_setxattr(struct dentry *dentry, const char *name, |