Whamcloud - gitweb
LU-2924 ldlm: split client namespaces into active and inactive
[fs/lustre-release.git] / lustre / ldlm / ldlm_resource.c
index 43fb2d1..d4a2bed 100644 (file)
 
 cfs_mem_cache_t *ldlm_resource_slab, *ldlm_lock_slab;
 
-cfs_atomic_t ldlm_srv_namespace_nr = CFS_ATOMIC_INIT(0);
-cfs_atomic_t ldlm_cli_namespace_nr = CFS_ATOMIC_INIT(0);
+int ldlm_srv_namespace_nr = 0;
+int ldlm_cli_namespace_nr = 0;
 
 struct mutex ldlm_srv_namespace_lock;
 CFS_LIST_HEAD(ldlm_srv_namespace_list);
 
 struct mutex ldlm_cli_namespace_lock;
-CFS_LIST_HEAD(ldlm_cli_namespace_list);
+/* Client Namespaces that have active resources in them.
+ * Once all resources go away, ldlm_poold moves such namespaces to the
+ * inactive list */
+CFS_LIST_HEAD(ldlm_cli_active_namespace_list);
+/* Client namespaces that don't have any locks in them */
+CFS_LIST_HEAD(ldlm_cli_inactive_namespace_list);
 
 cfs_proc_dir_entry_t *ldlm_type_proc_dir = NULL;
 cfs_proc_dir_entry_t *ldlm_ns_proc_dir = NULL;
@@ -675,7 +680,7 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name,
                 GOTO(out_hash, rc);
         }
 
-        idx = cfs_atomic_read(ldlm_namespace_nr(client));
+        idx = ldlm_namespace_nr_read(client);
         rc = ldlm_pool_init(&ns->ns_pool, ns, idx, client);
         if (rc) {
                 CERROR("Can't initialize lock pool, rc %d\n", rc);
@@ -992,6 +997,12 @@ void ldlm_namespace_get(struct ldlm_namespace *ns)
 }
 EXPORT_SYMBOL(ldlm_namespace_get);
 
+/* This is only for callers that care about refcount */
+int ldlm_namespace_get_return(struct ldlm_namespace *ns)
+{
+        return cfs_atomic_inc_return(&ns->ns_bref);
+}
+
 void ldlm_namespace_put(struct ldlm_namespace *ns)
 {
        if (cfs_atomic_dec_and_lock(&ns->ns_bref, &ns->ns_lock)) {
@@ -1006,8 +1017,8 @@ void ldlm_namespace_register(struct ldlm_namespace *ns, ldlm_side_t client)
 {
        mutex_lock(ldlm_namespace_lock(client));
        LASSERT(cfs_list_empty(&ns->ns_list_chain));
-       cfs_list_add(&ns->ns_list_chain, ldlm_namespace_list(client));
-       cfs_atomic_inc(ldlm_namespace_nr(client));
+       cfs_list_add(&ns->ns_list_chain, ldlm_namespace_inactive_list(client));
+       ldlm_namespace_nr_inc(client);
        mutex_unlock(ldlm_namespace_lock(client));
 }
 
@@ -1020,16 +1031,27 @@ void ldlm_namespace_unregister(struct ldlm_namespace *ns, ldlm_side_t client)
         * using list_empty(&ns->ns_list_chain). This is why it is
         * important to use list_del_init() here. */
        cfs_list_del_init(&ns->ns_list_chain);
-       cfs_atomic_dec(ldlm_namespace_nr(client));
+       ldlm_namespace_nr_dec(client);
        mutex_unlock(ldlm_namespace_lock(client));
 }
 
 /** Should be called with ldlm_namespace_lock(client) taken. */
-void ldlm_namespace_move_locked(struct ldlm_namespace *ns, ldlm_side_t client)
+void ldlm_namespace_move_to_active_locked(struct ldlm_namespace *ns,
+                                      ldlm_side_t client)
 {
-        LASSERT(!cfs_list_empty(&ns->ns_list_chain));
-        LASSERT_MUTEX_LOCKED(ldlm_namespace_lock(client));
-        cfs_list_move_tail(&ns->ns_list_chain, ldlm_namespace_list(client));
+       LASSERT(!cfs_list_empty(&ns->ns_list_chain));
+       LASSERT_MUTEX_LOCKED(ldlm_namespace_lock(client));
+       cfs_list_move_tail(&ns->ns_list_chain, ldlm_namespace_list(client));
+}
+
+/** Should be called with ldlm_namespace_lock(client) taken. */
+void ldlm_namespace_move_to_inactive_locked(struct ldlm_namespace *ns,
+                                        ldlm_side_t client)
+{
+       LASSERT(!cfs_list_empty(&ns->ns_list_chain));
+       LASSERT_MUTEX_LOCKED(ldlm_namespace_lock(client));
+       cfs_list_move_tail(&ns->ns_list_chain,
+                          ldlm_namespace_inactive_list(client));
 }
 
 /** Should be called with ldlm_namespace_lock(client) taken. */
@@ -1088,6 +1110,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
         struct ldlm_resource *res;
         cfs_hash_bd_t         bd;
         __u64                 version;
+       int                   ns_refcount = 0;
 
         LASSERT(ns != NULL);
         LASSERT(parent == NULL);
@@ -1157,8 +1180,8 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
        }
        /* We won! Let's add the resource. */
         cfs_hash_bd_add_locked(ns->ns_rs_hash, &bd, &res->lr_hash);
-        if (cfs_hash_bd_count_get(&bd) == 1)
-                ldlm_namespace_get(ns);
+       if (cfs_hash_bd_count_get(&bd) == 1)
+               ns_refcount = ldlm_namespace_get_return(ns);
 
         cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1);
         if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {
@@ -1184,6 +1207,20 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
        /* We create resource with locked lr_lvb_mutex. */
        mutex_unlock(&res->lr_lvb_mutex);
 
+       /* Let's see if we happened to be the very first resource in this
+        * namespace. If so, and this is a client namespace, we need to move
+        * the namespace into the active namespaces list to be patrolled by
+        * the ldlm_poold.
+        * A notable exception, for quota namespaces qsd_lib.c already took a
+        * namespace reference, so it won't be participating in all of this,
+        * but I guess that's ok since we have no business cancelling quota
+        * locks anyway */
+       if (ns_is_client(ns) && ns_refcount == 1) {
+               mutex_lock(ldlm_namespace_lock(LDLM_NAMESPACE_CLIENT));
+               ldlm_namespace_move_to_active_locked(ns, LDLM_NAMESPACE_CLIENT);
+               mutex_unlock(ldlm_namespace_lock(LDLM_NAMESPACE_CLIENT));
+       }
+
        return res;
 }
 EXPORT_SYMBOL(ldlm_resource_get);