aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dlm/dlmmaster.c
diff options
context:
space:
mode:
authorSunil Mushran <sunil.mushran@oracle.com>2008-12-16 18:49:23 -0500
committerMark Fasheh <mfasheh@suse.com>2009-01-05 11:40:35 -0500
commit7b791d68562e4ce5ab57cbacb10a1ad4ee33956e (patch)
tree7ecff8f244995c4d16dff21f2a61c9946ab67435 /fs/ocfs2/dlm/dlmmaster.c
parentb0d4f817ba5de8adb875ace594554a96d7737710 (diff)
ocfs2/dlm: Fix race during lockres mastery
dlm_get_lock_resource() is supposed to return a lock resource with a proper master. If multiple concurrent threads attempt to lookup the lockres for the same lockid while the lock mastery in underway, one or more threads are likely to return a lockres without a proper master. This patch makes the threads wait in dlm_get_lock_resource() while the mastery is underway, ensuring all threads return the lockres with a proper master. This issue is known to be limited to users using the flock() syscall. For all other fs operations, the ocfs2 dlmglue layer serializes the dlm op for each lockid. Users encountering this bug will see flock() return EINVAL and dmesg have the following error: ERROR: Dlm error "DLM_BADARGS" while calling dlmlock on resource <LOCKID>: bad api args Reported-by: Coly Li <coyli@suse.de> Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/dlm/dlmmaster.c')
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index cbf3abe24cdb..54e182a27caf 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -732,14 +732,21 @@ lookup:
732 if (tmpres) { 732 if (tmpres) {
733 int dropping_ref = 0; 733 int dropping_ref = 0;
734 734
735 spin_unlock(&dlm->spinlock);
736
735 spin_lock(&tmpres->spinlock); 737 spin_lock(&tmpres->spinlock);
738 /* We wait for the other thread that is mastering the resource */
739 if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
740 __dlm_wait_on_lockres(tmpres);
741 BUG_ON(tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN);
742 }
743
736 if (tmpres->owner == dlm->node_num) { 744 if (tmpres->owner == dlm->node_num) {
737 BUG_ON(tmpres->state & DLM_LOCK_RES_DROPPING_REF); 745 BUG_ON(tmpres->state & DLM_LOCK_RES_DROPPING_REF);
738 dlm_lockres_grab_inflight_ref(dlm, tmpres); 746 dlm_lockres_grab_inflight_ref(dlm, tmpres);
739 } else if (tmpres->state & DLM_LOCK_RES_DROPPING_REF) 747 } else if (tmpres->state & DLM_LOCK_RES_DROPPING_REF)
740 dropping_ref = 1; 748 dropping_ref = 1;
741 spin_unlock(&tmpres->spinlock); 749 spin_unlock(&tmpres->spinlock);
742 spin_unlock(&dlm->spinlock);
743 750
744 /* wait until done messaging the master, drop our ref to allow 751 /* wait until done messaging the master, drop our ref to allow
745 * the lockres to be purged, start over. */ 752 * the lockres to be purged, start over. */