aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/lustre/lustre/ldlm/ldlm_resource.c')
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_resource.c358
1 files changed, 198 insertions, 160 deletions
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
index f750d42a7ad5..cdb63665a113 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
@@ -61,19 +61,17 @@ LIST_HEAD(ldlm_cli_active_namespace_list);
/* Client namespaces that don't have any locks in them */
LIST_HEAD(ldlm_cli_inactive_namespace_list);
-struct proc_dir_entry *ldlm_type_proc_dir = NULL;
-static struct proc_dir_entry *ldlm_ns_proc_dir = NULL;
-struct proc_dir_entry *ldlm_svc_proc_dir = NULL;
-
-extern unsigned int ldlm_cancel_unused_locks_before_replay;
+static struct dentry *ldlm_debugfs_dir;
+static struct dentry *ldlm_ns_debugfs_dir;
+struct dentry *ldlm_svc_debugfs_dir;
/* during debug dump certain amount of granted locks for one resource to avoid
* DDOS. */
unsigned int ldlm_dump_granted_max = 256;
-#if defined(CONFIG_PROC_FS)
-static ssize_t lprocfs_wr_dump_ns(struct file *file, const char __user *buffer,
- size_t count, loff_t *off)
+static ssize_t
+lprocfs_wr_dump_ns(struct file *file, const char __user *buffer,
+ size_t count, loff_t *off)
{
ldlm_dump_all_namespaces(LDLM_NAMESPACE_SERVER, D_DLMTRACE);
ldlm_dump_all_namespaces(LDLM_NAMESPACE_CLIENT, D_DLMTRACE);
@@ -82,81 +80,82 @@ static ssize_t lprocfs_wr_dump_ns(struct file *file, const char __user *buffer,
LPROC_SEQ_FOPS_WR_ONLY(ldlm, dump_ns);
LPROC_SEQ_FOPS_RW_TYPE(ldlm_rw, uint);
-LPROC_SEQ_FOPS_RO_TYPE(ldlm, uint);
-int ldlm_proc_setup(void)
+static struct lprocfs_vars ldlm_debugfs_list[] = {
+ { "dump_namespaces", &ldlm_dump_ns_fops, NULL, 0222 },
+ { "dump_granted_max", &ldlm_rw_uint_fops, &ldlm_dump_granted_max },
+ { NULL }
+};
+
+int ldlm_debugfs_setup(void)
{
int rc;
- struct lprocfs_vars list[] = {
- { "dump_namespaces", &ldlm_dump_ns_fops, NULL, 0222 },
- { "dump_granted_max", &ldlm_rw_uint_fops,
- &ldlm_dump_granted_max },
- { "cancel_unused_locks_before_replay", &ldlm_rw_uint_fops,
- &ldlm_cancel_unused_locks_before_replay },
- { NULL } };
- LASSERT(ldlm_ns_proc_dir == NULL);
-
- ldlm_type_proc_dir = lprocfs_register(OBD_LDLM_DEVICENAME,
- proc_lustre_root,
- NULL, NULL);
- if (IS_ERR(ldlm_type_proc_dir)) {
+
+ ldlm_debugfs_dir = ldebugfs_register(OBD_LDLM_DEVICENAME,
+ debugfs_lustre_root,
+ NULL, NULL);
+ if (IS_ERR_OR_NULL(ldlm_debugfs_dir)) {
CERROR("LProcFS failed in ldlm-init\n");
- rc = PTR_ERR(ldlm_type_proc_dir);
+ rc = ldlm_debugfs_dir ? PTR_ERR(ldlm_debugfs_dir) : -ENOMEM;
goto err;
}
- ldlm_ns_proc_dir = lprocfs_register("namespaces",
- ldlm_type_proc_dir,
- NULL, NULL);
- if (IS_ERR(ldlm_ns_proc_dir)) {
+ ldlm_ns_debugfs_dir = ldebugfs_register("namespaces",
+ ldlm_debugfs_dir,
+ NULL, NULL);
+ if (IS_ERR_OR_NULL(ldlm_ns_debugfs_dir)) {
CERROR("LProcFS failed in ldlm-init\n");
- rc = PTR_ERR(ldlm_ns_proc_dir);
+ rc = ldlm_ns_debugfs_dir ? PTR_ERR(ldlm_ns_debugfs_dir)
+ : -ENOMEM;
goto err_type;
}
- ldlm_svc_proc_dir = lprocfs_register("services",
- ldlm_type_proc_dir,
- NULL, NULL);
- if (IS_ERR(ldlm_svc_proc_dir)) {
+ ldlm_svc_debugfs_dir = ldebugfs_register("services",
+ ldlm_debugfs_dir,
+ NULL, NULL);
+ if (IS_ERR_OR_NULL(ldlm_svc_debugfs_dir)) {
CERROR("LProcFS failed in ldlm-init\n");
- rc = PTR_ERR(ldlm_svc_proc_dir);
+ rc = ldlm_svc_debugfs_dir ? PTR_ERR(ldlm_svc_debugfs_dir)
+ : -ENOMEM;
goto err_ns;
}
- rc = lprocfs_add_vars(ldlm_type_proc_dir, list, NULL);
+ rc = ldebugfs_add_vars(ldlm_debugfs_dir, ldlm_debugfs_list, NULL);
return 0;
err_ns:
- lprocfs_remove(&ldlm_ns_proc_dir);
+ ldebugfs_remove(&ldlm_ns_debugfs_dir);
err_type:
- lprocfs_remove(&ldlm_type_proc_dir);
+ ldebugfs_remove(&ldlm_debugfs_dir);
err:
- ldlm_svc_proc_dir = NULL;
- ldlm_type_proc_dir = NULL;
- ldlm_ns_proc_dir = NULL;
+ ldlm_svc_debugfs_dir = NULL;
+ ldlm_ns_debugfs_dir = NULL;
+ ldlm_debugfs_dir = NULL;
return rc;
}
-void ldlm_proc_cleanup(void)
+void ldlm_debugfs_cleanup(void)
{
- if (ldlm_svc_proc_dir)
- lprocfs_remove(&ldlm_svc_proc_dir);
+ if (!IS_ERR_OR_NULL(ldlm_svc_debugfs_dir))
+ ldebugfs_remove(&ldlm_svc_debugfs_dir);
- if (ldlm_ns_proc_dir)
- lprocfs_remove(&ldlm_ns_proc_dir);
+ if (!IS_ERR_OR_NULL(ldlm_ns_debugfs_dir))
+ ldebugfs_remove(&ldlm_ns_debugfs_dir);
- if (ldlm_type_proc_dir)
- lprocfs_remove(&ldlm_type_proc_dir);
+ if (!IS_ERR_OR_NULL(ldlm_debugfs_dir))
+ ldebugfs_remove(&ldlm_debugfs_dir);
- ldlm_svc_proc_dir = NULL;
- ldlm_type_proc_dir = NULL;
- ldlm_ns_proc_dir = NULL;
+ ldlm_svc_debugfs_dir = NULL;
+ ldlm_ns_debugfs_dir = NULL;
+ ldlm_debugfs_dir = NULL;
}
-static int lprocfs_ns_resources_seq_show(struct seq_file *m, void *v)
+static ssize_t resource_count_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct ldlm_namespace *ns = m->private;
+ struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+ ns_kobj);
__u64 res = 0;
struct cfs_hash_bd bd;
int i;
@@ -164,46 +163,56 @@ static int lprocfs_ns_resources_seq_show(struct seq_file *m, void *v)
/* result is not strictly consistent */
cfs_hash_for_each_bucket(ns->ns_rs_hash, &bd, i)
res += cfs_hash_bd_count_get(&bd);
- return lprocfs_rd_u64(m, &res);
+ return sprintf(buf, "%lld\n", res);
}
-LPROC_SEQ_FOPS_RO(lprocfs_ns_resources);
+LUSTRE_RO_ATTR(resource_count);
-static int lprocfs_ns_locks_seq_show(struct seq_file *m, void *v)
+static ssize_t lock_count_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct ldlm_namespace *ns = m->private;
+ struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+ ns_kobj);
__u64 locks;
locks = lprocfs_stats_collector(ns->ns_stats, LDLM_NSS_LOCKS,
LPROCFS_FIELDS_FLAGS_SUM);
- return lprocfs_rd_u64(m, &locks);
+ return sprintf(buf, "%lld\n", locks);
+}
+LUSTRE_RO_ATTR(lock_count);
+
+static ssize_t lock_unused_count_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+ ns_kobj);
+
+ return sprintf(buf, "%d\n", ns->ns_nr_unused);
}
-LPROC_SEQ_FOPS_RO(lprocfs_ns_locks);
+LUSTRE_RO_ATTR(lock_unused_count);
-static int lprocfs_lru_size_seq_show(struct seq_file *m, void *v)
+static ssize_t lru_size_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct ldlm_namespace *ns = m->private;
+ struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+ ns_kobj);
__u32 *nr = &ns->ns_max_unused;
if (ns_connect_lru_resize(ns))
nr = &ns->ns_nr_unused;
- return lprocfs_rd_uint(m, nr);
+ return sprintf(buf, "%u", *nr);
}
-static ssize_t lprocfs_lru_size_seq_write(struct file *file,
- const char __user *buffer,
- size_t count, loff_t *off)
+static ssize_t lru_size_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
{
- struct ldlm_namespace *ns = ((struct seq_file *)file->private_data)->private;
- char dummy[MAX_STRING_SIZE + 1];
+ struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+ ns_kobj);
unsigned long tmp;
int lru_resize;
int err;
- dummy[MAX_STRING_SIZE] = '\0';
- if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
- return -EFAULT;
-
- if (strncmp(dummy, "clear", 5) == 0) {
+ if (strncmp(buffer, "clear", 5) == 0) {
CDEBUG(D_DLMTRACE,
"dropping all unused locks from namespace %s\n",
ldlm_ns_name(ns));
@@ -229,9 +238,9 @@ static ssize_t lprocfs_lru_size_seq_write(struct file *file,
return count;
}
- err = kstrtoul(dummy, 10, &tmp);
+ err = kstrtoul(buffer, 10, &tmp);
if (err != 0) {
- CERROR("invalid value written\n");
+ CERROR("lru_size: invalid value written\n");
return -EINVAL;
}
lru_resize = (tmp == 0);
@@ -277,25 +286,56 @@ static ssize_t lprocfs_lru_size_seq_write(struct file *file,
return count;
}
-LPROC_SEQ_FOPS(lprocfs_lru_size);
+LUSTRE_RW_ATTR(lru_size);
-static int lprocfs_elc_seq_show(struct seq_file *m, void *v)
+static ssize_t lru_max_age_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct ldlm_namespace *ns = m->private;
- unsigned int supp = ns_connect_cancelset(ns);
+ struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+ ns_kobj);
- return lprocfs_rd_uint(m, &supp);
+ return sprintf(buf, "%u", ns->ns_max_age);
}
-static ssize_t lprocfs_elc_seq_write(struct file *file,
- const char __user *buffer,
- size_t count, loff_t *off)
+static ssize_t lru_max_age_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
{
- struct ldlm_namespace *ns = ((struct seq_file *)file->private_data)->private;
- unsigned int supp = -1;
+ struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+ ns_kobj);
+ unsigned long tmp;
+ int err;
+
+ err = kstrtoul(buffer, 10, &tmp);
+ if (err != 0)
+ return -EINVAL;
+
+ ns->ns_max_age = tmp;
+
+ return count;
+}
+LUSTRE_RW_ATTR(lru_max_age);
+
+static ssize_t early_lock_cancel_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+ ns_kobj);
+
+ return sprintf(buf, "%d\n", ns_connect_cancelset(ns));
+}
+
+static ssize_t early_lock_cancel_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buffer,
+ size_t count)
+{
+ struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+ ns_kobj);
+ unsigned long supp = -1;
int rc;
- rc = lprocfs_wr_uint(file, buffer, count, &supp);
+ rc = kstrtoul(buffer, 10, &supp);
if (rc < 0)
return rc;
@@ -305,91 +345,88 @@ static ssize_t lprocfs_elc_seq_write(struct file *file,
ns->ns_connect_flags |= OBD_CONNECT_CANCELSET;
return count;
}
-LPROC_SEQ_FOPS(lprocfs_elc);
+LUSTRE_RW_ATTR(early_lock_cancel);
+
+/* These are for namespaces in /sys/fs/lustre/ldlm/namespaces/ */
+static struct attribute *ldlm_ns_attrs[] = {
+ &lustre_attr_resource_count.attr,
+ &lustre_attr_lock_count.attr,
+ &lustre_attr_lock_unused_count.attr,
+ &lustre_attr_lru_size.attr,
+ &lustre_attr_lru_max_age.attr,
+ &lustre_attr_early_lock_cancel.attr,
+ NULL,
+};
+
+static void ldlm_ns_release(struct kobject *kobj)
+{
+ struct ldlm_namespace *ns = container_of(kobj, struct ldlm_namespace,
+ ns_kobj);
+ complete(&ns->ns_kobj_unregister);
+}
-void ldlm_namespace_proc_unregister(struct ldlm_namespace *ns)
+static struct kobj_type ldlm_ns_ktype = {
+ .default_attrs = ldlm_ns_attrs,
+ .sysfs_ops = &lustre_sysfs_ops,
+ .release = ldlm_ns_release,
+};
+
+static void ldlm_namespace_debugfs_unregister(struct ldlm_namespace *ns)
{
- if (ns->ns_proc_dir_entry == NULL)
+ if (IS_ERR_OR_NULL(ns->ns_debugfs_entry))
CERROR("dlm namespace %s has no procfs dir?\n",
ldlm_ns_name(ns));
else
- lprocfs_remove(&ns->ns_proc_dir_entry);
+ ldebugfs_remove(&ns->ns_debugfs_entry);
if (ns->ns_stats != NULL)
lprocfs_free_stats(&ns->ns_stats);
}
-#define LDLM_NS_ADD_VAR(name, var, ops) \
- do { \
- snprintf(lock_name, MAX_STRING_SIZE, name); \
- lock_vars[0].data = var; \
- lock_vars[0].fops = ops; \
- lprocfs_add_vars(ns_pde, lock_vars, NULL); \
- } while (0)
-
-int ldlm_namespace_proc_register(struct ldlm_namespace *ns)
+void ldlm_namespace_sysfs_unregister(struct ldlm_namespace *ns)
{
- struct lprocfs_vars lock_vars[2];
- char lock_name[MAX_STRING_SIZE + 1];
- struct proc_dir_entry *ns_pde;
+ kobject_put(&ns->ns_kobj);
+ wait_for_completion(&ns->ns_kobj_unregister);
+}
- LASSERT(ns != NULL);
- LASSERT(ns->ns_rs_hash != NULL);
+int ldlm_namespace_sysfs_register(struct ldlm_namespace *ns)
+{
+ int err;
- if (ns->ns_proc_dir_entry != NULL) {
- ns_pde = ns->ns_proc_dir_entry;
- } else {
- ns_pde = proc_mkdir(ldlm_ns_name(ns), ldlm_ns_proc_dir);
- if (ns_pde == NULL)
- return -ENOMEM;
- ns->ns_proc_dir_entry = ns_pde;
- }
+ ns->ns_kobj.kset = ldlm_ns_kset;
+ init_completion(&ns->ns_kobj_unregister);
+ err = kobject_init_and_add(&ns->ns_kobj, &ldlm_ns_ktype, NULL,
+ "%s", ldlm_ns_name(ns));
ns->ns_stats = lprocfs_alloc_stats(LDLM_NSS_LAST, 0);
- if (ns->ns_stats == NULL)
+ if (ns->ns_stats == NULL) {
+ kobject_put(&ns->ns_kobj);
return -ENOMEM;
+ }
lprocfs_counter_init(ns->ns_stats, LDLM_NSS_LOCKS,
LPROCFS_CNTR_AVGMINMAX, "locks", "locks");
- lock_name[MAX_STRING_SIZE] = '\0';
-
- memset(lock_vars, 0, sizeof(lock_vars));
- lock_vars[0].name = lock_name;
+ return err;
+}
- LDLM_NS_ADD_VAR("resource_count", ns, &lprocfs_ns_resources_fops);
- LDLM_NS_ADD_VAR("lock_count", ns, &lprocfs_ns_locks_fops);
+static int ldlm_namespace_debugfs_register(struct ldlm_namespace *ns)
+{
+ struct dentry *ns_entry;
- if (ns_is_client(ns)) {
- LDLM_NS_ADD_VAR("lock_unused_count", &ns->ns_nr_unused,
- &ldlm_uint_fops);
- LDLM_NS_ADD_VAR("lru_size", ns, &lprocfs_lru_size_fops);
- LDLM_NS_ADD_VAR("lru_max_age", &ns->ns_max_age,
- &ldlm_rw_uint_fops);
- LDLM_NS_ADD_VAR("early_lock_cancel", ns, &lprocfs_elc_fops);
+ if (!IS_ERR_OR_NULL(ns->ns_debugfs_entry)) {
+ ns_entry = ns->ns_debugfs_entry;
} else {
- LDLM_NS_ADD_VAR("ctime_age_limit", &ns->ns_ctime_age_limit,
- &ldlm_rw_uint_fops);
- LDLM_NS_ADD_VAR("lock_timeouts", &ns->ns_timeouts,
- &ldlm_uint_fops);
- LDLM_NS_ADD_VAR("max_nolock_bytes", &ns->ns_max_nolock_size,
- &ldlm_rw_uint_fops);
- LDLM_NS_ADD_VAR("contention_seconds", &ns->ns_contention_time,
- &ldlm_rw_uint_fops);
- LDLM_NS_ADD_VAR("contended_locks", &ns->ns_contended_locks,
- &ldlm_rw_uint_fops);
- LDLM_NS_ADD_VAR("max_parallel_ast", &ns->ns_max_parallel_ast,
- &ldlm_rw_uint_fops);
+ ns_entry = debugfs_create_dir(ldlm_ns_name(ns),
+ ldlm_ns_debugfs_dir);
+ if (ns_entry == NULL)
+ return -ENOMEM;
+ ns->ns_debugfs_entry = ns_entry;
}
+
return 0;
}
#undef MAX_STRING_SIZE
-#else /* CONFIG_PROC_FS */
-
-#define ldlm_namespace_proc_unregister(ns) ({; })
-#define ldlm_namespace_proc_register(ns) ({0; })
-
-#endif /* CONFIG_PROC_FS */
static unsigned ldlm_res_hop_hash(struct cfs_hash *hs,
const void *key, unsigned mask)
@@ -590,7 +627,7 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name,
break;
}
- OBD_ALLOC_PTR(ns);
+ ns = kzalloc(sizeof(*ns), GFP_NOFS);
if (!ns)
goto out_ref;
@@ -623,25 +660,26 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name,
atomic_set(&ns->ns_bref, 0);
init_waitqueue_head(&ns->ns_waitq);
- ns->ns_max_nolock_size = NS_DEFAULT_MAX_NOLOCK_BYTES;
- ns->ns_contention_time = NS_DEFAULT_CONTENTION_SECONDS;
- ns->ns_contended_locks = NS_DEFAULT_CONTENDED_LOCKS;
-
ns->ns_max_parallel_ast = LDLM_DEFAULT_PARALLEL_AST_LIMIT;
ns->ns_nr_unused = 0;
ns->ns_max_unused = LDLM_DEFAULT_LRU_SIZE;
ns->ns_max_age = LDLM_DEFAULT_MAX_ALIVE;
- ns->ns_ctime_age_limit = LDLM_CTIME_AGE_LIMIT;
- ns->ns_timeouts = 0;
ns->ns_orig_connect_flags = 0;
ns->ns_connect_flags = 0;
ns->ns_stopping = 0;
- rc = ldlm_namespace_proc_register(ns);
+
+ rc = ldlm_namespace_sysfs_register(ns);
if (rc != 0) {
- CERROR("Can't initialize ns proc, rc %d\n", rc);
+ CERROR("Can't initialize ns sysfs, rc %d\n", rc);
goto out_hash;
}
+ rc = ldlm_namespace_debugfs_register(ns);
+ if (rc != 0) {
+ CERROR("Can't initialize ns proc, rc %d\n", rc);
+ goto out_sysfs;
+ }
+
idx = ldlm_namespace_nr_read(client);
rc = ldlm_pool_init(&ns->ns_pool, ns, idx, client);
if (rc) {
@@ -652,12 +690,14 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name,
ldlm_namespace_register(ns, client);
return ns;
out_proc:
- ldlm_namespace_proc_unregister(ns);
+ ldlm_namespace_debugfs_unregister(ns);
+out_sysfs:
+ ldlm_namespace_sysfs_unregister(ns);
ldlm_namespace_cleanup(ns, 0);
out_hash:
cfs_hash_putref(ns->ns_rs_hash);
out_ns:
- OBD_FREE_PTR(ns);
+ kfree(ns);
out_ref:
ldlm_put_ref();
return NULL;
@@ -898,13 +938,13 @@ void ldlm_namespace_free_post(struct ldlm_namespace *ns)
* Removing it after @dir may cause oops. */
ldlm_pool_fini(&ns->ns_pool);
- ldlm_namespace_proc_unregister(ns);
+ ldlm_namespace_debugfs_unregister(ns);
cfs_hash_putref(ns->ns_rs_hash);
/* Namespace \a ns should be not on list at this time, otherwise
* this will cause issues related to using freed \a ns in poold
* thread. */
LASSERT(list_empty(&ns->ns_list_chain));
- OBD_FREE_PTR(ns);
+ kfree(ns);
ldlm_put_ref();
}
@@ -915,7 +955,7 @@ void ldlm_namespace_free_post(struct ldlm_namespace *ns)
* proc1: destroy import
* class_disconnect_export(grab cl_sem) ->
* -> ldlm_namespace_free ->
- * -> lprocfs_remove(grab _lprocfs_lock).
+ * -> ldebugfs_remove(grab _lprocfs_lock).
* proc2: read proc info
* lprocfs_fops_read(grab _lprocfs_lock) ->
* -> osc_rd_active, etc(grab cl_sem).
@@ -1137,10 +1177,8 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,
CERROR("%s: lvbo_init failed for resource %#llx:%#llx: rc = %d\n",
ns->ns_obd->obd_name, name->name[0],
name->name[1], rc);
- if (res->lr_lvb_data) {
- OBD_FREE(res->lr_lvb_data, res->lr_lvb_len);
- res->lr_lvb_data = NULL;
- }
+ kfree(res->lr_lvb_data);
+ res->lr_lvb_data = NULL;
res->lr_lvb_len = rc;
mutex_unlock(&res->lr_lvb_mutex);
ldlm_resource_putref(res);