Whamcloud - gitweb
- I had set the rpc buffer size down to 4k to ease testing, the smaller
[fs/lustre-release.git] / lustre / ost / ost_handler.c
1 /*
2  *  ost/ost_handler.c
3  *  Storage Target Handling functions
4  *  
5  *  Lustre Object Server Module (OST)
6  * 
7  *  Copyright (C) 2001, 2002 Cluster File Systems, Inc.
8  *
9  *  This code is issued under the GNU General Public License.
10  *  See the file COPYING in this distribution
11  *
12  *  by Peter Braam <braam@clusterfs.com>
13  * 
14  *  This server is single threaded at present (but can easily be multi
15  *  threaded). For testing and management it is treated as an
16  *  obd_device, although it does not export a full OBD method table
17  *  (the requests are coming in over the wire, so object target
18  *  modules do not have a full method table.)
19  * 
20  */
21
22
23 #define EXPORT_SYMTAB
24
25 #include <linux/version.h>
26 #include <linux/module.h>
27 #include <linux/fs.h>
28 #include <linux/stat.h>
29 #include <linux/locks.h>
30 #include <linux/ext2_fs.h>
31 #include <linux/quotaops.h>
32 #include <asm/unistd.h>
33 #include <linux/obd_support.h>
34 #include <linux/obd.h>
35 #include <linux/obd_class.h>
36 #include <linux/lustre_lib.h>
37 #include <linux/lustre_idl.h>
38 #include <linux/lustre_mds.h>
39 #include <linux/obd_class.h>
40
41 // for testing
42 static int ost_queue_req(struct obd_device *obddev, struct ptlrpc_request *req)
43 {
44         struct ptlrpc_request *srv_req; 
45         struct ost_obd *ost = &obddev->u.ost;
46         
47         if (!ost) { 
48                 EXIT;
49                 return -1;
50         }
51
52         OBD_ALLOC(srv_req, sizeof(*srv_req));
53         if (!srv_req) { 
54                 EXIT;
55                 return -ENOMEM;
56         }
57
58         printk("---> OST at %d %p, incoming req %p, srv_req %p\n", 
59                __LINE__, ost, req, srv_req);
60
61         memset(srv_req, 0, sizeof(*req)); 
62
63         /* move the request buffer */
64         srv_req->rq_reqbuf = req->rq_reqbuf;
65         srv_req->rq_reqlen    = req->rq_reqlen;
66         srv_req->rq_ost = ost;
67
68         /* remember where it came from */
69         srv_req->rq_reply_handle = req;
70
71         list_add(&srv_req->rq_list, &ost->ost_reqs); 
72         wake_up(&ost->ost_waitq);
73         return 0;
74 }
75
76 int ost_reply(struct obd_device *obddev, struct ptlrpc_request *req)
77 {
78         struct ptlrpc_request *clnt_req = req->rq_reply_handle;
79
80         ENTRY;
81
82         if (req->rq_ost->ost_service != NULL) {
83                 /* This is a request that came from the network via portals. */
84
85                 /* FIXME: we need to increment the count of handled events */
86                 ptl_send_buf(req, &req->rq_peer, OST_REPLY_PORTAL, 0);
87         } else {
88                 /* This is a local request that came from another thread. */
89
90                 /* move the reply to the client */ 
91                 clnt_req->rq_replen = req->rq_replen;
92                 clnt_req->rq_repbuf = req->rq_repbuf;
93                 req->rq_repbuf = NULL;
94                 req->rq_replen = 0;
95
96                 /* free the request buffer */
97                 OBD_FREE(req->rq_reqbuf, req->rq_reqlen);
98                 req->rq_reqbuf = NULL;
99
100                 /* wake up the client */ 
101                 wake_up_interruptible(&clnt_req->rq_wait_for_rep); 
102         }
103
104         EXIT;
105         return 0;
106 }
107
108 int ost_error(struct obd_device *obddev, struct ptlrpc_request *req)
109 {
110         struct ptlrep_hdr *hdr;
111
112         ENTRY;
113
114         OBD_ALLOC(hdr, sizeof(*hdr));
115         if (!hdr) { 
116                 EXIT;
117                 return -ENOMEM;
118         }
119
120         memset(hdr, 0, sizeof(*hdr));
121         
122         hdr->seqno = req->rq_reqhdr->seqno;
123         hdr->status = req->rq_status; 
124         hdr->type = OST_TYPE_ERR;
125
126         req->rq_repbuf = (char *)hdr;
127         req->rq_replen = sizeof(*hdr); 
128
129         EXIT;
130         return ost_reply(obddev, req);
131 }
132
133 static int ost_destroy(struct ost_obd *ost, struct ptlrpc_request *req)
134 {
135         struct obd_conn conn; 
136         int rc;
137
138         ENTRY;
139         
140         conn.oc_id = req->rq_req.ost->connid;
141         conn.oc_dev = ost->ost_tgt;
142
143         rc = ost_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep.ost,
144                           &req->rq_replen, &req->rq_repbuf); 
145         if (rc) { 
146                 printk("ost_destroy: cannot pack reply\n"); 
147                 return rc;
148         }
149
150         req->rq_rep.ost->result =ost->ost_tgt->obd_type->typ_ops->o_destroy
151                 (&conn, &req->rq_req.ost->oa); 
152
153         EXIT;
154         return 0;
155 }
156
157 static int ost_getattr(struct ost_obd *ost, struct ptlrpc_request *req)
158 {
159         struct obd_conn conn; 
160         int rc;
161
162         ENTRY;
163         printk("ost getattr entered\n"); 
164         
165         conn.oc_id = req->rq_req.ost->connid;
166         conn.oc_dev = ost->ost_tgt;
167
168         rc = ost_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep.ost,
169                           &req->rq_replen, &req->rq_repbuf); 
170         if (rc) { 
171                 printk("ost_getattr: cannot pack reply\n"); 
172                 return rc;
173         }
174         req->rq_rep.ost->oa.o_id = req->rq_req.ost->oa.o_id;
175         req->rq_rep.ost->oa.o_valid = req->rq_req.ost->oa.o_valid;
176
177         req->rq_rep.ost->result =ost->ost_tgt->obd_type->typ_ops->o_getattr
178                 (&conn, &req->rq_rep.ost->oa); 
179
180         EXIT;
181         return 0;
182 }
183
184 static int ost_create(struct ost_obd *ost, struct ptlrpc_request *req)
185 {
186         struct obd_conn conn; 
187         int rc;
188
189         ENTRY;
190         
191         conn.oc_id = req->rq_req.ost->connid;
192         conn.oc_dev = ost->ost_tgt;
193
194         rc = ost_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep.ost,
195                           &req->rq_replen, &req->rq_repbuf); 
196         if (rc) { 
197                 printk("ost_create: cannot pack reply\n"); 
198                 return rc;
199         }
200
201         memcpy(&req->rq_rep.ost->oa, &req->rq_req.ost->oa, sizeof(req->rq_req.ost->oa));
202
203         req->rq_rep.ost->result =ost->ost_tgt->obd_type->typ_ops->o_create
204                 (&conn, &req->rq_rep.ost->oa); 
205
206         EXIT;
207         return 0;
208 }
209
210
211 static int ost_setattr(struct ost_obd *ost, struct ptlrpc_request *req)
212 {
213         struct obd_conn conn; 
214         int rc;
215
216         ENTRY;
217         
218         conn.oc_id = req->rq_req.ost->connid;
219         conn.oc_dev = ost->ost_tgt;
220
221         rc = ost_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep.ost,
222                           &req->rq_replen, &req->rq_repbuf); 
223         if (rc) { 
224                 printk("ost_setattr: cannot pack reply\n"); 
225                 return rc;
226         }
227
228         memcpy(&req->rq_rep.ost->oa, &req->rq_req.ost->oa,
229                sizeof(req->rq_req.ost->oa));
230
231         req->rq_rep.ost->result =ost->ost_tgt->obd_type->typ_ops->o_setattr
232                 (&conn, &req->rq_rep.ost->oa); 
233
234         EXIT;
235         return 0;
236 }
237
238 static int ost_connect(struct ost_obd *ost, struct ptlrpc_request *req)
239 {
240         struct obd_conn conn; 
241         int rc;
242
243         ENTRY;
244         
245         conn.oc_dev = ost->ost_tgt;
246
247         rc = ost_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep.ost,
248                           &req->rq_replen, &req->rq_repbuf); 
249         if (rc) { 
250                 printk("ost_setattr: cannot pack reply\n"); 
251                 return rc;
252         }
253
254         req->rq_rep.ost->result =ost->ost_tgt->obd_type->typ_ops->o_connect(&conn);
255
256         printk("ost_connect: rep buffer %p, id %d\n", req->rq_repbuf, 
257                conn.oc_id);
258         req->rq_rep.ost->connid = conn.oc_id;
259         EXIT;
260         return 0;
261 }
262
263 static int ost_disconnect(struct ost_obd *ost, struct ptlrpc_request *req)
264 {
265         struct obd_conn conn; 
266         int rc;
267
268         ENTRY;
269         
270         conn.oc_dev = ost->ost_tgt;
271         conn.oc_id = req->rq_req.ost->connid;
272
273         rc = ost_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep.ost,
274                           &req->rq_replen, &req->rq_repbuf); 
275         if (rc) { 
276                 printk("ost_setattr: cannot pack reply\n"); 
277                 return rc;
278         }
279
280         req->rq_rep.ost->result =ost->ost_tgt->obd_type->typ_ops->o_disconnect(&conn);
281
282         EXIT;
283         return 0;
284 }
285
286 static int ost_get_info(struct ost_obd *ost, struct ptlrpc_request *req)
287 {
288         struct obd_conn conn; 
289         int rc;
290         int vallen;
291         void *val;
292         char *ptr; 
293
294         ENTRY;
295         
296         conn.oc_id = req->rq_req.ost->connid;
297         conn.oc_dev = ost->ost_tgt;
298
299         ptr = ost_req_buf1(req->rq_req.ost);
300         req->rq_rep.ost->result =ost->ost_tgt->obd_type->typ_ops->o_get_info
301                 (&conn, req->rq_req.ost->buflen1, ptr, &vallen, &val); 
302
303         rc = ost_pack_rep(val, vallen, NULL, 0, &req->rq_rephdr, &req->rq_rep.ost,
304                           &req->rq_replen, &req->rq_repbuf); 
305         if (rc) { 
306                 printk("ost_setattr: cannot pack reply\n"); 
307                 return rc;
308         }
309
310         EXIT;
311         return 0;
312 }
313
314 int ost_brw(struct ost_obd *obddev, struct ptlrpc_request *req)
315 {
316         struct obd_conn conn; 
317         int rc;
318         int i, j;
319         int objcount, niocount;
320         char *tmp1, *tmp2, *end2;
321         char *res;
322         int cmd;
323         struct niobuf *nb, *src, *dst;
324         struct obd_ioobj *ioo;
325         struct ost_req *r = req->rq_req.ost;
326
327         ENTRY;
328         
329         tmp1 = ost_req_buf1(r);
330         tmp2 = ost_req_buf2(r);
331         end2 = tmp2 + req->rq_req.ost->buflen2;
332         objcount = r->buflen1 / sizeof(*ioo); 
333         niocount = r->buflen2 / sizeof(*nb); 
334         cmd = r->cmd;
335
336         conn.oc_id = req->rq_req.ost->connid;
337         conn.oc_dev = req->rq_ost->ost_tgt;
338
339         rc = ost_pack_rep(NULL, niocount, NULL, 0, 
340                           &req->rq_rephdr, &req->rq_rep.ost,
341                           &req->rq_replen, &req->rq_repbuf); 
342         if (rc) { 
343                 printk("ost_create: cannot pack reply\n"); 
344                 return rc;
345         }
346         res = ost_rep_buf1(req->rq_rep.ost); 
347
348         for (i=0; i < objcount; i++) { 
349                 ost_unpack_ioo((void *)&tmp1, &ioo);
350                 if (tmp2 + ioo->ioo_bufcnt > end2) { 
351                         rc = -EFAULT;
352                         break; 
353                 }
354                 for (j = 0 ; j < ioo->ioo_bufcnt ; j++) { 
355                         ost_unpack_niobuf((void *)&tmp2, &nb); 
356                 }
357         }
358
359         /* The unpackers move tmp1 and tmp2, so reset them before using */
360         tmp1 = ost_req_buf1(r);
361         tmp2 = ost_req_buf2(r);
362         req->rq_rep.ost->result = 
363                 req->rq_ost->ost_tgt->obd_type->typ_ops->o_preprw
364                 (cmd, &conn, objcount, (struct obd_ioobj *)tmp1, 
365                  niocount, (struct niobuf *)tmp2, (struct niobuf *)res); 
366
367         if (cmd == OBD_BRW_WRITE) { 
368                 for (i=0; i<niocount; i++) { 
369                         src = &((struct niobuf *)tmp2)[i];
370                         dst = &((struct niobuf *)res)[i];
371                         memcpy((void *)(unsigned long)dst->addr, 
372                                (void *)(unsigned long)src->addr, 
373                                src->len);
374                 }
375         } else { 
376                 for (i=0; i<niocount; i++) { 
377                         dst = &((struct niobuf *)tmp2)[i];
378                         src = &((struct niobuf *)res)[i];
379                         memcpy((void *)(unsigned long)dst->addr, 
380                                (void *)(unsigned long)src->addr, 
381                                PAGE_SIZE); 
382                 }
383         }
384
385         req->rq_rep.ost->result = 
386                 req->rq_ost->ost_tgt->obd_type->typ_ops->o_commitrw
387                 (cmd, &conn, objcount, (struct obd_ioobj *)tmp1, 
388                  niocount, (struct niobuf *)res); 
389
390         EXIT;
391         return 0;
392 }
393
394 int ost_handle(struct obd_device *obddev, struct ptlrpc_request *req)
395 {
396         int rc;
397         struct ost_obd *ost = &obddev->u.ost;
398         struct ptlreq_hdr *hdr;
399
400         ENTRY;
401         printk("ost_handle: req at %p\n", req); 
402
403         hdr = (struct ptlreq_hdr *)req->rq_reqbuf;
404         if (NTOH__u32(hdr->type) != OST_TYPE_REQ) {
405                 printk("lustre_ost: wrong packet type sent %d\n",
406                        NTOH__u32(hdr->type));
407                 rc = -EINVAL;
408                 goto out;
409         }
410
411         rc = ost_unpack_req(req->rq_reqbuf, req->rq_reqlen, 
412                             &req->rq_reqhdr, &req->rq_req.ost);
413         if (rc) { 
414                 printk("lustre_ost: Invalid request\n");
415                 EXIT; 
416                 goto out;
417         }
418
419         switch (req->rq_reqhdr->opc) { 
420
421         case OST_CONNECT:
422                 CDEBUG(D_INODE, "connect\n");
423                 rc = ost_connect(ost, req);
424                 break;
425         case OST_DISCONNECT:
426                 CDEBUG(D_INODE, "disconnect\n");
427                 rc = ost_disconnect(ost, req);
428                 break;
429         case OST_GET_INFO:
430                 CDEBUG(D_INODE, "get_info\n");
431                 rc = ost_get_info(ost, req);
432                 break;
433         case OST_CREATE:
434                 CDEBUG(D_INODE, "create\n");
435                 rc = ost_create(ost, req);
436                 break;
437         case OST_DESTROY:
438                 CDEBUG(D_INODE, "destroy\n");
439                 rc = ost_destroy(ost, req);
440                 break;
441         case OST_GETATTR:
442                 CDEBUG(D_INODE, "getattr\n");
443                 rc = ost_getattr(ost, req);
444                 break;
445         case OST_SETATTR:
446                 CDEBUG(D_INODE, "setattr\n");
447                 rc = ost_setattr(ost, req);
448                 break;
449         case OST_BRW:
450                 CDEBUG(D_INODE, "brw\n");
451                 rc = ost_brw(ost, req);
452                 break;
453         default:
454                 req->rq_status = -ENOTSUPP;
455                 return ost_error(obddev, req);
456         }
457
458 out:
459         req->rq_status = rc;
460         if (rc) { 
461                 printk("ost: processing error %d\n", rc);
462                 ost_error(obddev, req);
463         } else { 
464                 CDEBUG(D_INODE, "sending reply\n"); 
465                 ost_reply(obddev, req); 
466         }
467
468         return 0;
469 }
470
471 int ost_main(void *arg)
472 {
473         struct obd_device *obddev = (struct obd_device *) arg;
474         struct ost_obd *ost = &obddev->u.ost;
475         ENTRY;
476
477         lock_kernel();
478         daemonize();
479         spin_lock_irq(&current->sigmask_lock);
480         sigfillset(&current->blocked);
481         recalc_sigpending(current);
482         spin_unlock_irq(&current->sigmask_lock);
483
484         sprintf(current->comm, "lustre_ost");
485
486         /* Record that the  thread is running */
487         ost->ost_thread = current;
488         wake_up(&ost->ost_done_waitq); 
489
490         /* XXX maintain a list of all managed devices: insert here */
491
492         /* And now, wait forever for commit wakeup events. */
493         while (1) {
494                 int rc; 
495
496                 if (ost->ost_flags & OST_EXIT)
497                         break;
498
499                 wake_up(&ost->ost_done_waitq);
500                 interruptible_sleep_on(&ost->ost_waitq);
501
502                 CDEBUG(D_INODE, "lustre_ost wakes\n");
503                 CDEBUG(D_INODE, "pick up req here and continue\n"); 
504
505
506                 if (ost->ost_service != NULL) {
507                         ptl_event_t ev;
508
509                         while (1) {
510                                 struct ptlrpc_request request;
511                                 struct ptlrpc_service *service;
512
513                                 rc = PtlEQGet(ost->ost_service->srv_eq_h, &ev);
514                                 if (rc != PTL_OK && rc != PTL_EQ_DROPPED)
515                                         break;
516
517                                 service = (struct ptlrpc_service *)ev.mem_desc.user_ptr;
518
519                                 /* FIXME: If we move to an event-driven model,
520                                  * we should put the request on the stack of
521                                  * mds_handle instead. */
522                                 memset(&request, 0, sizeof(request));
523                                 request.rq_reqbuf = ev.mem_desc.start +
524                                         ev.offset;
525                                 request.rq_reqlen = ev.mem_desc.length;
526                                 request.rq_ost = ost;
527                                 request.rq_xid = ev.match_bits;
528
529                                 request.rq_peer.peer_nid = ev.initiator.nid;
530                                 /* FIXME: this NI should be the incoming NI.
531                                  * We don't know how to find that from here. */
532                                 request.rq_peer.peer_ni =
533                                         ost->ost_service->srv_self.peer_ni;
534                                 rc = ost_handle(obddev, &request);
535
536                                 /* Inform the rpc layer the event has been handled */
537                                 ptl_received_rpc(service);
538                         }
539                 } else {
540                         struct ptlrpc_request *request;
541
542                         if (list_empty(&ost->ost_reqs)) { 
543                                 CDEBUG(D_INODE, "woke because of timer\n"); 
544                         } else { 
545                                 request = list_entry(ost->ost_reqs.next,
546                                                      struct ptlrpc_request,
547                                                      rq_list);
548                                 list_del(&request->rq_list);
549                                 rc = ost_handle(obddev, request); 
550                         }
551                 }
552         }
553
554         /* XXX maintain a list of all managed devices: cleanup here */
555
556         ost->ost_thread = NULL;
557         wake_up(&ost->ost_done_waitq);
558         printk("lustre_ost: exiting\n");
559         return 0;
560 }
561
562 static void ost_stop_srv_thread(struct ost_obd *ost)
563 {
564         ost->ost_flags |= OST_EXIT;
565
566         while (ost->ost_thread) {
567                 wake_up(&ost->ost_waitq);
568                 sleep_on(&ost->ost_done_waitq);
569         }
570 }
571
572 static void ost_start_srv_thread(struct obd_device *obd)
573 {
574         struct ost_obd *ost = &obd->u.ost;
575         ENTRY;
576
577         init_waitqueue_head(&ost->ost_waitq);
578         init_waitqueue_head(&ost->ost_done_waitq);
579         kernel_thread(ost_main, (void *)obd, 
580                       CLONE_VM | CLONE_FS | CLONE_FILES);
581         while (!ost->ost_thread) 
582                 sleep_on(&ost->ost_done_waitq);
583         EXIT;
584 }
585
586 /* mount the file system (secretly) */
587 static int ost_setup(struct obd_device *obddev, obd_count len,
588                         void *buf)
589                         
590 {
591         struct obd_ioctl_data* data = buf;
592         struct ost_obd *ost = &obddev->u.ost;
593         struct obd_device *tgt;
594         struct lustre_peer peer;
595         int err; 
596         ENTRY;
597
598         if (data->ioc_dev  < 0 || data->ioc_dev > MAX_OBD_DEVICES) { 
599                 EXIT;
600                 return -ENODEV;
601         }
602
603         tgt = &obd_dev[data->ioc_dev];
604         ost->ost_tgt = tgt;
605         if ( ! (tgt->obd_flags & OBD_ATTACHED) || 
606              ! (tgt->obd_flags & OBD_SET_UP) ){
607                 printk("device not attached or not set up (%d)\n", 
608                        data->ioc_dev);
609                 EXIT;
610                 return -EINVAL;
611         } 
612
613         ost->ost_conn.oc_dev = tgt;
614         err = tgt->obd_type->typ_ops->o_connect(&ost->ost_conn);
615         if (err) { 
616                 printk("lustre ost: fail to connect to device %d\n", 
617                        data->ioc_dev); 
618                 return -EINVAL;
619         }
620
621         INIT_LIST_HEAD(&ost->ost_reqs);
622         ost->ost_thread = NULL;
623         ost->ost_flags = 0;
624
625         spin_lock_init(&obddev->u.ost.ost_lock);
626
627         err = kportal_uuid_to_peer("self", &peer);
628         if (err == 0) {
629                 OBD_ALLOC(ost->ost_service, sizeof(*ost->ost_service));
630                 if (ost->ost_service == NULL)
631                         return -ENOMEM;
632                 ost->ost_service->srv_buf_size = 64 * 1024;
633                 ost->ost_service->srv_portal = OST_REQUEST_PORTAL;
634                 memcpy(&ost->ost_service->srv_self, &peer, sizeof(peer));
635                 ost->ost_service->srv_wait_queue = &ost->ost_waitq;
636
637                 rpc_register_service(ost->ost_service, "self");
638         }
639
640         ost_start_srv_thread(obddev);
641
642         MOD_INC_USE_COUNT;
643         EXIT; 
644         return 0;
645
646
647 static int ost_cleanup(struct obd_device * obddev)
648 {
649         struct ost_obd *ost = &obddev->u.ost;
650         struct obd_device *tgt;
651         int err;
652
653         ENTRY;
654
655         if ( !(obddev->obd_flags & OBD_SET_UP) ) {
656                 EXIT;
657                 return 0;
658         }
659
660         if ( !list_empty(&obddev->obd_gen_clients) ) {
661                 printk(KERN_WARNING __FUNCTION__ ": still has clients!\n");
662                 EXIT;
663                 return -EBUSY;
664         }
665
666         ost_stop_srv_thread(ost);
667         rpc_unregister_service(ost->ost_service);
668         OBD_FREE(ost->ost_service, sizeof(*ost->ost_service));
669
670         if (!list_empty(&ost->ost_reqs)) {
671                 // XXX reply with errors and clean up
672                 CDEBUG(D_INODE, "Request list not empty!\n");
673         }
674
675         tgt = ost->ost_tgt;
676         err = tgt->obd_type->typ_ops->o_disconnect(&ost->ost_conn);
677         if (err) { 
678                 printk("lustre ost: fail to disconnect device\n");
679                 return -EINVAL;
680         }
681         
682
683         MOD_DEC_USE_COUNT;
684         EXIT;
685         return 0;
686 }
687
688 /* use obd ops to offer management infrastructure */
689 static struct obd_ops ost_obd_ops = {
690         o_setup:       ost_setup,
691         o_cleanup:     ost_cleanup,
692 };
693
694 static int __init ost_init(void)
695 {
696         obd_register_type(&ost_obd_ops, LUSTRE_OST_NAME);
697         return 0;
698 }
699
700 static void __exit ost_exit(void)
701 {
702         obd_unregister_type(LUSTRE_OST_NAME);
703 }
704
705 MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
706 MODULE_DESCRIPTION("Lustre Object Storage Target (OST) v0.01");
707 MODULE_LICENSE("GPL");
708
709 // for testing (maybe this stays)
710 EXPORT_SYMBOL(ost_queue_req);
711
712 module_init(ost_init);
713 module_exit(ost_exit);