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;
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);
}
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)) {
{
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));
}
* 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. */
struct ldlm_resource *res;
cfs_hash_bd_t bd;
__u64 version;
+ int ns_refcount = 0;
LASSERT(ns != NULL);
LASSERT(parent == NULL);
}
/* 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) {
/* 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);