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,
35 static int ldlm_enqueue(struct ptlrpc_request *req)
37 struct ldlm_reply *dlm_rep;
38 struct ldlm_request *dlm_req;
39 struct lustre_msg *msg, *req_msg;
42 int bufsize = sizeof(*dlm_rep);
44 rc = lustre_pack_msg(1, &bufsize, NULL, &req->rq_replen,
47 CERROR("out of memory\n");
48 req->rq_status = -ENOMEM;
51 msg = (struct lustre_msg *)req->rq_repbuf;
52 req_msg = req->rq_req.lustre;
53 dlm_rep = lustre_msg_buf(0, msg);
54 dlm_req = lustre_msg_buf(0, req_msg);
56 msg->xid = req_msg->xid;
58 err = ldlm_local_lock_enqueue(req->rq_obd, dlm_req->ns_id,
59 &dlm_req->parent_res_handle,
60 &dlm_req->parent_lock_handle,
61 dlm_req->res_id, dlm_req->mode,
62 &dlm_req->flags, ldlm_client_callback,
65 lustre_msg_buf(1, req_msg),
66 &dlm_rep->lock_handle);
67 msg->status = HTON__u32(err);
73 static int ldlm_handle(struct obd_device *dev, struct ptlrpc_service *svc,
74 struct ptlrpc_request *req)
77 struct ptlreq_hdr *hdr;
81 hdr = (struct ptlreq_hdr *)req->rq_reqbuf;
83 if (NTOH__u32(hdr->type) != PTL_RPC_REQUEST) {
84 CERROR("lustre_ldlm: wrong packet type sent %d\n",
85 NTOH__u32(hdr->type));
90 rc = lustre_unpack_msg(req->rq_reqbuf, req->rq_reqlen);
91 req->rq_reqhdr = (void *)req->rq_reqbuf;
93 CERROR("lustre_ldlm: Invalid request\n");
97 switch (req->rq_reqhdr->opc) {
99 CDEBUG(D_INODE, "enqueue\n");
100 OBD_FAIL_RETURN(req, OBD_FAIL_LDLM_ENQUEUE);
101 rc = ldlm_enqueue(req);
105 CDEBUG(D_INODE, "convert\n");
106 OBD_FAIL_RETURN(req, OBD_FAIL_LDLM_CONVERT);
107 rc = ldlm_convert(req);
111 CDEBUG(D_INODE, "cancel\n");
112 OBD_FAIL_RETURN(req, OBD_FAIL_LDLM_CANCEL);
113 rc = ldlm_cancel(req);
117 CDEBUG(D_INODE, "callback\n");
118 OBD_FAIL_RETURN(req, OBD_FAIL_LDLM_CALLBACK);
119 rc = ldlm_callback(req);
124 rc = ptlrpc_error(dev, svc, req);
131 CERROR("no header\n");
135 if( req->rq_status) {
136 ptlrpc_error(dev, svc, req);
138 CDEBUG(D_NET, "sending reply\n");
139 ptlrpc_reply(dev, svc, req);
147 static int ldlm_iocontrol(int cmd, struct obd_conn *conn, int len, void *karg,
150 struct obd_device *obddev = conn->oc_dev;
155 if ( _IOC_TYPE(cmd) != IOC_LDLM_TYPE ||
156 _IOC_NR(cmd) < IOC_LDLM_MIN_NR ||
157 _IOC_NR(cmd) > IOC_LDLM_MAX_NR ) {
158 CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
159 _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
165 case IOC_LDLM_TEST: {
166 err = ldlm_test(obddev);
167 CERROR("-- done err %d\n", err);
180 static int ldlm_setup(struct obd_device *obddev, obd_count len, void *data)
182 struct ldlm_obd *ldlm = &obddev->u.ldlm;
186 INIT_LIST_HEAD(&obddev->u.ldlm.ldlm_namespaces);
187 obddev->u.ldlm.ldlm_lock = SPIN_LOCK_UNLOCKED;
189 ldlm->ldlm_service = ptlrpc_init_svc(64 * 1024,
192 "self", ldlm_handle);
194 rpc_register_service(ldlm->ldlm_service, "self");
196 err = ptlrpc_start_thread(obddev, ldlm->ldlm_service, "lustre_dlm");
198 CERROR("cannot start thread\n");
204 static int ldlm_cleanup(struct obd_device *obddev)
206 struct ldlm_obd *ldlm = &obddev->u.ldlm;
209 ptlrpc_stop_thread(ldlm->ldlm_service);
210 rpc_unregister_service(ldlm->ldlm_service);
212 if (!list_empty(&ldlm->ldlm_service->srv_reqs)) {
213 // XXX reply with errors and clean up
214 CERROR("Request list not empty!\n");
217 rpc_unregister_service(ldlm->ldlm_service);
218 OBD_FREE(ldlm->ldlm_service, sizeof(*ldlm->ldlm_service));
224 struct obd_ops ldlm_obd_ops = {
225 o_iocontrol: ldlm_iocontrol,
227 o_cleanup: ldlm_cleanup,
228 o_connect: gen_connect,
229 o_disconnect: gen_disconnect
233 static int __init ldlm_init(void)
235 int rc = obd_register_type(&ldlm_obd_ops, OBD_LDLM_DEVICENAME);
239 ldlm_resource_slab = kmem_cache_create("ldlm_resources",
240 sizeof(struct ldlm_resource), 0,
241 SLAB_HWCACHE_ALIGN, NULL, NULL);
242 if (ldlm_resource_slab == NULL)
245 ldlm_lock_slab = kmem_cache_create("ldlm_locks",
246 sizeof(struct ldlm_lock), 0,
247 SLAB_HWCACHE_ALIGN, NULL, NULL);
248 if (ldlm_lock_slab == NULL) {
249 kmem_cache_destroy(ldlm_resource_slab);
256 static void __exit ldlm_exit(void)
258 obd_unregister_type(OBD_LDLM_DEVICENAME);
259 kmem_cache_destroy(ldlm_resource_slab);
260 kmem_cache_destroy(ldlm_lock_slab);
263 MODULE_AUTHOR("Cluster File Systems, Inc. <braam@clusterfs.com>");
264 MODULE_DESCRIPTION("Lustre Lock Management Module v0.1");
265 MODULE_LICENSE("GPL");
267 module_init(ldlm_init);
268 module_exit(ldlm_exit);