struct kmem_cache *ldlm_resource_slab, *ldlm_lock_slab;
struct kmem_cache *ldlm_interval_tree_slab;
+struct kmem_cache *ldlm_inodebits_slab;
int ldlm_srv_namespace_nr = 0;
int ldlm_cli_namespace_nr = 0;
struct ldlm_namespace, ns_list_chain);
}
+static bool ldlm_resource_extent_new(struct ldlm_resource *res)
+{
+ int idx;
+
+ OBD_SLAB_ALLOC(res->lr_itree, ldlm_interval_tree_slab,
+ sizeof(*res->lr_itree) * LCK_MODE_NUM);
+ if (res->lr_itree == NULL)
+ return false;
+ /* Initialize interval trees for each lock mode. */
+ for (idx = 0; idx < LCK_MODE_NUM; idx++) {
+ res->lr_itree[idx].lit_size = 0;
+ res->lr_itree[idx].lit_mode = 1 << idx;
+ res->lr_itree[idx].lit_root = NULL;
+ }
+ return true;
+}
+
+static bool ldlm_resource_inodebits_new(struct ldlm_resource *res)
+{
+ int i;
+
+ OBD_ALLOC_PTR(res->lr_ibits_queues);
+ if (res->lr_ibits_queues == NULL)
+ return false;
+ for (i = 0; i < MDS_INODELOCK_NUMBITS; i++)
+ INIT_LIST_HEAD(&res->lr_ibits_queues->liq_waiting[i]);
+ return true;
+}
+
/** Create and initialize new resource. */
static struct ldlm_resource *ldlm_resource_new(enum ldlm_type ldlm_type)
{
struct ldlm_resource *res;
- int idx;
+ bool rc;
OBD_SLAB_ALLOC_PTR_GFP(res, ldlm_resource_slab, GFP_NOFS);
if (res == NULL)
return NULL;
- if (ldlm_type == LDLM_EXTENT) {
- OBD_SLAB_ALLOC(res->lr_itree, ldlm_interval_tree_slab,
- sizeof(*res->lr_itree) * LCK_MODE_NUM);
- if (res->lr_itree == NULL) {
- OBD_SLAB_FREE_PTR(res, ldlm_resource_slab);
- return NULL;
- }
- /* Initialize interval trees for each lock mode. */
- for (idx = 0; idx < LCK_MODE_NUM; idx++) {
- res->lr_itree[idx].lit_size = 0;
- res->lr_itree[idx].lit_mode = 1 << idx;
- res->lr_itree[idx].lit_root = NULL;
- }
+ switch (ldlm_type) {
+ case LDLM_EXTENT:
+ rc = ldlm_resource_extent_new(res);
+ break;
+ case LDLM_IBITS:
+ rc = ldlm_resource_inodebits_new(res);
+ break;
+ default:
+ rc = true;
+ break;
+ }
+ if (!rc) {
+ OBD_SLAB_FREE_PTR(res, ldlm_resource_slab);
+ return NULL;
}
INIT_LIST_HEAD(&res->lr_granted);
return res;
}
+static void ldlm_resource_free(struct ldlm_resource *res)
+{
+ if (res->lr_type == LDLM_EXTENT) {
+ if (res->lr_itree != NULL)
+ OBD_SLAB_FREE(res->lr_itree, ldlm_interval_tree_slab,
+ sizeof(*res->lr_itree) * LCK_MODE_NUM);
+ } else if (res->lr_type == LDLM_IBITS) {
+ if (res->lr_ibits_queues != NULL)
+ OBD_FREE_PTR(res->lr_ibits_queues);
+ }
+
+ OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
+}
+
/**
* Return a reference to resource with given name, creating it if necessary.
* Args: namespace with ns_lock unlocked
cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1);
/* Clean lu_ref for failed resource. */
lu_ref_fini(&res->lr_reference);
- if (res->lr_itree != NULL)
- OBD_SLAB_FREE(res->lr_itree, ldlm_interval_tree_slab,
- sizeof(*res->lr_itree) * LCK_MODE_NUM);
- OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
+ ldlm_resource_free(res);
found:
res = hlist_entry(hnode, struct ldlm_resource, lr_hash);
return res;
cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1);
if (ns->ns_lvbo && ns->ns_lvbo->lvbo_free)
ns->ns_lvbo->lvbo_free(res);
- if (res->lr_itree != NULL)
- OBD_SLAB_FREE(res->lr_itree, ldlm_interval_tree_slab,
- sizeof(*res->lr_itree) * LCK_MODE_NUM);
- OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
+ ldlm_resource_free(res);
return 1;
}
return 0;
LASSERT(list_empty(&lock->l_res_link));
list_add_tail(&lock->l_res_link, head);
+
+ if (res->lr_type == LDLM_IBITS)
+ ldlm_inodebits_add_lock(res, head, lock);
}
/**
int type = lock->l_resource->lr_type;
check_res_locked(lock->l_resource);
- if (type == LDLM_IBITS || type == LDLM_PLAIN)
+ switch (type) {
+ case LDLM_PLAIN:
ldlm_unlink_lock_skiplist(lock);
- else if (type == LDLM_EXTENT)
+ break;
+ case LDLM_EXTENT:
ldlm_extent_unlink_lock(lock);
+ break;
+ case LDLM_IBITS:
+ ldlm_inodebits_unlink_lock(lock);
+ break;
+ }
list_del_init(&lock->l_res_link);
}
EXPORT_SYMBOL(ldlm_resource_unlink_lock);