path: root/fs/ocfs2/file.c
diff options
authorJunxiao Bi <>2016-05-12 15:42:15 -0700
committerLinus Torvalds <>2016-05-12 15:52:50 -0700
commit5ee0fbd50fdf1c1329de8bee35ea9d7c6a81a2e0 (patch)
treead5472be43466ea27f8a6804f0de9a8631d67cc6 /fs/ocfs2/file.c
parent422ce5a97570cb8a37d016b6bc2021ae4dac5499 (diff)
ocfs2: revert using ocfs2_acl_chmod to avoid inode cluster lock hang
Commit 743b5f1434f5 ("ocfs2: take inode lock in ocfs2_iop_set/get_acl()") introduced this issue. ocfs2_setattr called by chmod command holds cluster wide inode lock when calling posix_acl_chmod. This latter function in turn calls ocfs2_iop_get_acl and ocfs2_iop_set_acl. These two are also called directly from vfs layer for getfacl/setfacl commands and therefore acquire the cluster wide inode lock. If a remote conversion request comes after the first inode lock in ocfs2_setattr, OCFS2_LOCK_BLOCKED will be set. And this will cause the second call to inode lock from the ocfs2_iop_get_acl() to block indefinetly. The deleted version of ocfs2_acl_chmod() calls __posix_acl_chmod() which does not call back into the filesystem. Therefore, we restore ocfs2_acl_chmod(), modify it slightly for locking as needed, and use that instead. Fixes: 743b5f1434f5 ("ocfs2: take inode lock in ocfs2_iop_set/get_acl()") Signed-off-by: Tariq Saeed <> Signed-off-by: Junxiao Bi <> Cc: Mark Fasheh <> Cc: Joel Becker <> Cc: Joseph Qi <> Cc: <> Signed-off-by: Andrew Morton <> Signed-off-by: Linus Torvalds <>
Diffstat (limited to 'fs/ocfs2/file.c')
1 files changed, 2 insertions, 2 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 5308841756be..59cce53c91d8 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1268,20 +1268,20 @@ bail_unlock_rw:
if (size_change)
ocfs2_rw_unlock(inode, 1);
- brelse(bh);
/* Release quota pointers in case we acquired them */
for (qtype = 0; qtype < OCFS2_MAXQUOTAS; qtype++)
if (!status && attr->ia_valid & ATTR_MODE) {
- status = posix_acl_chmod(inode, inode->i_mode);
+ status = ocfs2_acl_chmod(inode, bh);
if (status < 0)
if (inode_locked)
ocfs2_inode_unlock(inode, 1);
+ brelse(bh);
return status;