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          0x00000010
>  #define DLM_LOCK_RES_MIGRATING            0x00000020
>  #define DLM_LOCK_RES_DROPPING_REF         0x00000040
> +#define DLM_LOCK_RES_IN_USE               0x00000100
>  #define DLM_LOCK_RES_BLOCK_DIRTY          0x00001000
>  #define DLM_LOCK_RES_SETREF_INPROG        0x00002000
>  
> diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
> index 7333377..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

Reply via email to