Patchwork [3.5.y.z,extended,stable] Patch "GFS2: Don't call file_accessed() with a shared glock" has been added to staging queue

mail settings
Submitter Herton Ronaldo Krzesinski
Date Dec. 12, 2012, 5:12 a.m.
Message ID <>
Download mbox | patch
Permalink /patch/205429/
State New
Headers show


Herton Ronaldo Krzesinski - Dec. 12, 2012, 5:12 a.m.
This is a note to let you know that I have just added a patch titled

    GFS2: Don't call file_accessed() with a shared glock

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:;a=shortlog;h=refs/heads/linux-3.5.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see



From 9572d7d85c65d5306b937e696c0b3a89f5f2fab8 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <>
Date: Tue, 6 Nov 2012 00:49:28 -0600
Subject: [PATCH] GFS2: Don't call file_accessed() with a shared glock

commit 3d1626889a64bd5a661544d582036a0a02104a60 upstream.

file_accessed() was being called by gfs2_mmap() with a shared glock. If it
needed to update the atime, it was crashing because it dirtied the inode in
gfs2_dirty_inode() without holding an exclusive lock. gfs2_dirty_inode()
checked if the caller was already holding a glock, but it didn't make sure that
the glock was in the exclusive state. Now, instead of calling file_accessed()
while holding the shared lock in gfs2_mmap(), file_accessed() is called after
grabbing and releasing the glock to update the inode.  If file_accessed() needs
to update the atime, it will grab an exclusive lock in gfs2_dirty_inode().

gfs2_dirty_inode() now also checks to make sure that if the calling process has
already locked the glock, it has an exclusive lock.

Signed-off-by: Benjamin Marzinski <>
Signed-off-by: Steven Whitehouse <>
Signed-off-by: Herton Ronaldo Krzesinski <>
 fs/gfs2/file.c  |   12 +++++-------
 fs/gfs2/super.c |    3 ++-
 2 files changed, 7 insertions(+), 8 deletions(-)



diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 31b199f..a8a81d7 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -492,15 +492,13 @@  static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
 		struct gfs2_holder i_gh;
 		int error;

-		gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
-		error = gfs2_glock_nq(&i_gh);
-		if (error == 0) {
-			file_accessed(file);
-			gfs2_glock_dq(&i_gh);
-		}
-		gfs2_holder_uninit(&i_gh);
+		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY,
+					   &i_gh);
 		if (error)
 			return error;
+		/* grab lock to update inode */
+		gfs2_glock_dq_uninit(&i_gh);
+		file_accessed(file);
 	vma->vm_ops = &gfs2_vm_ops;
 	vma->vm_flags |= VM_CAN_NONLINEAR;
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 713e621..12769a2 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -800,7 +800,8 @@  static void gfs2_dirty_inode(struct inode *inode, int flags)
 		need_unlock = 1;
-	}
+	} else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE))
+		return;

 	if (current->journal_info == NULL) {
 		ret = gfs2_trans_begin(sdp, RES_DINODE, 0);