diff options
| author | Anand Avati <avati@gluster.com> | 2011-10-22 09:48:17 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vijay@gluster.com> | 2011-10-28 05:02:03 -0700 | 
| commit | 90d820d193c06efdae0a7e513faaadffb2bfdafd (patch) | |
| tree | 837f7579a20a44dba5204f4f958bf84907b39800 | |
| parent | ea4cd6ff18bb811b053b8fc6bcef7d6377dac30b (diff) | |
locks: perform inode_ref of pl_update_refkeeper outside locked region
Performing inode_ref inside the critical section of pl_update_refkeeper
(around pl_inode_t->mutex) causes a deadlock with inode_table_t->lock.
The other thread (process state dump) holds the inode_table_t->lock first
to loop over inodes and then while dumping an inode's lock context, tries
to acquire pl_inode_t->mutex thereby completing the deadlock.
The fix is to perform inode_ref outside the critical section in
pl_update_refkeeper
Change-Id: I689ab4a9b46b36287740279fdec6159182c86119
BUG: 3753
Reviewed-on: http://review.gluster.com/628
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Krishnan Parthasarathi <kp@gluster.com>
| -rw-r--r-- | xlators/features/locks/src/common.c | 7 | 
1 files changed, 6 insertions, 1 deletions
diff --git a/xlators/features/locks/src/common.c b/xlators/features/locks/src/common.c index 4b6a810fde8..ab1542b62e4 100644 --- a/xlators/features/locks/src/common.c +++ b/xlators/features/locks/src/common.c @@ -400,6 +400,7 @@ pl_update_refkeeper (xlator_t *this, inode_t *inode)          pl_inode_t *pl_inode  = NULL;          int         is_empty  = 0;          int         need_unref = 0; +        int         need_ref = 0;          pl_inode = pl_inode_get (this, inode); @@ -413,13 +414,17 @@ pl_update_refkeeper (xlator_t *this, inode_t *inode)                  }                  if (!is_empty && !pl_inode->refkeeper) { -                        pl_inode->refkeeper = inode_ref (inode); +                        need_ref = 1; +                        pl_inode->refkeeper = inode;                  }          }          pthread_mutex_unlock (&pl_inode->mutex);          if (need_unref)                  inode_unref (inode); + +        if (need_ref) +                inode_ref (inode);  }  | 
