Whamcloud - gitweb
LU-911 ost: ost_handle() to refill environment on every requests
[fs/lustre-release.git] / lustre / obdclass / lu_object.c
index b3bc375..3993c18 100644 (file)
@@ -28,9 +28,8 @@
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2011 Whamcloud, Inc.
+ *
+ * Copyright (c) 2011, 2012, Whamcloud, Inc.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -355,7 +354,7 @@ enum {
          *
          * XXX overflow is not handled correctly.
          */
-        LU_CDEBUG_LINE = 256
+        LU_CDEBUG_LINE = 512
 };
 
 struct lu_cdebug_data {
@@ -384,8 +383,8 @@ struct lu_context_key lu_global_key = {
 int lu_cdebug_printer(const struct lu_env *env,
                       void *cookie, const char *format, ...)
 {
-        struct lu_cdebug_print_info *info = cookie;
-        struct lu_cdebug_data       *key;
+        struct libcfs_debug_msg_data *msgdata = cookie;
+        struct lu_cdebug_data        *key;
         int used;
         int complete;
         va_list args;
@@ -403,10 +402,8 @@ int lu_cdebug_printer(const struct lu_env *env,
         vsnprintf(key->lck_area + used,
                   ARRAY_SIZE(key->lck_area) - used, format, args);
         if (complete) {
-                if (cfs_cdebug_show(info->lpi_mask, info->lpi_subsys))
-                        libcfs_debug_msg(NULL, info->lpi_subsys, info->lpi_mask,
-                                         (char *)info->lpi_file, info->lpi_fn,
-                                         info->lpi_line, "%s", key->lck_area);
+                if (cfs_cdebug_show(msgdata->msg_mask, msgdata->msg_subsys))
+                        libcfs_debug_msg(msgdata, "%s", key->lck_area);
                 key->lck_area[0] = 0;
         }
         va_end(args);
@@ -504,6 +501,7 @@ static struct lu_object *htable_lookup(struct lu_site *s,
         h = container_of0(hnode, struct lu_object_header, loh_hash);
         if (likely(!lu_object_is_dying(h))) {
                 lprocfs_counter_incr(s->ls_stats, LU_SS_CACHE_HIT);
+                cfs_list_del_init(&h->loh_lru);
                 return lu_object_top(h);
         }
 
@@ -600,8 +598,6 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env,
         hs = s->ls_obj_hash;
         cfs_hash_bd_get_and_lock(hs, (void *)f, &bd, 1);
         o = htable_lookup(s, &bd, f, waiter, &version);
-        if (o != NULL && !cfs_list_empty(&o->lo_header->loh_lru))
-                cfs_list_del_init(&o->lo_header->loh_lru);
         cfs_hash_bd_unlock(hs, &bd, 1);
         if (o != NULL)
                 return o;
@@ -725,7 +721,7 @@ EXPORT_SYMBOL(lu_types_stop);
  * Global list of all sites on this node
  */
 static CFS_LIST_HEAD(lu_sites);
-static CFS_DECLARE_MUTEX(lu_sites_guard);
+static CFS_DEFINE_MUTEX(lu_sites_guard);
 
 /**
  * Global environment used by site shrinker.
@@ -829,10 +825,18 @@ static unsigned lu_obj_hop_hash(cfs_hash_t *hs,
                                 const void *key, unsigned mask)
 {
         struct lu_fid  *fid = (struct lu_fid *)key;
-        unsigned        hash;
+        __u32           hash;
+
+        hash = fid_flatten32(fid);
+        hash += (hash >> 4) + (hash << 12); /* mixing oid and seq */
+        hash = cfs_hash_long(hash, hs->hs_bkt_bits);
+
+        /* give me another random factor */
+        hash -= cfs_hash_long((unsigned long)hs, fid_oid(fid) % 11 + 3);
+
+        hash <<= hs->hs_cur_bits - hs->hs_bkt_bits;
+        hash |= (fid_seq(fid) + fid_oid(fid)) & (CFS_HASH_NBKT(hs) - 1);
 
-        hash = (fid_seq(fid) + fid_oid(fid)) & (CFS_HASH_NBKT(hs) - 1);
-        hash += fid_hash(fid, hs->hs_bkt_bits) << hs->hs_bkt_bits;
         return hash & mask;
 }
 
@@ -890,27 +894,29 @@ cfs_hash_ops_t lu_site_hash_ops = {
  * Initialize site \a s, with \a d as the top level device.
  */
 #define LU_SITE_BITS_MIN    12
-#define LU_SITE_BITS_MAX    23
+#define LU_SITE_BITS_MAX    24
 /**
- * total 128 buckets, we don't want too many buckets because:
+ * total 256 buckets, we don't want too many buckets because:
  * - consume too much memory
  * - avoid unbalanced LRU list
  */
-#define LU_SITE_BKT_BITS    7
+#define LU_SITE_BKT_BITS    8
 
 int lu_site_init(struct lu_site *s, struct lu_device *top)
 {
         struct lu_site_bkt_data *bkt;
         cfs_hash_bd_t bd;
+        char name[16];
         int bits;
         int i;
         ENTRY;
 
         memset(s, 0, sizeof *s);
         bits = lu_htable_order();
+        snprintf(name, 16, "lu_site_%s", top->ld_type->ldt_name);
         for (bits = min(max(LU_SITE_BITS_MIN, bits), LU_SITE_BITS_MAX);
              bits >= LU_SITE_BITS_MIN; bits--) {
-                s->ls_obj_hash = cfs_hash_create("lu_site", bits, bits,
+                s->ls_obj_hash = cfs_hash_create(name, bits, bits,
                                                  bits - LU_SITE_BKT_BITS,
                                                  sizeof(*bkt), 0, 0,
                                                  &lu_site_hash_ops,
@@ -959,6 +965,13 @@ int lu_site_init(struct lu_site *s, struct lu_device *top)
         lu_device_get(top);
         lu_ref_add(&top->ld_reference, "site-top", s);
 
+        CFS_INIT_LIST_HEAD(&s->ls_ld_linkage);
+        cfs_spin_lock_init(&s->ls_ld_lock);
+
+        cfs_spin_lock(&s->ls_ld_lock);
+        cfs_list_add(&top->ld_linkage, &s->ls_ld_linkage);
+        cfs_spin_unlock(&s->ls_ld_lock);
+
         RETURN(0);
 }
 EXPORT_SYMBOL(lu_site_init);
@@ -968,9 +981,9 @@ EXPORT_SYMBOL(lu_site_init);
  */
 void lu_site_fini(struct lu_site *s)
 {
-        cfs_down(&lu_sites_guard);
+        cfs_mutex_lock(&lu_sites_guard);
         cfs_list_del_init(&s->ls_linkage);
-        cfs_up(&lu_sites_guard);
+        cfs_mutex_unlock(&lu_sites_guard);
 
         if (s->ls_obj_hash != NULL) {
                 cfs_hash_putref(s->ls_obj_hash);
@@ -995,11 +1008,11 @@ EXPORT_SYMBOL(lu_site_fini);
 int lu_site_init_finish(struct lu_site *s)
 {
         int result;
-        cfs_down(&lu_sites_guard);
+        cfs_mutex_lock(&lu_sites_guard);
         result = lu_context_refill(&lu_shrink_env.le_ctx);
         if (result == 0)
                 cfs_list_add(&s->ls_linkage, &lu_sites);
-        cfs_up(&lu_sites_guard);
+        cfs_mutex_unlock(&lu_sites_guard);
         return result;
 }
 EXPORT_SYMBOL(lu_site_init_finish);
@@ -1034,6 +1047,7 @@ int lu_device_init(struct lu_device *d, struct lu_device_type *t)
         cfs_atomic_set(&d->ld_ref, 0);
         d->ld_type = t;
         lu_ref_init(&d->ld_reference);
+        CFS_INIT_LIST_HEAD(&d->ld_linkage);
         return 0;
 }
 EXPORT_SYMBOL(lu_device_init);
@@ -1192,9 +1206,9 @@ void lu_stack_fini(const struct lu_env *env, struct lu_device *top)
                 /*
                  * Uh-oh, objects still exist.
                  */
-                static DECLARE_LU_CDEBUG_PRINT_INFO(cookie, D_ERROR);
+                LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_ERROR, NULL);
 
-                lu_site_print(env, site, &cookie, lu_cdebug_printer);
+                lu_site_print(env, site, &msgdata, lu_cdebug_printer);
         }
 
         for (scan = top; scan != NULL; scan = next) {
@@ -1462,6 +1476,7 @@ static int keys_fill(struct lu_context *ctx)
 {
         int i;
 
+        LINVRNT(ctx->lc_value != NULL);
         for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) {
                 struct lu_context_key *key;
 
@@ -1585,15 +1600,61 @@ EXPORT_SYMBOL(lu_context_exit);
 
 /**
  * Allocate for context all missing keys that were registered after context
- * creation.
+ * creation. key_set_version is only changed in rare cases when modules
+ * are loaded and removed.
  */
 int lu_context_refill(struct lu_context *ctx)
 {
-        LINVRNT(ctx->lc_value != NULL);
-        return ctx->lc_version == key_set_version ? 0 : keys_fill(ctx);
+        return likely(ctx->lc_version == key_set_version) ? 0 : keys_fill(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;
@@ -1625,6 +1686,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{
@@ -1679,7 +1768,7 @@ static int lu_cache_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask))
                 CDEBUG(D_INODE, "Shrink %d objects\n", remain);
         }
 
-        cfs_down(&lu_sites_guard);
+        cfs_mutex_lock(&lu_sites_guard);
         cfs_list_for_each_entry_safe(s, tmp, &lu_sites, ls_linkage) {
                 if (shrink_param(sc, nr_to_scan) != 0) {
                         remain = lu_site_purge(&lu_shrink_env, s, remain);
@@ -1697,7 +1786,7 @@ static int lu_cache_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask))
                         break;
         }
         cfs_list_splice(&splice, lu_sites.prev);
-        cfs_up(&lu_sites_guard);
+        cfs_mutex_unlock(&lu_sites_guard);
 
         cached = (cached / 100) * sysctl_vfs_cache_pressure;
         if (shrink_param(sc, nr_to_scan) == 0)
@@ -1793,9 +1882,9 @@ int lu_global_init(void)
          * conservatively. This should not be too bad, because this
          * environment is global.
          */
-        cfs_down(&lu_sites_guard);
+        cfs_mutex_lock(&lu_sites_guard);
         result = lu_env_init(&lu_shrink_env, LCT_SHRINKER);
-        cfs_up(&lu_sites_guard);
+        cfs_mutex_unlock(&lu_sites_guard);
         if (result != 0)
                 return result;
 
@@ -1849,9 +1938,9 @@ void lu_global_fini(void)
          * Tear shrinker environment down _after_ de-registering
          * lu_global_key, because the latter has a value in the former.
          */
-        cfs_down(&lu_sites_guard);
+        cfs_mutex_lock(&lu_sites_guard);
         lu_env_fini(&lu_shrink_env);
-        cfs_up(&lu_sites_guard);
+        cfs_mutex_unlock(&lu_sites_guard);
 
         lu_ref_global_fini();
 }