[Cluster-devel] [GFS2 PATCH 1/2] GFS2: Introduce EXSH (exclusively shared on one node)

Steven Whitehouse swhiteho at redhat.com
Wed Apr 18 19:13:50 UTC 2018


Hi,


On 18/04/18 17:58, Bob Peterson wrote:
> This patch is a first step in rgrp sharing. It allows for a new
> type of glock mode called EXSH, which stands for a lock that is
> Exclusive to one node, but shared amongst processes on that node.
> Like a Shared glock, multiple processes may acquire the lock in
> EXSH mode at the same time, provided they're all on the same
> node. All other nodes will see this as an EX lock. In other words,
> to the DLM, the lock is granted to the node in EX, but at the
> glock layer, they may be shared.
>
> For now, there are no users of the new EXSH glock mode.
> Future patches will use it to improve performance with rgrp sharing.
Is there a reason why we cannot just add a lock flag here, rather than 
requiring a new lock state? That should make it a much smaller change, 
and leaves the lock state always reflecting the cluster lock state,

Steve.

>
> Signed-off-by: Bob Peterson <rpeterso at redhat.com>
> ---
>   fs/gfs2/glock.c      | 12 +++++++++++-
>   fs/gfs2/glock.h      | 16 ++++++++++++----
>   fs/gfs2/incore.h     |  8 ++++----
>   fs/gfs2/lock_dlm.c   |  5 ++++-
>   fs/gfs2/trace_gfs2.h |  2 ++
>   5 files changed, 33 insertions(+), 10 deletions(-)
>
> diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
> index 097bd3c0f270..3e3c3e7fada8 100644
> --- a/fs/gfs2/glock.c
> +++ b/fs/gfs2/glock.c
> @@ -287,7 +287,7 @@ static inline int may_grant(const struct gfs2_glock *gl, const struct gfs2_holde
>   		return 1;
>   	if (gh->gh_flags & GL_EXACT)
>   		return 0;
> -	if (gl->gl_state == LM_ST_EXCLUSIVE) {
> +	if (gl->gl_state == LM_ST_EXCLUSIVE || gl->gl_state == LM_ST_EXSH) {
>   		if (gh->gh_state == LM_ST_SHARED && gh_head->gh_state == LM_ST_SHARED)
>   			return 1;
>   		if (gh->gh_state == LM_ST_DEFERRED && gh_head->gh_state == LM_ST_DEFERRED)
> @@ -453,6 +453,13 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
>   	unsigned state = ret & LM_OUT_ST_MASK;
>   	int rv;
>   
> +	/**
> +	 * If we asked DLM to grant EX, it might have been EX or EXSH.
> +	 * Here we adjust to compensate for the difference between them.
> +	 */
> +	if (state == LM_ST_EXCLUSIVE && gl->gl_target == LM_ST_EXSH)
> +		state = LM_ST_EXSH;
> +
>   	spin_lock(&gl->gl_lockref.lock);
>   	trace_gfs2_glock_state_change(gl, state);
>   	state_change(gl, state);
> @@ -557,6 +564,7 @@ __acquires(&gl->gl_lockref.lock)
>   	set_bit(GLF_BLOCKING, &gl->gl_flags);
>   	if ((gl->gl_req == LM_ST_UNLOCKED) ||
>   	    (gl->gl_state == LM_ST_EXCLUSIVE) ||
> +	    (gl->gl_state == LM_ST_EXSH) ||
>   	    (lck_flags & (LM_FLAG_TRY|LM_FLAG_TRY_1CB)))
>   		clear_bit(GLF_BLOCKING, &gl->gl_flags);
>   	spin_unlock(&gl->gl_lockref.lock);
> @@ -1663,6 +1671,8 @@ static const char *state2str(unsigned state)
>   		return "DF";
>   	case LM_ST_EXCLUSIVE:
>   		return "EX";
> +	case LM_ST_EXSH:
> +		return "ES";
>   	}
>   	return "??";
>   }
> diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
> index 5e12220cc0c2..351df3905e70 100644
> --- a/fs/gfs2/glock.h
> +++ b/fs/gfs2/glock.h
> @@ -45,12 +45,15 @@ enum {
>    *
>    * SHARED is compatible with SHARED, not with DEFERRED or EX.
>    * DEFERRED is compatible with DEFERRED, not with SHARED or EX.
> + * EXSH looks like an EX lock to DLM and thus, all other nodes, but
> + *      to the node to which it's granted, it acts like an SHARED lock.
>    */
>   
>   #define LM_ST_UNLOCKED		0
>   #define LM_ST_EXCLUSIVE		1
>   #define LM_ST_DEFERRED		2
>   #define LM_ST_SHARED		3
> +#define LM_ST_EXSH		4 /* Exclusively shared on one node) */
>   
>   /*
>    * lm_lock() flags
> @@ -94,16 +97,16 @@ enum {
>    * lm_async_cb return flags
>    *
>    * LM_OUT_ST_MASK
> - * Masks the lower two bits of lock state in the returned value.
> + * Masks the lower three bits of lock state in the returned value.
>    *
>    * LM_OUT_CANCELED
>    * The lock request was canceled.
>    *
>    */
>   
> -#define LM_OUT_ST_MASK		0x00000003
> -#define LM_OUT_CANCELED		0x00000008
> -#define LM_OUT_ERROR		0x00000004
> +#define LM_OUT_ST_MASK		0x00000007
> +#define LM_OUT_CANCELED		0x00000010
> +#define LM_OUT_ERROR		0x00000008
>   
>   /*
>    * lm_recovery_done() messages
> @@ -162,6 +165,11 @@ static inline int gfs2_glock_is_held_excl(struct gfs2_glock *gl)
>   	return gl->gl_state == LM_ST_EXCLUSIVE;
>   }
>   
> +static inline int gfs2_glock_is_held_exsh(struct gfs2_glock *gl)
> +{
> +	return gl->gl_state == LM_ST_EXSH;
> +}
> +
>   static inline int gfs2_glock_is_held_dfrd(struct gfs2_glock *gl)
>   {
>   	return gl->gl_state == LM_ST_DEFERRED;
> diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
> index 0bbbaa9b05cb..58b3ed8531ee 100644
> --- a/fs/gfs2/incore.h
> +++ b/fs/gfs2/incore.h
> @@ -338,10 +338,10 @@ struct gfs2_glock {
>   	struct lockref gl_lockref;
>   
>   	/* State fields protected by gl_lockref.lock */
> -	unsigned int gl_state:2,	/* Current state */
> -		     gl_target:2,	/* Target state */
> -		     gl_demote_state:2,	/* State requested by remote node */
> -		     gl_req:2,		/* State in last dlm request */
> +	unsigned int gl_state:4,	/* Current state */
> +		     gl_target:4,	/* Target state */
> +		     gl_demote_state:4,	/* State requested by remote node */
> +		     gl_req:4,		/* State in last dlm request */
>   		     gl_reply:8;	/* Last reply from the dlm */
>   
>   	unsigned long gl_demote_time; /* time of first demote request */
> diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
> index 006c6164f759..e2f1968435a2 100644
> --- a/fs/gfs2/lock_dlm.c
> +++ b/fs/gfs2/lock_dlm.c
> @@ -191,6 +191,8 @@ static int make_mode(const unsigned int lmstate)
>   		return DLM_LOCK_NL;
>   	case LM_ST_EXCLUSIVE:
>   		return DLM_LOCK_EX;
> +	case LM_ST_EXSH:
> +		return DLM_LOCK_EX;
>   	case LM_ST_DEFERRED:
>   		return DLM_LOCK_CW;
>   	case LM_ST_SHARED:
> @@ -297,7 +299,8 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
>   
>   	/* don't want to skip dlm_unlock writing the lvb when lock is ex */
>   
> -	if (gl->gl_lksb.sb_lvbptr && (gl->gl_state == LM_ST_EXCLUSIVE))
> +	if (gl->gl_lksb.sb_lvbptr && (gl->gl_state == LM_ST_EXCLUSIVE ||
> +				      gl->gl_state == LM_ST_EXSH))
>   		lvb_needs_unlock = 1;
>   
>   	if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) &&
> diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h
> index cb10b95efe0f..6a46cee64508 100644
> --- a/fs/gfs2/trace_gfs2.h
> +++ b/fs/gfs2/trace_gfs2.h
> @@ -72,6 +72,8 @@ static inline u8 glock_trace_state(unsigned int state)
>   		return DLM_LOCK_CW;
>   	case LM_ST_EXCLUSIVE:
>   		return DLM_LOCK_EX;
> +	case LM_ST_EXSH:
> +		return DLM_LOCK_EX;
>   	}
>   	return DLM_LOCK_NL;
>   }




More information about the Cluster-devel mailing list