1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
6 * This code is issued under the GNU General Public License.
7 * See the file COPYING in this distribution
9 * by Cluster File Systems, Inc.
14 #include <linux/version.h>
15 #include <linux/module.h>
16 #include <linux/slab.h>
17 #include <asm/unistd.h>
19 #define DEBUG_SUBSYSTEM S_LDLM
21 #include <linux/obd_support.h>
22 #include <linux/obd_class.h>
24 #include <linux/lustre_dlm.h>
26 extern kmem_cache_t *ldlm_lock_slab;
28 static struct ldlm_lock *ldlm_lock_new(struct ldlm_lock *parent,
29 struct ldlm_resource *resource,
32 struct ldlm_lock *lock;
34 lock = kmem_cache_alloc(ldlm_lock_slab, SLAB_KERNEL);
38 memset(lock, 0, sizeof(*lock));
39 lock->l_resource = resource;
40 lock->l_req_mode = mode;
41 INIT_LIST_HEAD(&lock->l_children);
44 lock->l_parent = parent;
45 list_add(&lock->l_childof, &parent->l_children);
51 static int ldlm_notify_incompatible(struct list_head *list,
52 struct ldlm_lock *new)
54 struct list_head *tmp;
57 list_for_each(tmp, list) {
58 struct ldlm_lock *lock = list_entry(tmp, struct ldlm_lock,
60 if (lockmode_compat(lock->l_req_mode, new->l_req_mode))
65 if (lock->l_resource->lr_blocking != NULL)
66 lock->l_resource->lr_blocking(lock, new);
72 ldlm_error_t ldlm_local_lock_enqueue(struct obd_device *obddev, __u32 ns_id,
73 struct ldlm_resource *parent_res,
74 struct ldlm_lock *parent_lock,
75 __u32 *res_id, ldlm_mode_t mode)
77 struct ldlm_namespace *ns;
78 struct ldlm_resource *res;
79 struct ldlm_lock *lock;
84 ns = ldlm_namespace_find(obddev, ns_id);
85 if (ns == NULL || ns->ns_hash == NULL)
88 res = ldlm_resource_get(ns, parent_res, res_id, 1);
92 lock = ldlm_lock_new(parent_lock, res, mode);
96 spin_lock(&res->lr_lock);
98 /* FIXME: We may want to optimize by checking lr_most_restr */
100 if (!list_empty(&res->lr_converting)) {
101 list_add(&lock->l_res_link, res->lr_waiting.prev);
102 rc = ELDLM_BLOCK_CONV;
105 if (!list_empty(&res->lr_waiting)) {
106 list_add(&lock->l_res_link, res->lr_waiting.prev);
107 rc = ELDLM_BLOCK_WAIT;
110 incompat = ldlm_notify_incompatible(&res->lr_granted, lock);
112 list_add(&lock->l_res_link, res->lr_waiting.prev);
113 rc = ELDLM_BLOCK_GRANTED;
117 list_add(&lock->l_res_link, &res->lr_granted);
118 lock->l_granted_mode = mode;
119 if (mode < res->lr_most_restr)
120 res->lr_most_restr = mode;
126 spin_unlock(&res->lr_lock);
130 void ldlm_lock_dump(struct ldlm_lock *lock)
134 if (RES_VERSION_SIZE != 4)
137 snprintf(ver, sizeof(ver), "%x %x %x %x",
138 lock->l_version[0], lock->l_version[1],
139 lock->l_version[2], lock->l_version[3]);
141 CDEBUG(D_OTHER, " -- Lock dump: %p (%s)\n", lock, ver);
142 CDEBUG(D_OTHER, " Parent: %p\n", lock->l_parent);
143 CDEBUG(D_OTHER, " Requested mode: %d, granted mode: %d\n",
144 (int)lock->l_req_mode, (int)lock->l_granted_mode);