X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fldlm%2Fldlm_resource.c;h=0f9f4e29442fff0d8d3e05b9caf623a37b69cd7f;hb=a1d6c3267c1e9934b827629a80078df3754e6268;hp=99d00b894bbffda60c4db907b674c0d412aacbe5;hpb=ccde9866c8679c37f1dcd0309100986e1d1c2041;p=fs%2Flustre-release.git diff --git a/lustre/ldlm/ldlm_resource.c b/lustre/ldlm/ldlm_resource.c index 99d00b8..0f9f4e2 100644 --- a/lustre/ldlm/ldlm_resource.c +++ b/lustre/ldlm/ldlm_resource.c @@ -1,135 +1,299 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * Copyright (C) 2002 Cluster File Systems, Inc. + * Copyright (C) 2002, 2003 Cluster File Systems, Inc. + * Author: Phil Schwan + * Author: Peter Braam * - * This code is issued under the GNU General Public License. - * See the file COPYING in this distribution + * This file is part of Lustre, http://www.lustre.org. * - * by Cluster File Systems, Inc. + * Lustre is free 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. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define DEBUG_SUBSYSTEM S_LDLM - +#ifdef __KERNEL__ #include +#else +#include +#endif + +#include kmem_cache_t *ldlm_resource_slab, *ldlm_lock_slab; -struct ldlm_namespace *ldlm_namespace_new(__u32 local) +spinlock_t ldlm_namespace_lock = SPIN_LOCK_UNLOCKED; +struct list_head ldlm_namespace_list = LIST_HEAD_INIT(ldlm_namespace_list); +static struct proc_dir_entry *ldlm_ns_proc_dir = NULL; + +int ldlm_proc_setup(struct obd_device *obd) +{ + int rc; + ENTRY; + LASSERT(ldlm_ns_proc_dir == NULL); + LASSERT(obd != NULL); + rc = lprocfs_obd_attach(obd, 0); + if (rc) { + CERROR("LProcFS failed in ldlm-init\n"); + RETURN(rc); + } + ldlm_ns_proc_dir = obd->obd_proc_entry; + RETURN(0); +} + +void ldlm_proc_cleanup(struct obd_device *obd) +{ + if (ldlm_ns_proc_dir) { + lprocfs_obd_detach(obd); + ldlm_ns_proc_dir = NULL; + } +} + +#ifdef __KERNEL__ +static int lprocfs_uint_rd(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + unsigned int *temp = (unsigned int *)data; + return snprintf(page, count, "%u\n", *temp); +} + + +#define MAX_STRING_SIZE 128 +void ldlm_proc_namespace(struct ldlm_namespace *ns) +{ + struct lprocfs_vars lock_vars[2]; + char lock_name[MAX_STRING_SIZE + 1]; + + LASSERT(ns != NULL); + LASSERT(ns->ns_name != NULL); + + lock_name[MAX_STRING_SIZE] = '\0'; + + memset(lock_vars, 0, sizeof(lock_vars)); + lock_vars[0].read_fptr = lprocfs_rd_u64; + + lock_vars[0].name = lock_name; + + snprintf(lock_name, MAX_STRING_SIZE, "%s/resource_count", ns->ns_name); + + lock_vars[0].data = &ns->ns_resources; + lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); + + snprintf(lock_name, MAX_STRING_SIZE, "%s/lock_count", ns->ns_name); + + lock_vars[0].data = &ns->ns_locks; + lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); + + snprintf(lock_name, MAX_STRING_SIZE, "%s/lock_unused_count", + ns->ns_name); + lock_vars[0].data = &ns->ns_nr_unused; + lock_vars[0].read_fptr = lprocfs_uint_rd; + lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0); +} +#endif +#undef MAX_STRING_SIZE + +#define LDLM_MAX_UNUSED 20 +struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 client) { struct ldlm_namespace *ns = NULL; struct list_head *bucket; + ENTRY; OBD_ALLOC(ns, sizeof(*ns)); - if (!ns) { - LBUG(); - GOTO(out, NULL); - } + if (!ns) + RETURN(NULL); ns->ns_hash = vmalloc(sizeof(*ns->ns_hash) * RES_HASH_SIZE); - if (!ns->ns_hash) { - LBUG(); - GOTO(out, ns); - } + if (!ns->ns_hash) + GOTO(out_ns, NULL); + + atomic_add(sizeof(*ns->ns_hash) * RES_HASH_SIZE, &obd_memory); - ptlrpc_init_client(NULL, NULL, - LDLM_REQUEST_PORTAL, LDLM_REPLY_PORTAL, - &ns->ns_client); + OBD_ALLOC(ns->ns_name, strlen(name) + 1); + if (!ns->ns_name) + GOTO(out_hash, NULL); + + strcpy(ns->ns_name, name); INIT_LIST_HEAD(&ns->ns_root_list); - ns->ns_lock = SPIN_LOCK_UNLOCKED; + l_lock_init(&ns->ns_lock); ns->ns_refcount = 0; - ns->ns_local = local; + ns->ns_client = client; + spin_lock_init(&ns->ns_counter_lock); + ns->ns_locks = 0; + ns->ns_resources = 0; for (bucket = ns->ns_hash + RES_HASH_SIZE - 1; bucket >= ns->ns_hash; bucket--) INIT_LIST_HEAD(bucket); + + INIT_LIST_HEAD(&ns->ns_unused_list); + ns->ns_nr_unused = 0; + ns->ns_max_unused = LDLM_MAX_UNUSED; + + spin_lock(&ldlm_namespace_lock); + list_add(&ns->ns_list_chain, &ldlm_namespace_list); + spin_unlock(&ldlm_namespace_lock); +#ifdef __KERNEL__ + ldlm_proc_namespace(ns); +#endif RETURN(ns); - out: - if (ns && ns->ns_hash) - vfree(ns->ns_hash); - if (ns) - OBD_FREE(ns, sizeof(*ns)); +out_hash: + POISON(ns->ns_hash, 0x5a, sizeof(*ns->ns_hash) * RES_HASH_SIZE); + vfree(ns->ns_hash); + atomic_sub(sizeof(*ns->ns_hash) * RES_HASH_SIZE, &obd_memory); +out_ns: + OBD_FREE(ns, sizeof(*ns)); return NULL; } -static int cleanup_resource(struct ldlm_resource *res, struct list_head *q) +extern struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock); + +/* If 'local_only' is true, don't try to tell the server, just cleanup. + * This is currently only used for recovery, and we make certain assumptions + * as a result--notably, that we shouldn't cancel locks with refs. -phil + * + * Called with the ns_lock held. */ +static void cleanup_resource(struct ldlm_resource *res, struct list_head *q, + int local_only) { struct list_head *tmp, *pos; - int rc = 0, client = res->lr_namespace->ns_local; + int rc = 0, client = res->lr_namespace->ns_client; ENTRY; list_for_each_safe(tmp, pos, q) { struct ldlm_lock *lock; lock = list_entry(tmp, struct ldlm_lock, l_res_link); + LDLM_LOCK_GET(lock); + + if (local_only && (lock->l_readers || lock->l_writers)) { + /* This is a little bit gross, but much better than the + * alternative: pretend that we got a blocking AST from + * the server, so that when the lock is decref'd, it + * will go away ... */ + lock->l_flags |= LDLM_FL_CBPENDING; + /* ... without sending a CANCEL message. */ + lock->l_flags |= LDLM_FL_LOCAL_ONLY; + /* ... and without calling the cancellation callback */ + lock->l_flags |= LDLM_FL_CANCEL; + LDLM_LOCK_PUT(lock); + continue; + } + + /* At shutdown time, don't call the cancellation callback */ + lock->l_flags |= LDLM_FL_CANCEL; if (client) { - rc = ldlm_cli_cancel(lock->l_client, lock); - if (rc < 0) { - CERROR("ldlm_cli_cancel: %d\n", rc); - LBUG(); + struct lustre_handle lockh; + ldlm_lock2handle(lock, &lockh); + if (!local_only) { + rc = ldlm_cli_cancel(&lockh); + if (rc) + CERROR("ldlm_cli_cancel: %d\n", rc); } - if (rc == ELDLM_RESOURCE_FREED) - rc = 1; + /* Force local cleanup on errors, too. */ + if (local_only || rc != ELDLM_OK) + ldlm_lock_cancel(lock); } else { - CERROR("Freeing a lock still held by a client node.\n"); - - spin_lock(&lock->l_lock); - ldlm_resource_del_lock(lock); - ldlm_lock_free(lock); + LDLM_DEBUG(lock, "Freeing a lock still held by a " + "client node"); - rc = ldlm_resource_put(res); + ldlm_resource_unlink_lock(lock); + ldlm_lock_destroy(lock); } + LDLM_LOCK_PUT(lock); } - - RETURN(rc); + EXIT; } -int ldlm_namespace_free(struct ldlm_namespace *ns) +int ldlm_namespace_cleanup(struct ldlm_namespace *ns, int local_only) { - struct list_head *tmp, *pos; - int i, rc; + int i; - if (!ns) - RETURN(ELDLM_OK); - /* We should probably take the ns_lock, but then ldlm_resource_put - * couldn't take it. Hmm. */ + if (ns == NULL) { + CDEBUG(D_INFO, "NULL ns, skipping cleanup\n"); + return ELDLM_OK; + } + + l_lock(&ns->ns_lock); for (i = 0; i < RES_HASH_SIZE; i++) { + struct list_head *tmp, *pos; list_for_each_safe(tmp, pos, &(ns->ns_hash[i])) { struct ldlm_resource *res; res = list_entry(tmp, struct ldlm_resource, lr_hash); - - spin_lock(&res->lr_lock); - rc = cleanup_resource(res, &res->lr_granted); - if (!rc) - rc = cleanup_resource(res, &res->lr_converting); - if (!rc) - rc = cleanup_resource(res, &res->lr_waiting); - - if (rc == 0) { - CERROR("Resource refcount nonzero after lock " - "cleanup; forcing cleanup.\n"); - res->lr_refcount = 1; - rc = ldlm_resource_put(res); + ldlm_resource_getref(res); + + cleanup_resource(res, &res->lr_granted, local_only); + cleanup_resource(res, &res->lr_converting, local_only); + cleanup_resource(res, &res->lr_waiting, local_only); + + /* XXX what a mess: don't force cleanup if we're + * local_only (which is only used by recovery). In that + * case, we probably still have outstanding lock refs + * which reference these resources. -phil */ + if (!ldlm_resource_putref(res) && !local_only) { + CERROR("Resource refcount nonzero (%d) after " + "lock cleanup; forcing cleanup.\n", + atomic_read(&res->lr_refcount)); + ldlm_resource_dump(res); + atomic_set(&res->lr_refcount, 1); + ldlm_resource_putref(res); } } } + l_unlock(&ns->ns_lock); + + return ELDLM_OK; +} - vfree(ns->ns_hash /* , sizeof(struct list_head) * RES_HASH_SIZE */); - ptlrpc_cleanup_client(&ns->ns_client); +/* Cleanup, but also free, the namespace */ +int ldlm_namespace_free(struct ldlm_namespace *ns) +{ + if (!ns) + RETURN(ELDLM_OK); + + spin_lock(&ldlm_namespace_lock); + list_del(&ns->ns_list_chain); + + spin_unlock(&ldlm_namespace_lock); + + ldlm_namespace_cleanup(ns, 0); + + POISON(ns->ns_hash, 0x5a, sizeof(*ns->ns_hash) * RES_HASH_SIZE); + vfree(ns->ns_hash /* , sizeof(*ns->ns_hash) * RES_HASH_SIZE */); + atomic_sub(sizeof(*ns->ns_hash) * RES_HASH_SIZE, &obd_memory); + OBD_FREE(ns->ns_name, strlen(ns->ns_name) + 1); OBD_FREE(ns, sizeof(*ns)); return ELDLM_OK; } -static __u32 ldlm_hash_fn(struct ldlm_resource *parent, __u64 *name) +int ldlm_client_free(struct obd_export *exp) +{ + struct ldlm_export_data *led = &exp->exp_ldlm_data; + ptlrpc_cleanup_client(&led->led_import); + RETURN(0); +} + +static __u32 ldlm_hash_fn(struct ldlm_resource *parent, struct ldlm_res_id name) { __u32 hash = 0; int i; for (i = 0; i < RES_NAME_SIZE; i++) - hash += name[i]; + hash += name.name[i]; hash += (__u32)((unsigned long)parent >> 4); @@ -153,17 +317,16 @@ static struct ldlm_resource *ldlm_resource_new(void) INIT_LIST_HEAD(&res->lr_converting); INIT_LIST_HEAD(&res->lr_waiting); - res->lr_lock = SPIN_LOCK_UNLOCKED; - res->lr_refcount = 1; + atomic_set(&res->lr_refcount, 1); return res; } /* Args: locked namespace * Returns: newly-allocated, referenced, unlocked resource */ -static struct ldlm_resource *ldlm_resource_add(struct ldlm_namespace *ns, - struct ldlm_resource *parent, - __u64 *name, __u32 type) +static struct ldlm_resource * +ldlm_resource_add(struct ldlm_namespace *ns, struct ldlm_resource *parent, + struct ldlm_res_id name, __u32 type) { struct list_head *bucket; struct ldlm_resource *res; @@ -180,23 +343,28 @@ static struct ldlm_resource *ldlm_resource_add(struct ldlm_namespace *ns, RETURN(NULL); } - memcpy(res->lr_name, name, sizeof(res->lr_name)); + spin_lock(&ns->ns_counter_lock); + ns->ns_resources++; + spin_unlock(&ns->ns_counter_lock); + + l_lock(&ns->ns_lock); + memcpy(&res->lr_name, &name, sizeof(res->lr_name)); res->lr_namespace = ns; ns->ns_refcount++; - res->lr_type = type; + res->lr_type = type; res->lr_most_restr = LCK_NL; bucket = ns->ns_hash + ldlm_hash_fn(parent, name); list_add(&res->lr_hash, bucket); if (parent == NULL) { - res->lr_parent = res; - list_add(&res->lr_rootlink, &ns->ns_root_list); + list_add(&res->lr_childof, &ns->ns_root_list); } else { res->lr_parent = parent; list_add(&res->lr_childof, &parent->lr_children); } + l_unlock(&ns->ns_lock); RETURN(res); } @@ -204,129 +372,178 @@ static struct ldlm_resource *ldlm_resource_add(struct ldlm_namespace *ns, /* Args: unlocked namespace * Locks: takes and releases ns->ns_lock and res->lr_lock * Returns: referenced, unlocked ldlm_resource or NULL */ -struct ldlm_resource *ldlm_resource_get(struct ldlm_namespace *ns, - struct ldlm_resource *parent, - __u64 *name, __u32 type, int create) +struct ldlm_resource * +ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, + struct ldlm_res_id name, __u32 type, int create) { - struct list_head *bucket; - struct list_head *tmp = bucket; + struct list_head *bucket, *tmp; struct ldlm_resource *res = NULL; ENTRY; - if (ns == NULL || ns->ns_hash == NULL) { - LBUG(); - RETURN(NULL); - } + LASSERT(ns != NULL); + LASSERT(ns->ns_hash != NULL); - spin_lock(&ns->ns_lock); + l_lock(&ns->ns_lock); bucket = ns->ns_hash + ldlm_hash_fn(parent, name); list_for_each(tmp, bucket) { - struct ldlm_resource *chk; - chk = list_entry(tmp, struct ldlm_resource, lr_hash); - - if (memcmp(chk->lr_name, name, sizeof(chk->lr_name)) == 0) { - res = chk; - spin_lock(&res->lr_lock); - res->lr_refcount++; - spin_unlock(&res->lr_lock); - EXIT; - break; + res = list_entry(tmp, struct ldlm_resource, lr_hash); + + if (memcmp(&res->lr_name, &name, sizeof(res->lr_name)) == 0) { + ldlm_resource_getref(res); + l_unlock(&ns->ns_lock); + RETURN(res); } } - if (res == NULL && create) + if (create) res = ldlm_resource_add(ns, parent, name, type); - spin_unlock(&ns->ns_lock); + else + res = NULL; + + l_unlock(&ns->ns_lock); RETURN(res); } -/* Args: locked resource - * Locks: takes and releases res->lr_lock - * takes and releases ns->ns_lock iff res->lr_refcount falls to 0 - */ -int ldlm_resource_put(struct ldlm_resource *res) +struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res) +{ + atomic_inc(&res->lr_refcount); + CDEBUG(D_INFO, "getref res: %p count: %d\n", res, + atomic_read(&res->lr_refcount)); + return res; +} + +/* Returns 1 if the resource was freed, 0 if it remains. */ +int ldlm_resource_putref(struct ldlm_resource *res) { int rc = 0; + ENTRY; + + CDEBUG(D_INFO, "putref res: %p count: %d\n", res, + atomic_read(&res->lr_refcount) - 1); + LASSERT(atomic_read(&res->lr_refcount) > 0); + LASSERT(atomic_read(&res->lr_refcount) < 0x5a5a5a5a); - if (res->lr_refcount == 1) { + if (atomic_dec_and_test(&res->lr_refcount)) { struct ldlm_namespace *ns = res->lr_namespace; ENTRY; - spin_unlock(&res->lr_lock); - spin_lock(&ns->ns_lock); - spin_lock(&res->lr_lock); + l_lock(&ns->ns_lock); - if (res->lr_refcount != 1) { - spin_unlock(&ns->ns_lock); - goto out; + if (atomic_read(&res->lr_refcount) != 0) { + /* We lost the race. */ + l_unlock(&ns->ns_lock); + RETURN(rc); } - if (!list_empty(&res->lr_granted)) + if (!list_empty(&res->lr_granted)) { + ldlm_resource_dump(res); LBUG(); + } - if (!list_empty(&res->lr_converting)) + if (!list_empty(&res->lr_converting)) { + ldlm_resource_dump(res); LBUG(); + } - if (!list_empty(&res->lr_waiting)) + if (!list_empty(&res->lr_waiting)) { + ldlm_resource_dump(res); LBUG(); + } - if (!list_empty(&res->lr_children)) + if (!list_empty(&res->lr_children)) { + ldlm_resource_dump(res); LBUG(); + } ns->ns_refcount--; - list_del(&res->lr_hash); - list_del(&res->lr_rootlink); - list_del(&res->lr_childof); + list_del_init(&res->lr_hash); + list_del_init(&res->lr_childof); + POISON(res, 0x5a, sizeof(*res)); kmem_cache_free(ldlm_resource_slab, res); - spin_unlock(&ns->ns_lock); + l_unlock(&ns->ns_lock); + + spin_lock(&ns->ns_counter_lock); + ns->ns_resources--; + spin_unlock(&ns->ns_counter_lock); + rc = 1; - } else { - ENTRY; - out: - res->lr_refcount--; - if (res->lr_refcount < 0) - LBUG(); + EXIT; } - RETURN(rc); + RETURN(rc); } -/* Must be called with resource->lr_lock taken */ void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head, struct ldlm_lock *lock) { - ldlm_resource_dump(res); - ldlm_lock_dump(lock); - if (!list_empty(&lock->l_res_link)) - LBUG(); + l_lock(&res->lr_namespace->ns_lock); - list_add(&lock->l_res_link, head); - res->lr_refcount++; -} + ldlm_resource_dump(res); + CDEBUG(D_OTHER, "About to add this lock:\n"); + ldlm_lock_dump(D_OTHER, lock); -/* Must be called with resource->lr_lock taken */ -void ldlm_resource_del_lock(struct ldlm_lock *lock) -{ - list_del_init(&lock->l_res_link); - lock->l_resource->lr_refcount--; + if (lock->l_destroyed) { + CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n"); + return; + } + + LASSERT(list_empty(&lock->l_res_link)); + + list_add_tail(&lock->l_res_link, head); + l_unlock(&res->lr_namespace->ns_lock); } -int ldlm_get_resource_handle(struct ldlm_resource *res, struct lustre_handle *h) +void ldlm_resource_unlink_lock(struct ldlm_lock *lock) { - LBUG(); - return 0; + l_lock(&lock->l_resource->lr_namespace->ns_lock); + list_del_init(&lock->l_res_link); + l_unlock(&lock->l_resource->lr_namespace->ns_lock); } void ldlm_res2desc(struct ldlm_resource *res, struct ldlm_resource_desc *desc) { desc->lr_type = res->lr_type; - memcpy(desc->lr_name, res->lr_name, sizeof(desc->lr_name)); + memcpy(&desc->lr_name, &res->lr_name, sizeof(desc->lr_name)); memcpy(desc->lr_version, res->lr_version, sizeof(desc->lr_version)); } +void ldlm_dump_all_namespaces(void) +{ + struct list_head *tmp; + + spin_lock(&ldlm_namespace_lock); + + list_for_each(tmp, &ldlm_namespace_list) { + struct ldlm_namespace *ns; + ns = list_entry(tmp, struct ldlm_namespace, ns_list_chain); + ldlm_namespace_dump(ns); + } + + spin_unlock(&ldlm_namespace_lock); +} + +void ldlm_namespace_dump(struct ldlm_namespace *ns) +{ + struct list_head *tmp; + + l_lock(&ns->ns_lock); + CDEBUG(D_OTHER, "--- Namespace: %s (rc: %d, client: %d)\n", ns->ns_name, + ns->ns_refcount, ns->ns_client); + + list_for_each(tmp, &ns->ns_root_list) { + struct ldlm_resource *res; + res = list_entry(tmp, struct ldlm_resource, lr_childof); + + /* Once we have resources with children, this should really dump + * them recursively. */ + ldlm_resource_dump(res); + } + l_unlock(&ns->ns_lock); +} + void ldlm_resource_dump(struct ldlm_resource *res) { struct list_head *tmp; @@ -336,32 +553,34 @@ void ldlm_resource_dump(struct ldlm_resource *res) LBUG(); snprintf(name, sizeof(name), "%Lx %Lx %Lx", - (unsigned long long)res->lr_name[0], - (unsigned long long)res->lr_name[1], - (unsigned long long)res->lr_name[2]); - - CDEBUG(D_OTHER, "--- Resource: %p (%s)\n", res, name); - CDEBUG(D_OTHER, "Namespace: %p\n", res->lr_namespace); + (unsigned long long)res->lr_name.name[0], + (unsigned long long)res->lr_name.name[1], + (unsigned long long)res->lr_name.name[2]); + + CDEBUG(D_OTHER, "--- Resource: %p (%s) (rc: %d)\n", res, name, + atomic_read(&res->lr_refcount)); + CDEBUG(D_OTHER, "Namespace: %p (%s)\n", res->lr_namespace, + res->lr_namespace->ns_name); CDEBUG(D_OTHER, "Parent: %p, root: %p\n", res->lr_parent, res->lr_root); CDEBUG(D_OTHER, "Granted locks:\n"); list_for_each(tmp, &res->lr_granted) { struct ldlm_lock *lock; lock = list_entry(tmp, struct ldlm_lock, l_res_link); - ldlm_lock_dump(lock); + ldlm_lock_dump(D_OTHER, lock); } CDEBUG(D_OTHER, "Converting locks:\n"); list_for_each(tmp, &res->lr_converting) { struct ldlm_lock *lock; lock = list_entry(tmp, struct ldlm_lock, l_res_link); - ldlm_lock_dump(lock); + ldlm_lock_dump(D_OTHER, lock); } CDEBUG(D_OTHER, "Waiting locks:\n"); list_for_each(tmp, &res->lr_waiting) { struct ldlm_lock *lock; lock = list_entry(tmp, struct ldlm_lock, l_res_link); - ldlm_lock_dump(lock); + ldlm_lock_dump(D_OTHER, lock); } }