+static inline void cl_env_do_detach(struct cl_env *cle)
+{
+ void *cookie;
+
+ LASSERT(cle->ce_owner == (void *) (long) current->pid);
+ cookie = cfs_hash_del(cl_env_hash, cle->ce_owner,
+ &cle->ce_node);
+ LASSERT(cookie == cle);
+ cle->ce_owner = NULL;
+}
+
+static int cl_env_store_init(void) {
+ cl_env_hash = cfs_hash_create("cl_env",
+ HASH_CL_ENV_BITS, HASH_CL_ENV_BITS,
+ HASH_CL_ENV_BKT_BITS, 0,
+ CFS_HASH_MIN_THETA,
+ CFS_HASH_MAX_THETA,
+ &cl_env_hops,
+ CFS_HASH_RW_BKTLOCK);
+ return cl_env_hash != NULL ? 0 :-ENOMEM;
+}
+
+static void cl_env_store_fini(void) {
+ cfs_hash_putref(cl_env_hash);
+}
+
+#else /* LL_TASK_CL_ENV */
+/*
+ * The implementation of store cl_env directly in thread structure.
+ */
+
+static inline struct cl_env *cl_env_fetch(void)
+{
+ struct cl_env *cle;
+
+ cle = current->LL_TASK_CL_ENV;
+ if (cle && cle->ce_magic != &cl_env_init0)
+ cle = NULL;
+ return cle;
+}
+
+static inline void cl_env_attach(struct cl_env *cle)
+{
+ if (cle) {
+ LASSERT(cle->ce_owner == NULL);
+ cle->ce_owner = current;
+ cle->ce_prev = current->LL_TASK_CL_ENV;
+ current->LL_TASK_CL_ENV = cle;
+ }
+}
+
+static inline void cl_env_do_detach(struct cl_env *cle)
+{
+ LASSERT(cle->ce_owner == current);
+ LASSERT(current->LL_TASK_CL_ENV == cle);
+ current->LL_TASK_CL_ENV = cle->ce_prev;
+ cle->ce_owner = NULL;
+}
+
+static int cl_env_store_init(void) { return 0; }
+static void cl_env_store_fini(void) { }
+
+#endif /* LL_TASK_CL_ENV */
+