Re: [Ocfs2-devel] [PATCH 15/17] fs/ocfs2/dlm: Add missing spin_unlock

2010-06-15 Thread Joel Becker
On Wed, May 26, 2010 at 05:58:53PM +0200, Julia Lawall wrote:
 From: Julia Lawall ju...@diku.dk
 
 Add a spin_unlock missing on the error path.  Unlock as in the other code
 that leads to the leave label.
 
 The semantic match that finds this problem is as follows:
 (http://coccinelle.lip6.fr/)
 
 // smpl
 @@
 expression E1;
 @@
 
 * spin_lock(E1,...);
   +... when != E1
   if (...) {
 ... when != E1
 *   return ...;
   }
   ...+
 * spin_unlock(E1,...);
 // /smpl
 
 Signed-off-by: Julia Lawall ju...@diku.dk

This patch is now in the 'fixes' branch of ocfs2.git.

Joel

-- 

In the arms of the angel, fly away from here,
 From this dark, cold hotel room and the endlessness that you fear.
 You are pulled from the wreckage of your silent reverie.
 In the arms of the angel, may you find some comfort here.

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.bec...@oracle.com
Phone: (650) 506-8127

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


Re: [Ocfs2-devel] [PATCH] ocfs2: Move orphan scan work to ocfs2_wq.

2010-06-15 Thread Joel Becker
On Fri, May 28, 2010 at 02:22:59PM +0800, Tao Ma wrote:
 We used to let orphan scan work in the default work queue,
 but there is a corner case which will make the system deadlock.
 The scenario is like this:
 1. set heartbeat threadshold to 200. this will allow us to have a
great chance to have a orphan scan work before our quorum decision.
 2. mount node 1.
 3. after 1~2 minutes, mount node 2(in order to make the bug easier
to reproduce, better add maxcpus=1 to kernel command line).
 4. node 1 do orphan scan work.
 5. node 2 do orphan scan work.
 6. node 1 do orphan scan work. After this, node 1 hold the orphan scan
lock while node 2 know node 1 is the master.
 7. ifdown eth2 in node 2(eth2 is what we do ocfs2 interconnection).
 
 Now when node 2 begins orphan scan, the system queue is blocked.
 
 The root cause is that both orphan scan work and quorum decision work
 will use the system event work queue. orphan scan has a chance of
 blocking the event work queue(in dlm_wait_for_node_death) so that there
 is no chance for quorum decision work to proceed.
 
 This patch resolve it by moving orphan scan work to ocfs2_wq.
 
 Signed-off-by: Tao Ma tao...@oracle.com

This patch is now in the 'fixes' branch of ocfs2.git

Joel

-- 

The one important thing i have learned over the years is the
 difference between taking one's work seriously and taking one's self
 seriously.  The first is imperative and the second is disastrous.
-Margot Fonteyn

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.bec...@oracle.com
Phone: (650) 506-8127

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


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

2010-06-15 Thread Srinivas Eeda
This patch fixes the following hole.
dlmlock tries to create a new lock on a lockres that is on purge list. It calls
dlm_get_lockresource and later adds a lock to blocked list. But in this window,
dlm_thread can purge the lockres and unhash it. This will cause a BUG, as when
the AST comes back from the master lockres is not found

This patch marks the lockres with a new state DLM_LOCK_RES_IN_USE which would
protect lockres from dlm_thread purging it.

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 |1 +
 4 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index 0102be3..6cf3c08 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -279,6 +279,7 @@ static inline void __dlm_set_joining_node(struct dlm_ctxt 
*dlm,
 #define DLM_LOCK_RES_DIRTY0x0008
 #define DLM_LOCK_RES_IN_PROGRESS  0x0010
 #define DLM_LOCK_RES_MIGRATING0x0020
+#define DLM_LOCK_RES_IN_USE   0x0100
 #define DLM_LOCK_RES_DROPPING_REF 0x0040
 #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 fb0be6c..2b82e0b 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 */
-- 
1.5.6.5


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


Re: [Ocfs2-devel] [PATCH] ocfs2/dlm: check dlm_state under spinlock

2010-06-15 Thread Srinivas Eeda
The lock order in this code causes dead lock, not caused by your patch. 
The lock order in dlm_query_join_handler is

dlm_domain_lock
-dlm-spinlock

dead locks with ..

dlm_lockres_put calls dlm_lockres_release while holding dlm-spinlock 
which calls dlm_put which gets dlm_domain_lock. So the spin lock order 
here is
dlm-spinlock
- dlm_domain_lock


On 6/15/2010 9:08 PM, Wengang Wang wrote:
 We should check dlm-dlm_state under dlm-spinlock though maybe in this case 
 it
 doesn't hurt.

 Signed-off-by: Wengang Wang wen.gang.w...@oracle.com
 ---
  fs/ocfs2/dlm/dlmdomain.c |   13 ++---
  1 files changed, 6 insertions(+), 7 deletions(-)

 diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
 index 6b5a492..ab82add 100644
 --- a/fs/ocfs2/dlm/dlmdomain.c
 +++ b/fs/ocfs2/dlm/dlmdomain.c
 @@ -796,7 +796,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, 
 u32 len, void *data,
   spin_lock(dlm_domain_lock);
   dlm = __dlm_lookup_domain_full(query-domain, query-name_len);
   if (!dlm)
 - goto unlock_respond;
 + goto unlock_domain_respond;
  
   /*
* There is a small window where the joining node may not see the
 @@ -811,7 +811,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, 
 u32 len, void *data,
have node %u in its nodemap\n,
query-node_idx, nodenum);
   packet.code = JOIN_DISALLOW;
 - goto unlock_respond;
 + goto unlock_domain_respond;
   }
   }
   nodenum++;
 @@ -821,9 +821,9 @@ static int dlm_query_join_handler(struct o2net_msg *msg, 
 u32 len, void *data,
* to be put in someone's domain map.
* Also, explicitly disallow joining at certain troublesome
* times (ie. during recovery). */
 - if (dlm  dlm-dlm_state != DLM_CTXT_LEAVING) {
 + spin_lock(dlm-spinlock);
 + if (dlm-dlm_state != DLM_CTXT_LEAVING) {
   int bit = query-node_idx;
 - spin_lock(dlm-spinlock);
  
   if (dlm-dlm_state == DLM_CTXT_NEW 
   dlm-joining_node == DLM_LOCK_RES_OWNER_UNKNOWN) {
 @@ -869,10 +869,9 @@ static int dlm_query_join_handler(struct o2net_msg *msg, 
 u32 len, void *data,
   __dlm_set_joining_node(dlm, query-node_idx);
   }
   }
 -
 - spin_unlock(dlm-spinlock);
   }
 -unlock_respond:
 + spin_unlock(dlm-spinlock);
 +unlock_domain_respond:
   spin_unlock(dlm_domain_lock);
  
  respond:
   

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


Re: [Ocfs2-devel] [PATCH] ocfs2/dlm: check dlm_state under spinlock

2010-06-15 Thread Wengang Wang
Thanks for review :)

The second path has problem. I think the correct order should be dlm_domain_lock
and then dlm-spinlock.

I will try to fix it.

regards,
wengang.
On 10-06-15 22:00, Srinivas Eeda wrote:
 The lock order in this code causes dead lock, not caused by your
 patch. The lock order in dlm_query_join_handler is
 
 dlm_domain_lock
-dlm-spinlock
 
 dead locks with ..
 
 dlm_lockres_put calls dlm_lockres_release while holding
 dlm-spinlock which calls dlm_put which gets dlm_domain_lock. So the
 spin lock order here is
 dlm-spinlock
- dlm_domain_lock
 
 
 On 6/15/2010 9:08 PM, Wengang Wang wrote:
 We should check dlm-dlm_state under dlm-spinlock though maybe in this case 
 it
 doesn't hurt.
 
 Signed-off-by: Wengang Wang wen.gang.w...@oracle.com
 ---
  fs/ocfs2/dlm/dlmdomain.c |   13 ++---
  1 files changed, 6 insertions(+), 7 deletions(-)
 
 diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
 index 6b5a492..ab82add 100644
 --- a/fs/ocfs2/dlm/dlmdomain.c
 +++ b/fs/ocfs2/dlm/dlmdomain.c
 @@ -796,7 +796,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, 
 u32 len, void *data,
  spin_lock(dlm_domain_lock);
  dlm = __dlm_lookup_domain_full(query-domain, query-name_len);
  if (!dlm)
 -goto unlock_respond;
 +goto unlock_domain_respond;
  /*
   * There is a small window where the joining node may not see the
 @@ -811,7 +811,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, 
 u32 len, void *data,
   have node %u in its nodemap\n,
   query-node_idx, nodenum);
  packet.code = JOIN_DISALLOW;
 -goto unlock_respond;
 +goto unlock_domain_respond;
  }
  }
  nodenum++;
 @@ -821,9 +821,9 @@ static int dlm_query_join_handler(struct o2net_msg *msg, 
 u32 len, void *data,
   * to be put in someone's domain map.
   * Also, explicitly disallow joining at certain troublesome
   * times (ie. during recovery). */
 -if (dlm  dlm-dlm_state != DLM_CTXT_LEAVING) {
 +spin_lock(dlm-spinlock);
 +if (dlm-dlm_state != DLM_CTXT_LEAVING) {
  int bit = query-node_idx;
 -spin_lock(dlm-spinlock);
  if (dlm-dlm_state == DLM_CTXT_NEW 
  dlm-joining_node == DLM_LOCK_RES_OWNER_UNKNOWN) {
 @@ -869,10 +869,9 @@ static int dlm_query_join_handler(struct o2net_msg 
 *msg, u32 len, void *data,
  __dlm_set_joining_node(dlm, query-node_idx);
  }
  }
 -
 -spin_unlock(dlm-spinlock);
  }
 -unlock_respond:
 +spin_unlock(dlm-spinlock);
 +unlock_domain_respond:
  spin_unlock(dlm_domain_lock);
  respond:

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