Re: [Ocfs2-devel] [PATCH v2] ocfs2: fix deadlock caused by recursive locking in xattr

2017-06-22 Thread Eric Ren
Hi Andrew,

On 06/23/2017 05:24 AM, Andrew Morton wrote:
> On Thu, 22 Jun 2017 14:10:38 +0800 Joseph Qi  wrote:
>
>> Looks good.
>> Reviewed-by: Joseph Qi 
> Should this fix be backported into -stable kernels?

No, I think, because the previous patches that this one needs to be on,

- commit 439a36b8ef38 ("ocfs2/dlmglue: prepare tracking logic to avoid 
recursive cluster lock").
- commit b891fa5024a9 ("ocfs2: fix deadlock issue when taking inode lock at vfs 
entry points")

is not in --stable too.

I don't know if it's possible to make them all into stable.

Thanks,
Eric

>
>> On 17/6/22 09:47, Eric Ren wrote:
>>> Another deadlock path caused by recursive locking is reported.
>>> This kind of issue was introduced since commit 743b5f1434f5 ("ocfs2:
>>> take inode lock in ocfs2_iop_set/get_acl()"). Two deadlock paths
>>> have been fixed by commit b891fa5024a9 ("ocfs2: fix deadlock issue when
>>> taking inode lock at vfs entry points"). Yes, we intend to fix this
>>> kind of case in incremental way, because it's hard to find out all
>>> possible paths at once.
>>>
>>> This one can be reproduced like this. On node1, cp a large file from
>>> home directory to ocfs2 mountpoint. While on node2, run setfacl/getfacl.
>>> Both nodes will hang up there. The backtraces:
>>>
>>> On node1:
>>> [] __ocfs2_cluster_lock.isra.39+0x357/0x740 [ocfs2]
>>> [] ocfs2_inode_lock_full_nested+0x17d/0x840 [ocfs2]
>>> [] ocfs2_write_begin+0x43/0x1a0 [ocfs2]
>>> [] generic_perform_write+0xa9/0x180
>>> [] __generic_file_write_iter+0x1aa/0x1d0
>>> [] ocfs2_file_write_iter+0x4f4/0xb40 [ocfs2]
>>> [] __vfs_write+0xc3/0x130
>>> [] vfs_write+0xb1/0x1a0
>>> [] SyS_write+0x46/0xa0
>>>
>>> On node2:
>>> [] __ocfs2_cluster_lock.isra.39+0x357/0x740 [ocfs2]
>>> [] ocfs2_inode_lock_full_nested+0x17d/0x840 [ocfs2]
>>> [] ocfs2_xattr_set+0x12e/0xe80 [ocfs2]
>>> [] ocfs2_set_acl+0x22d/0x260 [ocfs2]
>>> [] ocfs2_iop_set_acl+0x65/0xb0 [ocfs2]
>>> [] set_posix_acl+0x75/0xb0
>>> [] posix_acl_xattr_set+0x49/0xa0
>>> [] __vfs_setxattr+0x69/0x80
>>> [] __vfs_setxattr_noperm+0x72/0x1a0
>>> [] vfs_setxattr+0xa7/0xb0
>>> [] setxattr+0x12d/0x190
>>> [] path_setxattr+0x9f/0xb0
>>> [] SyS_setxattr+0x14/0x20
>>>
>>> Fixes this one by using ocfs2_inode_{lock|unlock}_tracker, which is
>>> exported by commit 439a36b8ef38 ("ocfs2/dlmglue: prepare tracking
>>> logic to avoid recursive cluster lock").
>>>
>>> Changes since v1:
>>> - Revised git commit description style in commit log.
>>>
>>> Reported-by: Thomas Voegtle 
>>> Tested-by: Thomas Voegtle 
>>> Signed-off-by: Eric Ren 
>>> ---
>>>   fs/ocfs2/dlmglue.c |  4 
>>>   fs/ocfs2/xattr.c   | 23 +--
>>>   2 files changed, 17 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
>>> index 3b7c937..4689940 100644
>>> --- a/fs/ocfs2/dlmglue.c
>>> +++ b/fs/ocfs2/dlmglue.c
>>> @@ -2591,6 +2591,10 @@ void ocfs2_inode_unlock_tracker(struct inode *inode,
>>> struct ocfs2_lock_res *lockres;
>>>   
>>> lockres = _I(inode)->ip_inode_lockres;
>>> +   /* had_lock means that the currect process already takes the cluster
>>> +* lock previously. If had_lock is 1, we have nothing to do here, and
>>> +* it will get unlocked where we got the lock.
>>> +*/
>>> if (!had_lock) {
>>> ocfs2_remove_holder(lockres, oh);
>>> ocfs2_inode_unlock(inode, ex);
>>> diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
>>> index 3c5384d..f70c377 100644
>>> --- a/fs/ocfs2/xattr.c
>>> +++ b/fs/ocfs2/xattr.c
>>> @@ -1328,20 +1328,21 @@ static int ocfs2_xattr_get(struct inode *inode,
>>>void *buffer,
>>>size_t buffer_size)
>>>   {
>>> -   int ret;
>>> +   int ret, had_lock;
>>> struct buffer_head *di_bh = NULL;
>>> +   struct ocfs2_lock_holder oh;
>>>   
>>> -   ret = ocfs2_inode_lock(inode, _bh, 0);
>>> -   if (ret < 0) {
>>> -   mlog_errno(ret);
>>> -   return ret;
>>> +   had_lock = ocfs2_inode_lock_tracker(inode, _bh, 0, );
>>> +   if (had_lock < 0) {
>>> +   mlog_errno(had_lock);
>>> +   return had_lock;
>>> }
>>> down_read(_I(inode)->ip_xattr_sem);
>>> ret = ocfs2_xattr_get_nolock(inode, di_bh, name_index,
>>>  name, buffer, buffer_size);
>>> up_read(_I(inode)->ip_xattr_sem);
>>>   
>>> -   ocfs2_inode_unlock(inode, 0);
>>> +   ocfs2_inode_unlock_tracker(inode, 0, , had_lock);
>>>   
>>> brelse(di_bh);
>>>   
>>> @@ -3537,11 +3538,12 @@ int ocfs2_xattr_set(struct inode *inode,
>>>   {
>>> struct buffer_head *di_bh = NULL;
>>> struct ocfs2_dinode *di;
>>> -   int ret, credits, ref_meta = 0, ref_credits = 0;
>>> +   int ret, credits, had_lock, ref_meta = 0, ref_credits = 0;
>>> struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
>>> struct inode *tl_inode = osb->osb_tl_inode;
>>> struct ocfs2_xattr_set_ctxt ctxt 

Re: [Ocfs2-devel] [PATCH v2] ocfs2: fix deadlock caused by recursive locking in xattr

2017-06-22 Thread Andrew Morton
On Thu, 22 Jun 2017 14:10:38 +0800 Joseph Qi  wrote:

> Looks good.
> Reviewed-by: Joseph Qi 

Should this fix be backported into -stable kernels?

> On 17/6/22 09:47, Eric Ren wrote:
> > Another deadlock path caused by recursive locking is reported.
> > This kind of issue was introduced since commit 743b5f1434f5 ("ocfs2:
> > take inode lock in ocfs2_iop_set/get_acl()"). Two deadlock paths
> > have been fixed by commit b891fa5024a9 ("ocfs2: fix deadlock issue when
> > taking inode lock at vfs entry points"). Yes, we intend to fix this
> > kind of case in incremental way, because it's hard to find out all
> > possible paths at once.
> > 
> > This one can be reproduced like this. On node1, cp a large file from
> > home directory to ocfs2 mountpoint. While on node2, run setfacl/getfacl.
> > Both nodes will hang up there. The backtraces:
> > 
> > On node1:
> > [] __ocfs2_cluster_lock.isra.39+0x357/0x740 [ocfs2]
> > [] ocfs2_inode_lock_full_nested+0x17d/0x840 [ocfs2]
> > [] ocfs2_write_begin+0x43/0x1a0 [ocfs2]
> > [] generic_perform_write+0xa9/0x180
> > [] __generic_file_write_iter+0x1aa/0x1d0
> > [] ocfs2_file_write_iter+0x4f4/0xb40 [ocfs2]
> > [] __vfs_write+0xc3/0x130
> > [] vfs_write+0xb1/0x1a0
> > [] SyS_write+0x46/0xa0
> > 
> > On node2:
> > [] __ocfs2_cluster_lock.isra.39+0x357/0x740 [ocfs2]
> > [] ocfs2_inode_lock_full_nested+0x17d/0x840 [ocfs2]
> > [] ocfs2_xattr_set+0x12e/0xe80 [ocfs2]
> > [] ocfs2_set_acl+0x22d/0x260 [ocfs2]
> > [] ocfs2_iop_set_acl+0x65/0xb0 [ocfs2]
> > [] set_posix_acl+0x75/0xb0
> > [] posix_acl_xattr_set+0x49/0xa0
> > [] __vfs_setxattr+0x69/0x80
> > [] __vfs_setxattr_noperm+0x72/0x1a0
> > [] vfs_setxattr+0xa7/0xb0
> > [] setxattr+0x12d/0x190
> > [] path_setxattr+0x9f/0xb0
> > [] SyS_setxattr+0x14/0x20
> > 
> > Fixes this one by using ocfs2_inode_{lock|unlock}_tracker, which is
> > exported by commit 439a36b8ef38 ("ocfs2/dlmglue: prepare tracking
> > logic to avoid recursive cluster lock").
> > 
> > Changes since v1:
> > - Revised git commit description style in commit log.
> > 
> > Reported-by: Thomas Voegtle 
> > Tested-by: Thomas Voegtle 
> > Signed-off-by: Eric Ren 
> > ---
> >  fs/ocfs2/dlmglue.c |  4 
> >  fs/ocfs2/xattr.c   | 23 +--
> >  2 files changed, 17 insertions(+), 10 deletions(-)
> > 
> > diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
> > index 3b7c937..4689940 100644
> > --- a/fs/ocfs2/dlmglue.c
> > +++ b/fs/ocfs2/dlmglue.c
> > @@ -2591,6 +2591,10 @@ void ocfs2_inode_unlock_tracker(struct inode *inode,
> > struct ocfs2_lock_res *lockres;
> >  
> > lockres = _I(inode)->ip_inode_lockres;
> > +   /* had_lock means that the currect process already takes the cluster
> > +* lock previously. If had_lock is 1, we have nothing to do here, and
> > +* it will get unlocked where we got the lock.
> > +*/
> > if (!had_lock) {
> > ocfs2_remove_holder(lockres, oh);
> > ocfs2_inode_unlock(inode, ex);
> > diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
> > index 3c5384d..f70c377 100644
> > --- a/fs/ocfs2/xattr.c
> > +++ b/fs/ocfs2/xattr.c
> > @@ -1328,20 +1328,21 @@ static int ocfs2_xattr_get(struct inode *inode,
> >void *buffer,
> >size_t buffer_size)
> >  {
> > -   int ret;
> > +   int ret, had_lock;
> > struct buffer_head *di_bh = NULL;
> > +   struct ocfs2_lock_holder oh;
> >  
> > -   ret = ocfs2_inode_lock(inode, _bh, 0);
> > -   if (ret < 0) {
> > -   mlog_errno(ret);
> > -   return ret;
> > +   had_lock = ocfs2_inode_lock_tracker(inode, _bh, 0, );
> > +   if (had_lock < 0) {
> > +   mlog_errno(had_lock);
> > +   return had_lock;
> > }
> > down_read(_I(inode)->ip_xattr_sem);
> > ret = ocfs2_xattr_get_nolock(inode, di_bh, name_index,
> >  name, buffer, buffer_size);
> > up_read(_I(inode)->ip_xattr_sem);
> >  
> > -   ocfs2_inode_unlock(inode, 0);
> > +   ocfs2_inode_unlock_tracker(inode, 0, , had_lock);
> >  
> > brelse(di_bh);
> >  
> > @@ -3537,11 +3538,12 @@ int ocfs2_xattr_set(struct inode *inode,
> >  {
> > struct buffer_head *di_bh = NULL;
> > struct ocfs2_dinode *di;
> > -   int ret, credits, ref_meta = 0, ref_credits = 0;
> > +   int ret, credits, had_lock, ref_meta = 0, ref_credits = 0;
> > struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
> > struct inode *tl_inode = osb->osb_tl_inode;
> > struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, NULL, };
> > struct ocfs2_refcount_tree *ref_tree = NULL;
> > +   struct ocfs2_lock_holder oh;
> >  
> > struct ocfs2_xattr_info xi = {
> > .xi_name_index = name_index,
> > @@ -3572,8 +3574,9 @@ int ocfs2_xattr_set(struct inode *inode,
> > return -ENOMEM;
> > }
> >  
> > -   ret = ocfs2_inode_lock(inode, _bh, 1);
> > -   if (ret < 0) {
> > +   had_lock = 

[Ocfs2-devel] [PATCH 0/11 v1] Fix inheritance of SGID in presence of default ACLs

2017-06-22 Thread Jan Kara
Hello,

this patch set fixes a problem introduced by commit 073931017b49 "posix_acl:
Clear SGID bit when setting file permissions". The problem is that when new
directory 'DIR1' is created in a directory 'DIR0' with SGID bit set, DIR1 is
expected to have SGID bit set (and owning group equal to the owning group of
'DIR0'). However when 'DIR0' also has some default ACLs that 'DIR1' inherits,
setting these ACLs will result in SGID bit on 'DIR1' to get cleared if user is
not member of the owning group.

The problem is fixed by moving posix_acl_update_mode() so that it does not
get called when default ACLs are inherited.

I have created new generic/441 test for this and verified that generic/314,
generic/375, and generic/441 pass for ext2, ext4, btrfs, xfs, ocfs2, reiserfs.

All patches in this series are completely independent so fs maintainers please
pick them up as soon as they get reviewed. I'm leaving for three weeks of
vacation at the end of the week so I won't be able to push this further for
some time.

Honza

___
Ocfs2-devel mailing list
Ocfs2-devel@oss.oracle.com
https://oss.oracle.com/mailman/listinfo/ocfs2-devel


[Ocfs2-devel] [PATCH 07/11] ocfs2: Make ocfs2_set_acl() static

2017-06-22 Thread Jan Kara
The function is never called outside of fs/ocfs2/acl.c.

CC: Joel Becker 
CC: ocfs2-devel@oss.oracle.com
Signed-off-by: Jan Kara 
---
 fs/ocfs2/acl.c | 2 +-
 fs/ocfs2/acl.h | 7 ---
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index dc22ba8c710f..3b9c3638a381 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -221,7 +221,7 @@ static int ocfs2_acl_set_mode(struct inode *inode, struct 
buffer_head *di_bh,
 /*
  * Set the access or default ACL of an inode.
  */
-int ocfs2_set_acl(handle_t *handle,
+static int ocfs2_set_acl(handle_t *handle,
 struct inode *inode,
 struct buffer_head *di_bh,
 int type,
diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h
index 2783a75b3999..7be0bb756286 100644
--- a/fs/ocfs2/acl.h
+++ b/fs/ocfs2/acl.h
@@ -28,13 +28,6 @@ struct ocfs2_acl_entry {
 
 struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type);
 int ocfs2_iop_set_acl(struct inode *inode, struct posix_acl *acl, int type);
-int ocfs2_set_acl(handle_t *handle,
-struct inode *inode,
-struct buffer_head *di_bh,
-int type,
-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 *);
 extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *,
  struct buffer_head *, struct buffer_head *,
-- 
2.12.3


___
Ocfs2-devel mailing list
Ocfs2-devel@oss.oracle.com
https://oss.oracle.com/mailman/listinfo/ocfs2-devel


[Ocfs2-devel] [PATCH 08/11] ocfs2: Don't clear SGID when inheriting ACLs

2017-06-22 Thread Jan Kara
When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit
set, DIR1 is expected to have SGID bit set (and owning group equal to
the owning group of 'DIR0'). However when 'DIR0' also has some default
ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on
'DIR1' to get cleared if user is not member of the owning group.

Fix the problem by moving posix_acl_update_mode() out of ocfs2_set_acl()
into ocfs2_iop_set_acl(). That way the function will not be called when
inheriting ACLs which is what we want as it prevents SGID bit clearing
and the mode has been properly set by posix_acl_create() anyway. Also
posix_acl_chmod() that is calling ocfs2_set_acl() takes care of updating
mode itself.

Fixes: 073931017b49d9458aa351605b43a7e34598caef
CC: sta...@vger.kernel.org
CC: Joel Becker 
CC: ocfs2-devel@oss.oracle.com
Signed-off-by: Jan Kara 
---
 fs/ocfs2/acl.c | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index 3b9c3638a381..40b5cc97f7b0 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -240,18 +240,6 @@ static int ocfs2_set_acl(handle_t *handle,
switch (type) {
case ACL_TYPE_ACCESS:
name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
-   if (acl) {
-   umode_t mode;
-
-   ret = posix_acl_update_mode(inode, , );
-   if (ret)
-   return ret;
-
-   ret = ocfs2_acl_set_mode(inode, di_bh,
-handle, mode);
-   if (ret)
-   return ret;
-   }
break;
case ACL_TYPE_DEFAULT:
name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT;
@@ -289,7 +277,19 @@ int ocfs2_iop_set_acl(struct inode *inode, struct 
posix_acl *acl, int type)
had_lock = ocfs2_inode_lock_tracker(inode, , 1, );
if (had_lock < 0)
return had_lock;
+   if (type == ACL_TYPE_ACCESS && acl) {
+   umode_t mode;
+
+   status = posix_acl_update_mode(inode, , );
+   if (status)
+   goto unlock;
+
+   status = ocfs2_acl_set_mode(inode, bh, NULL, mode);
+   if (status)
+   goto unlock;
+   }
status = ocfs2_set_acl(NULL, inode, bh, type, acl, NULL, NULL);
+unlock:
ocfs2_inode_unlock_tracker(inode, 1, , had_lock);
brelse(bh);
return status;
-- 
2.12.3


___
Ocfs2-devel mailing list
Ocfs2-devel@oss.oracle.com
https://oss.oracle.com/mailman/listinfo/ocfs2-devel


Re: [Ocfs2-devel] [PATCH v2] ocfs2: fix deadlock caused by recursive locking in xattr

2017-06-22 Thread Joseph Qi
Looks good.
Reviewed-by: Joseph Qi 

Thanks,
Joseph

On 17/6/22 09:47, Eric Ren wrote:
> Another deadlock path caused by recursive locking is reported.
> This kind of issue was introduced since commit 743b5f1434f5 ("ocfs2:
> take inode lock in ocfs2_iop_set/get_acl()"). Two deadlock paths
> have been fixed by commit b891fa5024a9 ("ocfs2: fix deadlock issue when
> taking inode lock at vfs entry points"). Yes, we intend to fix this
> kind of case in incremental way, because it's hard to find out all
> possible paths at once.
> 
> This one can be reproduced like this. On node1, cp a large file from
> home directory to ocfs2 mountpoint. While on node2, run setfacl/getfacl.
> Both nodes will hang up there. The backtraces:
> 
> On node1:
> [] __ocfs2_cluster_lock.isra.39+0x357/0x740 [ocfs2]
> [] ocfs2_inode_lock_full_nested+0x17d/0x840 [ocfs2]
> [] ocfs2_write_begin+0x43/0x1a0 [ocfs2]
> [] generic_perform_write+0xa9/0x180
> [] __generic_file_write_iter+0x1aa/0x1d0
> [] ocfs2_file_write_iter+0x4f4/0xb40 [ocfs2]
> [] __vfs_write+0xc3/0x130
> [] vfs_write+0xb1/0x1a0
> [] SyS_write+0x46/0xa0
> 
> On node2:
> [] __ocfs2_cluster_lock.isra.39+0x357/0x740 [ocfs2]
> [] ocfs2_inode_lock_full_nested+0x17d/0x840 [ocfs2]
> [] ocfs2_xattr_set+0x12e/0xe80 [ocfs2]
> [] ocfs2_set_acl+0x22d/0x260 [ocfs2]
> [] ocfs2_iop_set_acl+0x65/0xb0 [ocfs2]
> [] set_posix_acl+0x75/0xb0
> [] posix_acl_xattr_set+0x49/0xa0
> [] __vfs_setxattr+0x69/0x80
> [] __vfs_setxattr_noperm+0x72/0x1a0
> [] vfs_setxattr+0xa7/0xb0
> [] setxattr+0x12d/0x190
> [] path_setxattr+0x9f/0xb0
> [] SyS_setxattr+0x14/0x20
> 
> Fixes this one by using ocfs2_inode_{lock|unlock}_tracker, which is
> exported by commit 439a36b8ef38 ("ocfs2/dlmglue: prepare tracking
> logic to avoid recursive cluster lock").
> 
> Changes since v1:
> - Revised git commit description style in commit log.
> 
> Reported-by: Thomas Voegtle 
> Tested-by: Thomas Voegtle 
> Signed-off-by: Eric Ren 
> ---
>  fs/ocfs2/dlmglue.c |  4 
>  fs/ocfs2/xattr.c   | 23 +--
>  2 files changed, 17 insertions(+), 10 deletions(-)
> 
> diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
> index 3b7c937..4689940 100644
> --- a/fs/ocfs2/dlmglue.c
> +++ b/fs/ocfs2/dlmglue.c
> @@ -2591,6 +2591,10 @@ void ocfs2_inode_unlock_tracker(struct inode *inode,
>   struct ocfs2_lock_res *lockres;
>  
>   lockres = _I(inode)->ip_inode_lockres;
> + /* had_lock means that the currect process already takes the cluster
> +  * lock previously. If had_lock is 1, we have nothing to do here, and
> +  * it will get unlocked where we got the lock.
> +  */
>   if (!had_lock) {
>   ocfs2_remove_holder(lockres, oh);
>   ocfs2_inode_unlock(inode, ex);
> diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
> index 3c5384d..f70c377 100644
> --- a/fs/ocfs2/xattr.c
> +++ b/fs/ocfs2/xattr.c
> @@ -1328,20 +1328,21 @@ static int ocfs2_xattr_get(struct inode *inode,
>  void *buffer,
>  size_t buffer_size)
>  {
> - int ret;
> + int ret, had_lock;
>   struct buffer_head *di_bh = NULL;
> + struct ocfs2_lock_holder oh;
>  
> - ret = ocfs2_inode_lock(inode, _bh, 0);
> - if (ret < 0) {
> - mlog_errno(ret);
> - return ret;
> + had_lock = ocfs2_inode_lock_tracker(inode, _bh, 0, );
> + if (had_lock < 0) {
> + mlog_errno(had_lock);
> + return had_lock;
>   }
>   down_read(_I(inode)->ip_xattr_sem);
>   ret = ocfs2_xattr_get_nolock(inode, di_bh, name_index,
>name, buffer, buffer_size);
>   up_read(_I(inode)->ip_xattr_sem);
>  
> - ocfs2_inode_unlock(inode, 0);
> + ocfs2_inode_unlock_tracker(inode, 0, , had_lock);
>  
>   brelse(di_bh);
>  
> @@ -3537,11 +3538,12 @@ int ocfs2_xattr_set(struct inode *inode,
>  {
>   struct buffer_head *di_bh = NULL;
>   struct ocfs2_dinode *di;
> - int ret, credits, ref_meta = 0, ref_credits = 0;
> + int ret, credits, had_lock, ref_meta = 0, ref_credits = 0;
>   struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
>   struct inode *tl_inode = osb->osb_tl_inode;
>   struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, NULL, };
>   struct ocfs2_refcount_tree *ref_tree = NULL;
> + struct ocfs2_lock_holder oh;
>  
>   struct ocfs2_xattr_info xi = {
>   .xi_name_index = name_index,
> @@ -3572,8 +3574,9 @@ int ocfs2_xattr_set(struct inode *inode,
>   return -ENOMEM;
>   }
>  
> - ret = ocfs2_inode_lock(inode, _bh, 1);
> - if (ret < 0) {
> + had_lock = ocfs2_inode_lock_tracker(inode, _bh, 1, );
> + if (had_lock < 0) {
> + ret = had_lock;
>   mlog_errno(ret);
>   goto cleanup_nolock;
>   }
> @@ -3670,7 +3673,7 @@ int ocfs2_xattr_set(struct inode *inode,
>   if (ret)
>