From: wangdi Date: Sat, 4 Feb 2012 08:12:48 +0000 (-0800) Subject: LU-1067 obdecho: Recheck client env ctx for echo md client. X-Git-Tag: 2.1.56~34 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=e27a7ff8f337984a4e7f8d31e419528b71c3777b;hp=68570176f72515dc10875dcacd7dbdc76dff3eaa LU-1067 obdecho: Recheck client env ctx for echo md client. During echo md test, if there are real clients being mounted at the same time, the cl env it gotten from the cache might contain the wrong context, so we need recheck the ctx and refill the env forcedly. Signed-off-by: Wang Di Change-Id: Iddbceee80966b5ca9284c886731386a97d089d53 Reviewed-on: http://review.whamcloud.com/2092 Tested-by: Hudson Reviewed-by: Jinshan Xiong Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/cl_object.h b/lustre/include/cl_object.h index 25e518b..628bfbf 100644 --- a/lustre/include/cl_object.h +++ b/lustre/include/cl_object.h @@ -3137,8 +3137,6 @@ void cl_env_implant (struct lu_env *env, int *refcheck); void cl_env_unplant (struct lu_env *env, int *refcheck); unsigned cl_env_cache_purge(unsigned nr); -void cl_set_ctx_tags(__u32 tags); -void cl_set_ses_tags(__u32 tags); /** @} cl_env */ /* diff --git a/lustre/include/lu_object.h b/lustre/include/lu_object.h index f431e0b..60b8ea6 100644 --- a/lustre/include/lu_object.h +++ b/lustre/include/lu_object.h @@ -1247,6 +1247,14 @@ void lu_context_key_degister_many(struct lu_context_key *k, ...); void lu_context_key_revive_many (struct lu_context_key *k, ...); void lu_context_key_quiesce_many (struct lu_context_key *k, ...); +/* + * update/clear ctx/ses tags. + */ +void lu_context_tags_update(__u32 tags); +void lu_context_tags_clear(__u32 tags); +void lu_session_tags_update(__u32 tags); +void lu_session_tags_clear(__u32 tags); + /** * Environment. */ @@ -1264,6 +1272,7 @@ struct lu_env { int lu_env_init (struct lu_env *env, __u32 tags); void lu_env_fini (struct lu_env *env); int lu_env_refill(struct lu_env *env); +int lu_env_refill_by_tags(struct lu_env *env, __u32 ctags, __u32 stags); /** @} lu_context */ diff --git a/lustre/obdclass/cl_object.c b/lustre/obdclass/cl_object.c index 9e65b3a..5a2da3e 100644 --- a/lustre/obdclass/cl_object.c +++ b/lustre/obdclass/cl_object.c @@ -76,8 +76,8 @@ static cfs_lock_class_key_t cl_lock_guard_class; /** Lock class of cl_object_header::coh_attr_guard */ static cfs_lock_class_key_t cl_attr_guard_class; -static __u32 cl_ctx_tags; -static __u32 cl_ses_tags; +extern __u32 lu_context_tags_default; +extern __u32 lu_session_tags_default; /** * Initialize cl_object_header. */ @@ -795,18 +795,6 @@ static void cl_env_fini(struct cl_env *cle) OBD_SLAB_FREE_PTR(cle, cl_env_kmem); } -void cl_set_ctx_tags(__u32 tags) -{ - cl_ctx_tags = tags; -} -EXPORT_SYMBOL(cl_set_ctx_tags); - -void cl_set_ses_tags(__u32 tags) -{ - cl_ses_tags = tags; -} -EXPORT_SYMBOL(cl_set_ses_tags); - static struct lu_env *cl_env_obtain(void *debug) { struct cl_env *cle; @@ -835,7 +823,8 @@ static struct lu_env *cl_env_obtain(void *debug) } } else { cfs_spin_unlock(&cl_envs_guard); - env = cl_env_new(cl_ctx_tags, cl_ses_tags, debug); + env = cl_env_new(lu_context_tags_default, + lu_session_tags_default, debug); } RETURN(env); } diff --git a/lustre/obdclass/lu_object.c b/lustre/obdclass/lu_object.c index 7e40191..0232cdd 100644 --- a/lustre/obdclass/lu_object.c +++ b/lustre/obdclass/lu_object.c @@ -1614,6 +1614,52 @@ int lu_context_refill(struct lu_context *ctx) } EXPORT_SYMBOL(lu_context_refill); +/** + * lu_ctx_tags/lu_ses_tags will be updated if there are new types of + * obd being added. Currently, this is only used on client side, specifically + * for echo device client, for other stack (like ptlrpc threads), context are + * predefined when the lu_device type are registered, during the module probe + * phase. + */ +__u32 lu_context_tags_default = 0; +__u32 lu_session_tags_default = 0; + +void lu_context_tags_update(__u32 tags) +{ + cfs_spin_lock(&lu_keys_guard); + lu_context_tags_default |= tags; + key_set_version ++; + cfs_spin_unlock(&lu_keys_guard); +} +EXPORT_SYMBOL(lu_context_tags_update); + +void lu_context_tags_clear(__u32 tags) +{ + cfs_spin_lock(&lu_keys_guard); + lu_context_tags_default &= ~tags; + key_set_version ++; + cfs_spin_unlock(&lu_keys_guard); +} +EXPORT_SYMBOL(lu_context_tags_clear); + +void lu_session_tags_update(__u32 tags) +{ + cfs_spin_lock(&lu_keys_guard); + lu_session_tags_default |= tags; + key_set_version ++; + cfs_spin_unlock(&lu_keys_guard); +} +EXPORT_SYMBOL(lu_session_tags_update); + +void lu_session_tags_clear(__u32 tags) +{ + cfs_spin_lock(&lu_keys_guard); + lu_session_tags_default &= ~tags; + key_set_version ++; + cfs_spin_unlock(&lu_keys_guard); +} +EXPORT_SYMBOL(lu_session_tags_clear); + int lu_env_init(struct lu_env *env, __u32 tags) { int result; @@ -1645,6 +1691,34 @@ int lu_env_refill(struct lu_env *env) } EXPORT_SYMBOL(lu_env_refill); +/** + * Currently, this API will only be used by echo client. + * Because echo client and normal lustre client will share + * same cl_env cache. So echo client needs to refresh + * the env context after it get one from the cache, especially + * when normal client and echo client co-exist in the same client. + */ +int lu_env_refill_by_tags(struct lu_env *env, __u32 ctags, + __u32 stags) +{ + int result; + + if ((env->le_ctx.lc_tags & ctags) != ctags) { + env->le_ctx.lc_version = 0; + env->le_ctx.lc_tags |= ctags; + } + + if (env->le_ses && (env->le_ses->lc_tags & stags) != stags) { + env->le_ses->lc_version = 0; + env->le_ses->lc_tags |= stags; + } + + result = lu_env_refill(env); + + return result; +} +EXPORT_SYMBOL(lu_env_refill_by_tags); + static struct cfs_shrinker *lu_site_shrinker = NULL; typedef struct lu_site_stats{ diff --git a/lustre/obdecho/echo_client.c b/lustre/obdecho/echo_client.c index 669761b..5deec15 100644 --- a/lustre/obdecho/echo_client.c +++ b/lustre/obdecho/echo_client.c @@ -992,7 +992,6 @@ static struct lu_device *echo_device_free(const struct lu_env *env, echo_client_cleanup(d->ld_obd); echo_fid_fini(d->ld_obd); - while (next && !ed->ed_next_ismd) next = next->ld_type->ldt_ops->ldto_device_free(env, next); @@ -1958,6 +1957,9 @@ struct lu_object *echo_resolve_path(const struct lu_env *env, RETURN(parent); } +#define ECHO_MD_CTX_TAG (LCT_REMEMBER | LCT_NOREF | LCT_MD_THREAD) +#define ECHO_MD_SES_TAG (LCT_SESSION | LCT_REMEMBER | LCT_NOREF) + static int echo_md_handler(struct echo_device *ed, int command, char *path, int path_len, int id, int count, struct obd_ioctl_data *data) @@ -1968,7 +1970,7 @@ static int echo_md_handler(struct echo_device *ed, int command, struct lu_object *parent; char *name = NULL; int namelen = data->ioc_plen2; - int rc = 0; + int rc = 0; ENTRY; if (ld == NULL) { @@ -1984,7 +1986,12 @@ static int echo_md_handler(struct echo_device *ed, int command, env = cl_env_get(&refcheck); if (IS_ERR(env)) RETURN(PTR_ERR(env)); - lu_env_refill(env); + + rc = lu_env_refill_by_tags(env, ECHO_MD_CTX_TAG, ECHO_MD_SES_TAG); + if (rc != 0) { + cl_env_put(env, &refcheck); + RETURN(rc); + } parent = echo_resolve_path(env, ed, path, path_len); if (IS_ERR(parent)) { @@ -2647,7 +2654,14 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, env = cl_env_get(&refcheck); if (IS_ERR(env)) GOTO(out, rc = PTR_ERR(env)); - lu_env_refill(env); + + rc = lu_env_refill_by_tags(env, ECHO_MD_CTX_TAG, + ECHO_MD_SES_TAG); + if (rc != 0) { + cl_env_put(env, &refcheck); + GOTO(out, rc); + } + rc = seq_client_get_seq(env, ed->ed_cl_seq, &seq); cl_env_put(env, &refcheck); if (rc < 0) { @@ -2807,8 +2821,8 @@ static int echo_client_setup(const struct lu_env *env, ec->ec_nstripes = 0; if (!strcmp(tgt->obd_type->typ_name, LUSTRE_MDT_NAME)) { - cl_set_ctx_tags(LCT_REMEMBER | LCT_NOREF | LCT_MD_THREAD); - cl_set_ses_tags(LCT_SESSION | LCT_REMEMBER | LCT_NOREF); + lu_context_tags_update(ECHO_MD_CTX_TAG); + lu_session_tags_update(ECHO_MD_SES_TAG); RETURN(0); } @@ -2852,9 +2866,15 @@ static int echo_client_cleanup(struct obd_device *obddev) ENTRY; /*Do nothing for Metadata echo client*/ - if (!ed || ed->ed_next_ismd) + if (ed == NULL ) RETURN(0); + if (ed->ed_next_ismd) { + lu_context_tags_clear(ECHO_MD_CTX_TAG); + lu_session_tags_clear(ECHO_MD_SES_TAG); + RETURN(0); + } + if (!cfs_list_empty(&obddev->obd_exports)) { CERROR("still has clients!\n"); RETURN(-EBUSY);