mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 14:20:55 +07:00
ocfs2: revert using ocfs2_acl_chmod to avoid inode cluster lock hang
Commit743b5f1434
("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:743b5f1434
("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>
This commit is contained in:
parent
422ce5a975
commit
5ee0fbd50f
@ -322,3 +322,27 @@ struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
|
||||
brelse(di_bh);
|
||||
return acl;
|
||||
}
|
||||
|
||||
int ocfs2_acl_chmod(struct inode *inode, struct buffer_head *bh)
|
||||
{
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
struct posix_acl *acl;
|
||||
int ret;
|
||||
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
|
||||
return 0;
|
||||
|
||||
acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, bh);
|
||||
if (IS_ERR(acl) || !acl)
|
||||
return PTR_ERR(acl);
|
||||
ret = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS,
|
||||
acl, NULL, NULL);
|
||||
posix_acl_release(acl);
|
||||
return ret;
|
||||
}
|
||||
|
@ -35,5 +35,6 @@ int ocfs2_set_acl(handle_t *handle,
|
||||
struct posix_acl *acl,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct ocfs2_alloc_context *data_ac);
|
||||
extern int ocfs2_acl_chmod(struct inode *, struct buffer_head *);
|
||||
|
||||
#endif /* OCFS2_ACL_H */
|
||||
|
@ -1268,20 +1268,20 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
if (size_change)
|
||||
ocfs2_rw_unlock(inode, 1);
|
||||
bail:
|
||||
brelse(bh);
|
||||
|
||||
/* Release quota pointers in case we acquired them */
|
||||
for (qtype = 0; qtype < OCFS2_MAXQUOTAS; qtype++)
|
||||
dqput(transfer_to[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)
|
||||
mlog_errno(status);
|
||||
}
|
||||
if (inode_locked)
|
||||
ocfs2_inode_unlock(inode, 1);
|
||||
|
||||
brelse(bh);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user