diff options
author | Benjamin Marzinski <bmarzins@redhat.com> | 2012-11-06 00:49:28 -0600 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2012-11-07 09:42:49 +0000 |
commit | 3d1626889a64bd5a661544d582036a0a02104a60 (patch) | |
tree | 7b5d43873e088346175d982fd8e840be586fcb5e /fs/gfs2/super.c | |
parent | 076f0faa764ab3a5a32fc726ae05e2de0e66151d (diff) |
GFS2: Don't call file_accessed() with a shared glock
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 <bmarzins@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/super.c')
-rw-r--r-- | fs/gfs2/super.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index bc737261f234..d6488674d916 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags) return; } 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); |