aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/file.c
diff options
context:
space:
mode:
authorJunxiao Bi <junxiao.bi@oracle.com>2016-05-12 18:42:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-12 18:52:50 -0400
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 <tariq.x.saeed@oracle.com> Signed-off-by: Junxiao Bi <junxiao.bi@oracle.com> Cc: Mark Fasheh <mfasheh@suse.de> Cc: Joel Becker <jlbec@evilplan.org> Cc: Joseph Qi <joseph.qi@huawei.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r--fs/ocfs2/file.c4
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:
1268 if (size_change) 1268 if (size_change)
1269 ocfs2_rw_unlock(inode, 1); 1269 ocfs2_rw_unlock(inode, 1);
1270bail: 1270bail:
1271 brelse(bh);
1272 1271
1273 /* Release quota pointers in case we acquired them */ 1272 /* Release quota pointers in case we acquired them */
1274 for (qtype = 0; qtype < OCFS2_MAXQUOTAS; qtype++) 1273 for (qtype = 0; qtype < OCFS2_MAXQUOTAS; qtype++)
1275 dqput(transfer_to[qtype]); 1274 dqput(transfer_to[qtype]);
1276 1275
1277 if (!status && attr->ia_valid & ATTR_MODE) { 1276 if (!status && attr->ia_valid & ATTR_MODE) {
1278 status = posix_acl_chmod(inode, inode->i_mode); 1277 status = ocfs2_acl_chmod(inode, bh);
1279 if (status < 0) 1278 if (status < 0)
1280 mlog_errno(status); 1279 mlog_errno(status);
1281 } 1280 }
1282 if (inode_locked) 1281 if (inode_locked)
1283 ocfs2_inode_unlock(inode, 1); 1282 ocfs2_inode_unlock(inode, 1);
1284 1283
1284 brelse(bh);
1285 return status; 1285 return status;
1286} 1286}
1287 1287