Orabug:
21793017
ocfs2_setattr called by chmod command holds cluster wide inode lock
(Orabug
21685187) 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 in l_flags. This will cause the second
call to inode lock from the ocfs2_iop_get|set_acl() to block indefinetly.
The new flag OCFS2_LOCK_RECURSIVE will be used to prevent this blocking.
Signed-off-by: Tariq Saeed <tariq.x.saeed@oracle.com>
Signed-off-by: Junxiao Bi <junxiao.bi@oracle.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
#include "xattr.h"
#include "acl.h"
+
/*
* Convert from xattr value to acl struct.
*/
struct buffer_head *bh = NULL;
int status = 0;
- status = ocfs2_inode_lock(inode, &bh, 1);
+ status = ocfs2_inode_lock_full(inode, &bh, 1, OCFS2_LOCK_RECURSIVE);
if (status < 0) {
if (status != -ENOENT)
mlog_errno(status);
osb = OCFS2_SB(inode->i_sb);
if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
return NULL;
- ret = ocfs2_inode_lock(inode, &di_bh, 0);
+ ret = ocfs2_inode_lock_full(inode, &di_bh, 0, OCFS2_LOCK_RECURSIVE);
if (ret < 0) {
if (ret != -ENOENT)
mlog_errno(ret);
}
if (lockres->l_flags & OCFS2_LOCK_BLOCKED &&
- !ocfs2_may_continue_on_blocked_lock(lockres, level)) {
+ !ocfs2_may_continue_on_blocked_lock(lockres, level) &&
+ !(arg_flags & OCFS2_LOCK_RECURSIVE)) {
/* is the lock is currently blocked on behalf of
* another node */
lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BLOCKED, 0);
/* don't block waiting for the downconvert thread, instead return -EAGAIN */
#define OCFS2_LOCK_NONBLOCK (0x04)
+/* if requested level is <= l_level, ignore BLOCKED flag. */
+#define OCFS2_LOCK_RECURSIVE (0x08)
/* Locking subclasses of inode cluster lock */
enum {
OI_LS_NORMAL = 0,