]> err.no Git - linux-2.6/commitdiff
[GFS2] Fix recursive locking in gfs2_getattr
authorSteven Whitehouse <swhiteho@redhat.com>
Mon, 27 Nov 2006 15:12:05 +0000 (10:12 -0500)
committerSteven Whitehouse <swhiteho@redhat.com>
Thu, 30 Nov 2006 15:36:56 +0000 (10:36 -0500)
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>
fs/gfs2/ops_inode.c

index fd9fee2ceeac55d700524fd1d6513520480295c8..fbe38c1ab54e9c5d9656430b7638bdbd7f6b9c1f 100644 (file)
@@ -992,6 +992,12 @@ out:
  * @dentry: The dentry to stat
  * @stat: The inode's stats
  *
+ * This may be called from the VFS directly, or from within GFS2 with the
+ * inode locked, so we look to see if the glock is already locked and only
+ * lock the glock if its not already been done. Note that its the NFS
+ * readdirplus operation which causes this to be called (from filldir)
+ * with the glock already held.
+ *
  * Returns: errno
  */
 
@@ -1002,14 +1008,20 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int error;
+       int unlock = 0;
 
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
-       if (!error) {
-               generic_fillattr(inode, stat);
-               gfs2_glock_dq_uninit(&gh);
+       if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
+               error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
+               if (error)
+                       return error;
+               unlock = 1;
        }
 
-       return error;
+       generic_fillattr(inode, stat);
+       if (unlock);
+               gfs2_glock_dq_uninit(&gh);
+
+       return 0;
 }
 
 static int gfs2_setxattr(struct dentry *dentry, const char *name,