@@ -1208,6 +1208,14 @@ void *lu_context_key_get(const struct lu_context *ctx,
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.
*/
@@ -1225,6 +1233,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);
struct lu_env *lu_env_find(void);
int lu_env_add(struct lu_env *env);
@@ -788,8 +788,10 @@ void cl_env_put(struct lu_env *env, u16 *refcheck)
* with the standard tags.
*/
if (cl_envs[cpu].cec_count < cl_envs_cached_max &&
- (env->le_ctx.lc_tags & ~LCT_HAS_EXIT) == LCT_CL_THREAD &&
- (env->le_ses->lc_tags & ~LCT_HAS_EXIT) == LCT_SESSION) {
+ (env->le_ctx.lc_tags & ~LCT_HAS_EXIT) ==
+ lu_context_tags_default &&
+ (env->le_ses->lc_tags & ~LCT_HAS_EXIT) ==
+ lu_session_tags_default) {
read_lock(&cl_envs[cpu].cec_guard);
list_add(&cle->ce_linkage, &cl_envs[cpu].cec_envs);
cl_envs[cpu].cec_count++;
@@ -1778,8 +1778,44 @@ int lu_context_refill(struct lu_context *ctx)
* predefined when the lu_device type are registered, during the module probe
* phase.
*/
-u32 lu_context_tags_default;
-u32 lu_session_tags_default;
+u32 lu_context_tags_default = LCT_CL_THREAD;
+u32 lu_session_tags_default = LCT_SESSION;
+
+void lu_context_tags_update(__u32 tags)
+{
+ spin_lock(&lu_context_remembered_guard);
+ lu_context_tags_default |= tags;
+ atomic_inc(&key_set_version);
+ spin_unlock(&lu_context_remembered_guard);
+}
+EXPORT_SYMBOL(lu_context_tags_update);
+
+void lu_context_tags_clear(__u32 tags)
+{
+ spin_lock(&lu_context_remembered_guard);
+ lu_context_tags_default &= ~tags;
+ atomic_inc(&key_set_version);
+ spin_unlock(&lu_context_remembered_guard);
+}
+EXPORT_SYMBOL(lu_context_tags_clear);
+
+void lu_session_tags_update(__u32 tags)
+{
+ spin_lock(&lu_context_remembered_guard);
+ lu_session_tags_default |= tags;
+ atomic_inc(&key_set_version);
+ spin_unlock(&lu_context_remembered_guard);
+}
+EXPORT_SYMBOL(lu_session_tags_update);
+
+void lu_session_tags_clear(__u32 tags)
+{
+ spin_lock(&lu_context_remembered_guard);
+ lu_session_tags_default &= ~tags;
+ atomic_inc(&key_set_version);
+ spin_unlock(&lu_context_remembered_guard);
+}
+EXPORT_SYMBOL(lu_session_tags_clear);
int lu_env_init(struct lu_env *env, u32 tags)
{
@@ -1801,6 +1837,34 @@ void lu_env_fini(struct lu_env *env)
}
EXPORT_SYMBOL(lu_env_fini);
+/**
+ * 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);
+
int lu_env_refill(struct lu_env *env)
{
int result;
@@ -50,6 +50,10 @@
* @{
*/
+/* echo thread key have a CL_THREAD flag, which set cl_env function directly */
+#define ECHO_DT_CTX_TAG (LCT_REMEMBER | LCT_DT_THREAD)
+#define ECHO_SES_TAG (LCT_REMEMBER | LCT_SESSION | LCT_SERVER_SESSION)
+
struct echo_device {
struct cl_device ed_cl;
struct echo_client_obd *ed_ec;
@@ -1481,6 +1485,7 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw,
struct echo_object *eco;
struct obd_ioctl_data *data = karg;
struct lu_env *env;
+ u16 refcheck;
struct obdo *oa;
struct lu_fid fid;
int rw = OBD_BRW_READ;
@@ -1497,16 +1502,14 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw,
if (rc < 0)
return rc;
- env = kzalloc(sizeof(*env), GFP_NOFS);
- if (!env)
- return -ENOMEM;
+ env = cl_env_get(&refcheck);
+ if (IS_ERR(env))
+ return PTR_ERR(env);
- rc = lu_env_init(env, LCT_DT_THREAD);
- if (rc) {
- rc = -ENOMEM;
- goto out;
- }
lu_env_add(env);
+ rc = lu_env_refill_by_tags(env, ECHO_DT_CTX_TAG, ECHO_SES_TAG);
+ if (rc != 0)
+ goto out;
switch (cmd) {
case OBD_IOC_CREATE: /* may create echo object */
@@ -1574,8 +1577,7 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw,
out:
lu_env_remove(env);
- lu_env_fini(env);
- kfree(env);
+ cl_env_put(env, &refcheck);
return rc;
}
@@ -1606,6 +1608,9 @@ static int echo_client_setup(const struct lu_env *env,
INIT_LIST_HEAD(&ec->ec_locks);
ec->ec_unique = 0;
+ lu_context_tags_update(ECHO_DT_CTX_TAG);
+ lu_session_tags_update(ECHO_SES_TAG);
+
ocd = kzalloc(sizeof(*ocd), GFP_NOFS);
if (!ocd)
return -ENOMEM;
@@ -1642,6 +1647,9 @@ static int echo_client_cleanup(struct obd_device *obddev)
return -EBUSY;
}
+ lu_session_tags_clear(ECHO_SES_TAG & ~LCT_SESSION);
+ lu_context_tags_clear(ECHO_DT_CTX_TAG);
+
LASSERT(refcount_read(&ec->ec_exp->exp_refcount) > 0);
rc = obd_disconnect(ec->ec_exp);
if (rc != 0)