Patch "ocfs2: revert using ocfs2_acl_chmod to avoid inode cluster lock hang" has been added to the 4.5-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
ocfs2: revert using ocfs2_acl_chmod to avoid inode cluster lock hang
to the 4.5-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ocfs2-revert-using-ocfs2_acl_chmod-to-avoid-inode-cluster-lock-hang.patch
and it can be found in the queue-4.5 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
5ee0fbd50fdf1c1329de8bee35ea9d7c6a81a2e0Mon Sep 17 00:00:00 2001
From: Junxiao Bi <[email protected]>
Date: Thu, 12 May 2016 15:42:15 -0700
Subject: ocfs2: revert using ocfs2_acl_chmod to avoid inode cluster lock hang
From: Junxiao Bi <[email protected]>
commit 5ee0fbd50fdf1c1329de8bee35ea9d7c6a81a2e0 upstream.
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.
--- fs/ocfs2/acl.c | 24 ++++++++++++++++++++++++ fs/ocfs2/acl.h | 1 + fs/ocfs2/file.c | 4 ++-- 3 files changed, 27 insertions(+), 2 deletions(-)
fs/ocfs2/acl.c +24 -0
@@ -322,3 +322,27 @@ struct posix_acl *ocfs2_iop_get_acl(strubrelse (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; +}
fs/ocfs2/acl.h +1 -0
@@ -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 */
fs/ocfs2/file.c +2 -2
@@ -1268,20 +1268,20 @@ bail_unlock_rw: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; }
Patches currently in stable-queue which might be from [email protected] are
queue-4.5/ocfs2-fix-posix_acl_create-deadlock.patch queue-4.5/ocfs2-revert-using-ocfs2_acl_chmod-to-avoid-inode-cluster-lock-hang.patch