Whamcloud - gitweb
b=16098
[fs/lustre-release.git] / lustre / obdclass / lu_object.c
index 8629ee9..e65ddfa 100644 (file)
@@ -1,31 +1,45 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- * Lustre Object.
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *  Copyright (C) 2006 Cluster File Systems, Inc.
- *   Author: Nikita Danilov <nikita@clusterfs.com>
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
  *
- *   This file is part of the Lustre file system, http://www.lustre.org
- *   Lustre is a trademark of Cluster File Systems, Inc.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
  *
- *   You may have signed or agreed to another license before downloading
- *   this software.  If so, you are bound by the terms and conditions
- *   of that agreement, and the following does not apply to you.  See the
- *   LICENSE file included with this distribution for more information.
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see [sun.com URL with a
+ * copy of GPLv2].
  *
- *   If you did not agree to a different license, then this copy of Lustre
- *   is open source software; you can redistribute it and/or modify it
- *   under the terms of version 2 of the GNU General Public License as
- *   published by the Free Software Foundation.
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
  *
- *   In either case, Lustre is distributed in the hope that it will be
- *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   license text for more details.
+ * lustre/obdclass/lu_object.c
  *
+ * Lustre Object.
  * These are the only exported functions, they provide some generic
  * infrastructure for managing object devices
+ *
+ * Author: Nikita Danilov <nikita@clusterfs.com>
  */
 
 #define DEBUG_SUBSYSTEM S_CLASS
@@ -121,6 +135,7 @@ static struct lu_object *lu_object_alloc(const struct lu_env *env,
         struct list_head *layers;
         int clean;
         int result;
+        ENTRY;
 
         /*
          * Create top-level object slice. This will also create
@@ -128,8 +143,8 @@ static struct lu_object *lu_object_alloc(const struct lu_env *env,
          */
         top = s->ls_top_dev->ld_ops->ldo_object_alloc(env,
                                                       NULL, s->ls_top_dev);
-        if (IS_ERR(top))
-                RETURN(top);
+        if (top == NULL)
+                RETURN(ERR_PTR(-ENOMEM));
         /*
          * This is the only place where object fid is assigned. It's constant
          * after this point.
@@ -194,7 +209,7 @@ static void lu_object_free(const struct lu_env *env, struct lu_object *o)
          * necessary, because lu_object_header is freed together with the
          * top-level slice.
          */
-        INIT_LIST_HEAD(&splice);
+        CFS_INIT_LIST_HEAD(&splice);
         list_splice_init(&o->lo_header->loh_layers, &splice);
         while (!list_empty(&splice)) {
                 o = container_of0(splice.next, struct lu_object, lo_linkage);
@@ -213,7 +228,7 @@ int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr)
         struct lu_object_header *h;
         struct lu_object_header *temp;
 
-        INIT_LIST_HEAD(&dispose);
+        CFS_INIT_LIST_HEAD(&dispose);
         /*
          * Under LRU list lock, scan LRU list and move unreferenced objects to
          * the dispose list, removing them from LRU and hash table.
@@ -497,7 +512,7 @@ EXPORT_SYMBOL(lu_object_find);
 /*
  * Global list of all sites on this node
  */
-static LIST_HEAD(lu_sites);
+static CFS_LIST_HEAD(lu_sites);
 static DECLARE_MUTEX(lu_sites_guard);
 
 /*
@@ -534,7 +549,7 @@ void lu_site_print(const struct lu_env *env, struct lu_site *s, void *cookie,
 EXPORT_SYMBOL(lu_site_print);
 
 enum {
-        LU_CACHE_PERCENT   = 30,
+        LU_CACHE_PERCENT   = 20,
 };
 
 /*
@@ -542,18 +557,26 @@ enum {
  */
 static int lu_htable_order(void)
 {
-        int bits;
         unsigned long cache_size;
+        int bits;
 
         /*
          * Calculate hash table size, assuming that we want reasonable
-         * performance when 30% of available memory is occupied by cache of
+         * performance when 20% of total memory is occupied by cache of
          * lu_objects.
          *
          * Size of lu_object is (arbitrary) taken as 1K (together with inode).
          */
-        cache_size = nr_free_buffer_pages() / 100 *
-                LU_CACHE_PERCENT * (CFS_PAGE_SIZE / 1024);
+        cache_size = num_physpages;
+
+#if BITS_PER_LONG == 32
+        /* limit hashtable size for lowmem systems to low RAM */
+        if (cache_size > 1 << (30 - CFS_PAGE_SHIFT))
+                cache_size = 1 << (30 - CFS_PAGE_SHIFT) * 3 / 4;
+#endif
+
+        cache_size = cache_size / 100 * LU_CACHE_PERCENT *
+                (CFS_PAGE_SIZE / 1024);
 
         for (bits = 1; (1 << bits) < cache_size; ++bits) {
                 ;
@@ -782,6 +805,51 @@ struct lu_object *lu_object_locate(struct lu_object_header *h,
 }
 EXPORT_SYMBOL(lu_object_locate);
 
+
+
+/*
+ * Finalize and free devices in the device stack.
+ * 
+ * Finalize device stack by purging object cache, and calling
+ * lu_device_type_operations::ldto_device_fini() and
+ * lu_device_type_operations::ldto_device_free() on all devices in the stack.
+ */
+void lu_stack_fini(const struct lu_env *env, struct lu_device *top)
+{
+        struct lu_site   *site = top->ld_site;
+        struct lu_device *scan;
+        struct lu_device *next;
+
+        lu_site_purge(env, site, ~0);
+        for (scan = top; scan != NULL; scan = next) {
+                next = scan->ld_type->ldt_ops->ldto_device_fini(env, scan);
+                lu_device_put(scan);
+        }
+
+        /* purge again. */
+        lu_site_purge(env, site, ~0);
+
+        if (!list_empty(&site->ls_lru) || site->ls_total != 0) {
+                /*
+                 * Uh-oh, objects still exist.
+                 */
+                static DECLARE_LU_CDEBUG_PRINT_INFO(cookie, D_ERROR);
+
+                lu_site_print(env, site, &cookie, lu_cdebug_printer);
+        }
+
+        for (scan = top; scan != NULL; scan = next) {
+                const struct lu_device_type *ldt = scan->ld_type;
+                struct obd_type             *type;
+
+                next = ldt->ldt_ops->ldto_device_free(env, scan);
+                type = ldt->ldt_obd_type;
+                type->typ_refcnt--;
+                class_put_type(type);
+        }
+}
+EXPORT_SYMBOL(lu_stack_fini);
+
 enum {
         /*
          * Maximal number of tld slots.
@@ -867,6 +935,7 @@ EXPORT_SYMBOL(lu_context_key_degister);
 void *lu_context_key_get(const struct lu_context *ctx,
                          struct lu_context_key *key)
 {
+        LASSERT(ctx->lc_state == LCS_ENTERED);
         LASSERT(0 <= key->lct_index && key->lct_index < ARRAY_SIZE(lu_keys));
         return ctx->lc_value[key->lct_index];
 }
@@ -934,6 +1003,7 @@ static int keys_init(struct lu_context *ctx)
 int lu_context_init(struct lu_context *ctx, __u32 tags)
 {
         memset(ctx, 0, sizeof *ctx);
+        ctx->lc_state = LCS_INITIALIZED;
         ctx->lc_tags = tags;
         return keys_init(ctx);
 }
@@ -944,6 +1014,8 @@ EXPORT_SYMBOL(lu_context_init);
  */
 void lu_context_fini(struct lu_context *ctx)
 {
+        LASSERT(ctx->lc_state == LCS_INITIALIZED || ctx->lc_state == LCS_LEFT);
+        ctx->lc_state = LCS_FINALIZED;
         keys_fini(ctx);
 }
 EXPORT_SYMBOL(lu_context_fini);
@@ -953,6 +1025,8 @@ EXPORT_SYMBOL(lu_context_fini);
  */
 void lu_context_enter(struct lu_context *ctx)
 {
+        LASSERT(ctx->lc_state == LCS_INITIALIZED || ctx->lc_state == LCS_LEFT);
+        ctx->lc_state = LCS_ENTERED;
 }
 EXPORT_SYMBOL(lu_context_enter);
 
@@ -963,6 +1037,8 @@ void lu_context_exit(struct lu_context *ctx)
 {
         int i;
 
+        LASSERT(ctx->lc_state == LCS_ENTERED);
+        ctx->lc_state = LCS_LEFT;
         if (ctx->lc_value != NULL) {
                 for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) {
                         if (ctx->lc_value[i] != NULL) {
@@ -1030,7 +1106,7 @@ static int lu_cache_shrink(int nr, unsigned int gfp_mask)
         struct lu_site *tmp;
         int cached = 0;
         int remain = nr;
-        LIST_HEAD(splice);
+        CFS_LIST_HEAD(splice);
 
         if (nr != 0 && !(gfp_mask & __GFP_FS))
                 return -1;