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.
10 * authors, Peter Braam <braam@clusterfs.com> &
11 * Phil Schwan <phil@clusterfs.com>
16 #include <linux/version.h>
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 #include <asm/unistd.h>
21 #define DEBUG_SUBSYSTEM S_LDLM
23 #include <linux/obd_support.h>
24 #include <linux/obd_class.h>
26 #include <linux/lustre_dlm.h>
28 extern kmem_cache_t *ldlm_lock_slab;
30 static struct ldlm_lock *ldlm_lock_new(struct ldlm_lock *parent,
31 struct ldlm_resource *resource,
34 struct ldlm_lock *lock;
36 lock = kmem_cache_alloc(ldlm_lock_slab, SLAB_KERNEL);
40 memset(lock, 0, sizeof(*lock));
41 lock->l_resource = resource;
42 lock->l_req_mode = mode;
43 INIT_LIST_HEAD(&lock->l_children);
46 lock->l_parent = parent;
47 list_add(&lock->l_childof, &parent->l_children);
53 static int ldlm_notify_incompatible(struct list_head *list,
54 struct ldlm_lock *new)
56 struct list_head *tmp;
59 list_for_each(tmp, list) {
60 struct ldlm_lock *lock;
61 lock = list_entry(tmp, struct ldlm_lock, l_res_link);
62 if (lockmode_compat(lock->l_req_mode, new->l_req_mode))
67 if (lock->l_resource->lr_blocking != NULL)
68 lock->l_resource->lr_blocking(lock, new);
75 static int ldlm_reprocess_queue(struct list_head *queue,
76 struct list_head *granted_list)
78 struct list_head *tmp1, *tmp2;
79 struct ldlm_resource *res;
82 list_for_each(tmp1, queue) {
83 struct ldlm_lock *pending;
85 pending = list_entry(tmp1, struct ldlm_lock, l_res_link);
87 /* check if pending can go in ... */
88 list_for_each(tmp2, granted_list) {
89 struct ldlm_lock *lock;
90 lock = list_entry(tmp2, struct ldlm_lock, l_res_link);
91 if (lockmode_compat(lock->l_granted_mode,
102 /* no - we are done */
106 res = pending->l_resource;
107 list_del(&pending->l_res_link);
108 list_add(&pending->l_res_link, &res->lr_granted);
109 pending->l_granted_mode = pending->l_req_mode;
111 if (pending->l_granted_mode < res->lr_most_restr)
112 res->lr_most_restr = pending->l_granted_mode;
114 /* XXX call completion here */
122 ldlm_error_t ldlm_local_lock_enqueue(struct obd_device *obddev, __u32 ns_id,
123 struct ldlm_resource *parent_res,
124 struct ldlm_lock *parent_lock,
125 __u32 *res_id, ldlm_mode_t mode,
126 struct ldlm_handle *lockh)
128 struct ldlm_namespace *ns;
129 struct ldlm_resource *res;
130 struct ldlm_lock *lock;
135 ns = ldlm_namespace_find(obddev, ns_id);
136 if (ns == NULL || ns->ns_hash == NULL)
139 res = ldlm_resource_get(ns, parent_res, res_id, 1);
143 lock = ldlm_lock_new(parent_lock, res, mode);
147 lockh->addr = (__u64)(unsigned long)lock;
148 spin_lock(&res->lr_lock);
150 /* FIXME: We may want to optimize by checking lr_most_restr */
152 if (!list_empty(&res->lr_converting)) {
153 list_add(&lock->l_res_link, res->lr_waiting.prev);
154 rc = ELDLM_BLOCK_CONV;
157 if (!list_empty(&res->lr_waiting)) {
158 list_add(&lock->l_res_link, res->lr_waiting.prev);
159 rc = ELDLM_BLOCK_WAIT;
162 incompat = ldlm_notify_incompatible(&res->lr_granted, lock);
164 list_add(&lock->l_res_link, res->lr_waiting.prev);
165 rc = ELDLM_BLOCK_GRANTED;
169 list_add(&lock->l_res_link, &res->lr_granted);
170 lock->l_granted_mode = mode;
171 if (mode < res->lr_most_restr)
172 res->lr_most_restr = mode;
174 /* XXX call the completion call back function */
180 spin_unlock(&res->lr_lock);
184 ldlm_error_t ldlm_local_lock_cancel(struct obd_device *obddev,
185 struct ldlm_handle *lockh)
187 struct ldlm_lock *lock;
188 struct ldlm_resource *res = lock->l_resource;
191 lock = (struct ldlm_lock *)(unsigned long)lockh->addr;
192 list_del(&lock->l_res_link);
194 kmem_cache_free(ldlm_lock_slab, lock);
195 if (ldlm_resource_put(lock->l_resource)) {
200 ldlm_reprocess_queue(&res->lr_converting, &res->lr_granted);
201 if (list_empty(&res->lr_converting))
202 ldlm_reprocess_queue(&res->lr_waiting, &res->lr_granted);
207 void ldlm_lock_dump(struct ldlm_lock *lock)
211 if (RES_VERSION_SIZE != 4)
214 snprintf(ver, sizeof(ver), "%x %x %x %x",
215 lock->l_version[0], lock->l_version[1],
216 lock->l_version[2], lock->l_version[3]);
218 CDEBUG(D_OTHER, " -- Lock dump: %p (%s)\n", lock, ver);
219 CDEBUG(D_OTHER, " Parent: %p\n", lock->l_parent);
220 CDEBUG(D_OTHER, " Requested mode: %d, granted mode: %d\n",
221 (int)lock->l_req_mode, (int)lock->l_granted_mode);