Whamcloud - gitweb
LU-56 obdclass: SMP improvement for lu_key
[fs/lustre-release.git] / lustre / obdclass / lu_object.c
index 6057254..9d6746d 100644 (file)
@@ -1,6 +1,4 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
  * GPL HEADER START
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -28,9 +26,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/
@@ -46,9 +43,6 @@
  */
 
 #define DEBUG_SUBSYSTEM S_CLASS
-#ifndef EXPORT_SYMTAB
-# define EXPORT_SYMTAB
-#endif
 
 #include <libcfs/libcfs.h>
 
@@ -373,7 +367,8 @@ LU_KEY_INIT_FINI(lu_global, struct lu_cdebug_data);
  * lu_global_init().
  */
 struct lu_context_key lu_global_key = {
-        .lct_tags = LCT_MD_THREAD|LCT_DT_THREAD|LCT_CL_THREAD,
+        .lct_tags = LCT_MD_THREAD | LCT_DT_THREAD |
+                    LCT_MG_THREAD | LCT_CL_THREAD,
         .lct_init = lu_global_key_init,
         .lct_fini = lu_global_key_fini
 };
@@ -384,8 +379,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 +398,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);
@@ -618,7 +611,7 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env,
         cfs_hash_bd_lock(hs, &bd, 1);
 
         shadow = htable_lookup(s, &bd, f, waiter, &version);
-        if (shadow == NULL) {
+        if (likely(shadow == NULL)) {
                 struct lu_site_bkt_data *bkt;
 
                 bkt = cfs_hash_bd_extra_get(hs, &bd);
@@ -626,14 +619,12 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env,
                 bkt->lsb_busy++;
                 cfs_hash_bd_unlock(hs, &bd, 1);
                 return o;
-        } else {
-                if (!cfs_list_empty(&shadow->lo_header->loh_lru))
-                        cfs_list_del_init(&shadow->lo_header->loh_lru);
-                lprocfs_counter_incr(s->ls_stats, LU_SS_CACHE_RACE);
-                cfs_hash_bd_unlock(hs, &bd, 1);
-                lu_object_free(env, o);
-                return shadow;
         }
+
+        lprocfs_counter_incr(s->ls_stats, LU_SS_CACHE_RACE);
+        cfs_hash_bd_unlock(hs, &bd, 1);
+        lu_object_free(env, o);
+        return shadow;
 }
 
 /**
@@ -726,7 +717,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.
@@ -986,9 +977,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);
@@ -1013,11 +1004,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);
@@ -1211,9 +1202,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) {
@@ -1293,13 +1284,14 @@ static void key_fini(struct lu_context *ctx, int index)
                 key->lct_fini(ctx, key, ctx->lc_value[index]);
                 lu_ref_del(&key->lct_reference, "ctx", ctx);
                 cfs_atomic_dec(&key->lct_used);
-                LASSERT(key->lct_owner != NULL);
-                if (!(ctx->lc_tags & LCT_NOREF)) {
-                        LASSERT(cfs_module_refcount(key->lct_owner) > 0);
-                        cfs_module_put(key->lct_owner);
-                }
-                ctx->lc_value[index] = NULL;
-        }
+
+               LASSERT(key->lct_owner != NULL);
+               if ((ctx->lc_tags & LCT_NOREF) == 0) {
+                       LINVRNT(cfs_module_refcount(key->lct_owner) > 0);
+                       cfs_module_put(key->lct_owner);
+               }
+               ctx->lc_value[index] = NULL;
+       }
 }
 
 /**
@@ -1464,23 +1456,23 @@ EXPORT_SYMBOL(lu_context_key_revive);
 
 static void keys_fini(struct lu_context *ctx)
 {
-        int i;
+       int     i;
 
-        cfs_spin_lock(&lu_keys_guard);
-        if (ctx->lc_value != NULL) {
-                for (i = 0; i < ARRAY_SIZE(lu_keys); ++i)
-                        key_fini(ctx, i);
-                OBD_FREE(ctx->lc_value,
-                         ARRAY_SIZE(lu_keys) * sizeof ctx->lc_value[0]);
-                ctx->lc_value = NULL;
-        }
-        cfs_spin_unlock(&lu_keys_guard);
+       if (ctx->lc_value == NULL)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(lu_keys); ++i)
+               key_fini(ctx, i);
+
+       OBD_FREE(ctx->lc_value, ARRAY_SIZE(lu_keys) * sizeof ctx->lc_value[0]);
+       ctx->lc_value = NULL;
 }
 
 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;
 
@@ -1522,17 +1514,11 @@ static int keys_fill(struct lu_context *ctx)
 
 static int keys_init(struct lu_context *ctx)
 {
-        int result;
-
-        OBD_ALLOC(ctx->lc_value, ARRAY_SIZE(lu_keys) * sizeof ctx->lc_value[0]);
-        if (likely(ctx->lc_value != NULL))
-                result = keys_fill(ctx);
-        else
-                result = -ENOMEM;
+       OBD_ALLOC(ctx->lc_value, ARRAY_SIZE(lu_keys) * sizeof ctx->lc_value[0]);
+       if (likely(ctx->lc_value != NULL))
+               return keys_fill(ctx);
 
-        if (result != 0)
-                keys_fini(ctx);
-        return result;
+       return -ENOMEM;
 }
 
 /**
@@ -1540,6 +1526,8 @@ static int keys_init(struct lu_context *ctx)
  */
 int lu_context_init(struct lu_context *ctx, __u32 tags)
 {
+       int     rc;
+
         memset(ctx, 0, sizeof *ctx);
         ctx->lc_state = LCS_INITIALIZED;
         ctx->lc_tags = tags;
@@ -1547,9 +1535,15 @@ int lu_context_init(struct lu_context *ctx, __u32 tags)
                 cfs_spin_lock(&lu_keys_guard);
                 cfs_list_add(&ctx->lc_remember, &lu_context_remembered);
                 cfs_spin_unlock(&lu_keys_guard);
-        } else
-                CFS_INIT_LIST_HEAD(&ctx->lc_remember);
-        return keys_init(ctx);
+       } else {
+               CFS_INIT_LIST_HEAD(&ctx->lc_remember);
+       }
+
+       rc = keys_init(ctx);
+       if (rc != 0)
+               lu_context_fini(ctx);
+
+       return rc;
 }
 EXPORT_SYMBOL(lu_context_init);
 
@@ -1558,12 +1552,19 @@ EXPORT_SYMBOL(lu_context_init);
  */
 void lu_context_fini(struct lu_context *ctx)
 {
-        LINVRNT(ctx->lc_state == LCS_INITIALIZED || ctx->lc_state == LCS_LEFT);
-        ctx->lc_state = LCS_FINALIZED;
-        keys_fini(ctx);
-        cfs_spin_lock(&lu_keys_guard);
-        cfs_list_del_init(&ctx->lc_remember);
-        cfs_spin_unlock(&lu_keys_guard);
+       LINVRNT(ctx->lc_state == LCS_INITIALIZED || ctx->lc_state == LCS_LEFT);
+       ctx->lc_state = LCS_FINALIZED;
+
+       if ((ctx->lc_tags & LCT_REMEMBER) == 0) {
+               LASSERT(cfs_list_empty(&ctx->lc_remember));
+               keys_fini(ctx);
+
+       } else { /* could race with key degister */
+               cfs_spin_lock(&lu_keys_guard);
+               keys_fini(ctx);
+               cfs_list_del_init(&ctx->lc_remember);
+               cfs_spin_unlock(&lu_keys_guard);
+       }
 }
 EXPORT_SYMBOL(lu_context_fini);
 
@@ -1604,12 +1605,12 @@ 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);
 
@@ -1772,7 +1773,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);
@@ -1790,7 +1791,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)
@@ -1886,9 +1887,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;
 
@@ -1942,9 +1943,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();
 }