]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
add OCFS2_LOCK_RECURSIVE arg_flags to ocfs2_cluster_lock() to prevent hang
authorTariq Saeed <tariq.x.saeed@oracle.com>
Fri, 4 Sep 2015 22:39:03 +0000 (15:39 -0700)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Tue, 8 Sep 2015 18:19:11 +0000 (11:19 -0700)
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>
fs/ocfs2/acl.c
fs/ocfs2/dlmglue.c
fs/ocfs2/dlmglue.h

index 0cdf497c91efbb915512aceed2bf58acaa37fa1d..85bc143f674df2262faf651090985f2ef814bb1f 100644 (file)
@@ -37,6 +37,7 @@
 #include "xattr.h"
 #include "acl.h"
 
+
 /*
  * Convert from xattr value to acl struct.
  */
@@ -287,7 +288,7 @@ int ocfs2_iop_set_acl(struct inode *inode, struct posix_acl *acl, int type)
        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);
@@ -309,7 +310,7 @@ struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
        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);
index b2dbba7e4819178970eda0335196d5554521bd5a..a1d8110840a57fba8e477ef34bc008b97248c0d1 100644 (file)
@@ -1448,7 +1448,8 @@ again:
        }
 
        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);
index d293a22c32c5447e3595f1a61deba545f74df7e5..6e54fe78fdbd1de64299b4b969c65c636e8b8956 100644 (file)
@@ -78,6 +78,8 @@ struct ocfs2_orphan_scan_lvb {
 /* 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,