Re: [Ocfs2-devel] [PATCH 1/1] ocfs2: o2dlm fix race in purge lockres and newlock (orabug 9094491)

2010-06-14 Thread Srinivas Eeda
Please ignore this patch. I'll resend this patch along with dlm purge 
lockres for completeness.

On 6/9/2010 7:07 PM, Srinivas Eeda wrote:
 dlm_thread sends a deref message to the master node. At the same time,
 another thread sends a new lock request to the master node.
 Since dlm_thread wouldn't know about it, it would unhash the lockres
 after it gets the response. lock request AST would then won't find
 the lockres and hence BUGs.

 The fix is to add new state DLM_LOCK_RES_IN_USE which would prevent
 dlm_thread from purging the lockres and/or unhashing lockres.

 Signed-off-by: Srinivas Eeda srinivas.e...@oracle.com
 ---
  fs/ocfs2/dlm/dlmcommon.h |1 +
  fs/ocfs2/dlm/dlmlock.c   |4 
  fs/ocfs2/dlm/dlmmaster.c |5 -
  fs/ocfs2/dlm/dlmthread.c |4 +++-
  4 files changed, 12 insertions(+), 2 deletions(-)

 diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
 index 0102be3..0290612 100644
 --- a/fs/ocfs2/dlm/dlmcommon.h
 +++ b/fs/ocfs2/dlm/dlmcommon.h
 @@ -280,6 +280,7 @@ static inline void __dlm_set_joining_node(struct dlm_ctxt 
 *dlm,
  #define DLM_LOCK_RES_IN_PROGRESS  0x0010
  #define DLM_LOCK_RES_MIGRATING0x0020
  #define DLM_LOCK_RES_DROPPING_REF 0x0040
 +#define DLM_LOCK_RES_IN_USE   0x0100
  #define DLM_LOCK_RES_BLOCK_DIRTY  0x1000
  #define DLM_LOCK_RES_SETREF_INPROG0x2000
  
 diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
 index 777..501ac40 100644
 --- a/fs/ocfs2/dlm/dlmlock.c
 +++ b/fs/ocfs2/dlm/dlmlock.c
 @@ -134,6 +134,8 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt 
 *dlm,
   if (status != DLM_NORMAL 
   lock-ml.node != dlm-node_num) {
   /* erf.  state changed after lock was dropped. */
 + /* DLM_LOCK_RES_IN_USE is set in dlm_get_lock_resource */
 + res-state = ~DLM_LOCK_RES_IN_USE;
   spin_unlock(res-spinlock);
   dlm_error(status);
   return status;
 @@ -180,6 +182,7 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt 
 *dlm,
   kick_thread = 1;
   }
   }
 + res-state = ~DLM_LOCK_RES_IN_USE;
   /* reduce the inflight count, this may result in the lockres
* being purged below during calc_usage */
   if (lock-ml.node == dlm-node_num)
 @@ -246,6 +249,7 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt 
 *dlm,
  
   spin_lock(res-spinlock);
   res-state = ~DLM_LOCK_RES_IN_PROGRESS;
 + res-state = ~DLM_LOCK_RES_IN_USE;
   lock-lock_pending = 0;
   if (status != DLM_NORMAL) {
   if (status == DLM_RECOVERING 
 diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
 index 9289b43..f0f2d97 100644
 --- a/fs/ocfs2/dlm/dlmmaster.c
 +++ b/fs/ocfs2/dlm/dlmmaster.c
 @@ -719,6 +719,7 @@ lookup:
   if (tmpres) {
   int dropping_ref = 0;
  
 + tmpres-state |= DLM_LOCK_RES_IN_USE;
   spin_unlock(dlm-spinlock);
  
   spin_lock(tmpres-spinlock);
 @@ -731,8 +732,10 @@ lookup:
   if (tmpres-owner == dlm-node_num) {
   BUG_ON(tmpres-state  DLM_LOCK_RES_DROPPING_REF);
   dlm_lockres_grab_inflight_ref(dlm, tmpres);
 - } else if (tmpres-state  DLM_LOCK_RES_DROPPING_REF)
 + } else if (tmpres-state  DLM_LOCK_RES_DROPPING_REF) {
 + tmpres-state = ~DLM_LOCK_RES_IN_USE;
   dropping_ref = 1;
 + }
   spin_unlock(tmpres-spinlock);
  
   /* wait until done messaging the master, drop our ref to allow
 diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c
 index 11a6d1f..b2315cb 100644
 --- a/fs/ocfs2/dlm/dlmthread.c
 +++ b/fs/ocfs2/dlm/dlmthread.c
 @@ -93,6 +93,7 @@ int __dlm_lockres_has_locks(struct dlm_lock_resource *res)
  int __dlm_lockres_unused(struct dlm_lock_resource *res)
  {
   if (!__dlm_lockres_has_locks(res) 
 + !(res-state  DLM_LOCK_RES_IN_USE) 
   (list_empty(res-dirty)  !(res-state  DLM_LOCK_RES_DIRTY))) {
   /* try not to scan the bitmap unless the first two
* conditions are already true */
 @@ -222,7 +223,8 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
   } else
   spin_unlock(res-spinlock);
  
 - __dlm_unhash_lockres(res);
 + if (__dlm_lockres_unused(res))
 + __dlm_unhash_lockres(res);
  
   /* lockres is not in the hash now.  drop the flag and wake up
* any processes waiting in dlm_get_lock_resource. */
   

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


[Ocfs2-devel] [PATCH 1/1] ocfs2: o2dlm fix race in purge lockres and newlock (orabug 9094491)

2010-06-09 Thread Srinivas Eeda
dlm_thread sends a deref message to the master node. At the same time,
another thread sends a new lock request to the master node.
Since dlm_thread wouldn't know about it, it would unhash the lockres
after it gets the response. lock request AST would then won't find
the lockres and hence BUGs.

The fix is to add new state DLM_LOCK_RES_IN_USE which would prevent
dlm_thread from purging the lockres and/or unhashing lockres.

Signed-off-by: Srinivas Eeda srinivas.e...@oracle.com
---
 fs/ocfs2/dlm/dlmcommon.h |1 +
 fs/ocfs2/dlm/dlmlock.c   |4 
 fs/ocfs2/dlm/dlmmaster.c |5 -
 fs/ocfs2/dlm/dlmthread.c |4 +++-
 4 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index 0102be3..0290612 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -280,6 +280,7 @@ static inline void __dlm_set_joining_node(struct dlm_ctxt 
*dlm,
 #define DLM_LOCK_RES_IN_PROGRESS  0x0010
 #define DLM_LOCK_RES_MIGRATING0x0020
 #define DLM_LOCK_RES_DROPPING_REF 0x0040
+#define DLM_LOCK_RES_IN_USE   0x0100
 #define DLM_LOCK_RES_BLOCK_DIRTY  0x1000
 #define DLM_LOCK_RES_SETREF_INPROG0x2000
 
diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
index 777..501ac40 100644
--- a/fs/ocfs2/dlm/dlmlock.c
+++ b/fs/ocfs2/dlm/dlmlock.c
@@ -134,6 +134,8 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt *dlm,
if (status != DLM_NORMAL 
lock-ml.node != dlm-node_num) {
/* erf.  state changed after lock was dropped. */
+   /* DLM_LOCK_RES_IN_USE is set in dlm_get_lock_resource */
+   res-state = ~DLM_LOCK_RES_IN_USE;
spin_unlock(res-spinlock);
dlm_error(status);
return status;
@@ -180,6 +182,7 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt *dlm,
kick_thread = 1;
}
}
+   res-state = ~DLM_LOCK_RES_IN_USE;
/* reduce the inflight count, this may result in the lockres
 * being purged below during calc_usage */
if (lock-ml.node == dlm-node_num)
@@ -246,6 +249,7 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm,
 
spin_lock(res-spinlock);
res-state = ~DLM_LOCK_RES_IN_PROGRESS;
+   res-state = ~DLM_LOCK_RES_IN_USE;
lock-lock_pending = 0;
if (status != DLM_NORMAL) {
if (status == DLM_RECOVERING 
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 9289b43..f0f2d97 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -719,6 +719,7 @@ lookup:
if (tmpres) {
int dropping_ref = 0;
 
+   tmpres-state |= DLM_LOCK_RES_IN_USE;
spin_unlock(dlm-spinlock);
 
spin_lock(tmpres-spinlock);
@@ -731,8 +732,10 @@ lookup:
if (tmpres-owner == dlm-node_num) {
BUG_ON(tmpres-state  DLM_LOCK_RES_DROPPING_REF);
dlm_lockres_grab_inflight_ref(dlm, tmpres);
-   } else if (tmpres-state  DLM_LOCK_RES_DROPPING_REF)
+   } else if (tmpres-state  DLM_LOCK_RES_DROPPING_REF) {
+   tmpres-state = ~DLM_LOCK_RES_IN_USE;
dropping_ref = 1;
+   }
spin_unlock(tmpres-spinlock);
 
/* wait until done messaging the master, drop our ref to allow
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c
index 11a6d1f..b2315cb 100644
--- a/fs/ocfs2/dlm/dlmthread.c
+++ b/fs/ocfs2/dlm/dlmthread.c
@@ -93,6 +93,7 @@ int __dlm_lockres_has_locks(struct dlm_lock_resource *res)
 int __dlm_lockres_unused(struct dlm_lock_resource *res)
 {
if (!__dlm_lockres_has_locks(res) 
+   !(res-state  DLM_LOCK_RES_IN_USE) 
(list_empty(res-dirty)  !(res-state  DLM_LOCK_RES_DIRTY))) {
/* try not to scan the bitmap unless the first two
 * conditions are already true */
@@ -222,7 +223,8 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
} else
spin_unlock(res-spinlock);
 
-   __dlm_unhash_lockres(res);
+   if (__dlm_lockres_unused(res))
+   __dlm_unhash_lockres(res);
 
/* lockres is not in the hash now.  drop the flag and wake up
 * any processes waiting in dlm_get_lock_resource. */
-- 
1.5.6.5


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