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_class.h>
22 #include <linux/lustre_dlm.h>
23 #include <linux/lustre_net.h>
25 extern kmem_cache_t *ldlm_resource_slab;
26 extern kmem_cache_t *ldlm_lock_slab;
28 static int ldlm_client_callback(struct ldlm_lock *lock, struct ldlm_lock *new,
29 void *data, __u32 data_len)
35 static int ldlm_enqueue(struct ptlrpc_request *req)
37 struct ldlm_reply *dlm_rep;
38 struct ldlm_request *dlm_req;
40 int rc, bufsize = sizeof(*dlm_rep);
42 rc = lustre_pack_msg(1, &bufsize, NULL, &req->rq_replen,
45 CERROR("out of memory\n");
46 req->rq_status = -ENOMEM;
49 req->rq_repmsg = (struct lustre_msg *)req->rq_repbuf;
50 dlm_rep = lustre_msg_buf(req->rq_repmsg, 0);
51 dlm_req = lustre_msg_buf(req->rq_reqmsg, 0);
53 err = ldlm_local_lock_enqueue(req->rq_obd,
55 &dlm_req->parent_lock_handle,
58 &dlm_req->lock_extent,
63 lustre_msg_buf(req->rq_reqmsg, 1),
64 req->rq_reqmsg->buflens[1],
65 &dlm_rep->lock_handle);
68 CERROR("local_lock_enqueue: %d\n", err);
73 static int ldlm_handle(struct obd_device *dev, struct ptlrpc_service *svc,
74 struct ptlrpc_request *req)
79 rc = lustre_unpack_msg(req->rq_reqbuf, req->rq_reqlen);
80 req->rq_reqmsg = (struct lustre_msg *)req->rq_reqbuf;
82 CERROR("lustre_ldlm: Invalid request\n");
86 if (req->rq_reqmsg->type != PTL_RPC_REQUEST) {
87 CERROR("lustre_ldlm: wrong packet type sent %d\n",
88 req->rq_reqmsg->type);
89 GOTO(out, rc = -EINVAL);
92 switch (req->rq_reqmsg->opc) {
94 CDEBUG(D_INODE, "enqueue\n");
95 OBD_FAIL_RETURN(OBD_FAIL_LDLM_ENQUEUE, 0);
96 rc = ldlm_enqueue(req);
100 CDEBUG(D_INODE, "convert\n");
101 OBD_FAIL_RETURN(OBD_FAIL_LDLM_CONVERT, 0);
102 rc = ldlm_convert(req);
106 CDEBUG(D_INODE, "cancel\n");
107 OBD_FAIL_RETURN(OBD_FAIL_LDLM_CANCEL, 0);
108 rc = ldlm_cancel(req);
112 CDEBUG(D_INODE, "callback\n");
113 OBD_FAIL_RETURN(OBD_FAIL_LDLM_CALLBACK, 0);
114 rc = ldlm_callback(req);
119 rc = ptlrpc_error(dev, svc, req);
126 CERROR("no header\n");
130 if( req->rq_status) {
131 ptlrpc_error(dev, svc, req);
133 CDEBUG(D_NET, "sending reply\n");
134 ptlrpc_reply(dev, svc, req);
140 static int ldlm_iocontrol(int cmd, struct obd_conn *conn, int len, void *karg,
143 struct obd_device *obddev = conn->oc_dev;
144 struct ptlrpc_client cl;
149 if ( _IOC_TYPE(cmd) != IOC_LDLM_TYPE ||
150 _IOC_NR(cmd) < IOC_LDLM_MIN_NR ||
151 _IOC_NR(cmd) > IOC_LDLM_MAX_NR ) {
152 CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
153 _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
158 err = ptlrpc_connect_client(-1, "ldlm",
159 LDLM_REQUEST_PORTAL, LDLM_REPLY_PORTAL,
162 CERROR("cannot create client\n");
167 case IOC_LDLM_TEST: {
168 err = ldlm_test(obddev);
169 CERROR("-- done err %d\n", err);
182 static int ldlm_setup(struct obd_device *obddev, obd_count len, void *data)
184 struct ldlm_obd *ldlm = &obddev->u.ldlm;
188 INIT_LIST_HEAD(&obddev->u.ldlm.ldlm_namespaces);
189 obddev->u.ldlm.ldlm_lock = SPIN_LOCK_UNLOCKED;
191 ldlm->ldlm_service = ptlrpc_init_svc(64 * 1024,
194 "self", ldlm_handle);
195 if (!ldlm->ldlm_service)
198 err = ptlrpc_start_thread(obddev, ldlm->ldlm_service, "lustre_dlm");
200 CERROR("cannot start thread\n");
206 static int cleanup_resource(struct ldlm_resource *res, struct list_head *q)
208 struct list_head *tmp, *pos;
211 list_for_each_safe(tmp, pos, q) {
212 struct ldlm_lock *lock;
215 /* Res was already cleaned up. */
219 lock = list_entry(tmp, struct ldlm_lock, l_res_link);
221 ldlm_resource_del_lock(lock);
222 ldlm_lock_free(lock);
223 rc = ldlm_resource_put(res);
229 static int do_free_namespace(struct ldlm_namespace *ns)
231 struct list_head *tmp, *pos;
234 for (i = 0; i < RES_HASH_SIZE; i++) {
235 list_for_each_safe(tmp, pos, &(ns->ns_hash[i])) {
236 struct ldlm_resource *res;
237 res = list_entry(tmp, struct ldlm_resource, lr_hash);
238 list_del_init(&res->lr_hash);
240 rc = cleanup_resource(res, &res->lr_granted);
242 rc = cleanup_resource(res, &res->lr_converting);
244 rc = cleanup_resource(res, &res->lr_waiting);
247 rc = ldlm_resource_put(res);
251 return ldlm_namespace_free(ns);
254 static int ldlm_free_all(struct obd_device *obddev)
256 struct list_head *tmp, *pos;
261 list_for_each_safe(tmp, pos, &obddev->u.ldlm.ldlm_namespaces) {
262 struct ldlm_namespace *ns;
263 ns = list_entry(tmp, struct ldlm_namespace, ns_link);
265 rc |= do_free_namespace(ns);
273 static int ldlm_cleanup(struct obd_device *obddev)
275 struct ldlm_obd *ldlm = &obddev->u.ldlm;
278 ptlrpc_stop_thread(ldlm->ldlm_service);
279 rpc_unregister_service(ldlm->ldlm_service);
281 if (!list_empty(&ldlm->ldlm_service->srv_reqs)) {
282 // XXX reply with errors and clean up
283 CERROR("Request list not empty!\n");
286 OBD_FREE(ldlm->ldlm_service, sizeof(*ldlm->ldlm_service));
288 if (ldlm_free_all(obddev)) {
289 CERROR("ldlm_free_all could not complete.\n");
297 struct obd_ops ldlm_obd_ops = {
298 o_iocontrol: ldlm_iocontrol,
300 o_cleanup: ldlm_cleanup,
301 o_connect: gen_connect,
302 o_disconnect: gen_disconnect
306 static int __init ldlm_init(void)
308 int rc = obd_register_type(&ldlm_obd_ops, OBD_LDLM_DEVICENAME);
312 ldlm_resource_slab = kmem_cache_create("ldlm_resources",
313 sizeof(struct ldlm_resource), 0,
314 SLAB_HWCACHE_ALIGN, NULL, NULL);
315 if (ldlm_resource_slab == NULL)
318 ldlm_lock_slab = kmem_cache_create("ldlm_locks",
319 sizeof(struct ldlm_lock), 0,
320 SLAB_HWCACHE_ALIGN, NULL, NULL);
321 if (ldlm_lock_slab == NULL) {
322 kmem_cache_destroy(ldlm_resource_slab);
329 static void __exit ldlm_exit(void)
331 obd_unregister_type(OBD_LDLM_DEVICENAME);
332 kmem_cache_destroy(ldlm_resource_slab);
333 kmem_cache_destroy(ldlm_lock_slab);
336 MODULE_AUTHOR("Cluster File Systems, Inc. <braam@clusterfs.com>");
337 MODULE_DESCRIPTION("Lustre Lock Management Module v0.1");
338 MODULE_LICENSE("GPL");
340 module_init(ldlm_init);
341 module_exit(ldlm_exit);