Whamcloud - gitweb
Don't update your trees yet..... Brian and I are trying to get our
[fs/lustre-release.git] / lustre / obdclass / class_obd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *              An implementation of a loadable kernel mode driver providing
5  *              multiple kernel/user space bidirectional communications links.
6  *
7  *              Author:         Alan Cox <alan@cymru.net>
8  *
9  *              This program is free software; you can redistribute it and/or
10  *              modify it under the terms of the GNU General Public License
11  *              version 2 as published by the Free Software Foundation.
12  *
13  *              Adapted to become the Linux 2.0 Coda pseudo device
14  *              Peter  Braam  <braam@maths.ox.ac.uk>
15  *              Michael Callahan <mjc@emmy.smith.edu>
16  *
17  *              Changes for Linux 2.1
18  *              Copyright (c) 1997 Carnegie-Mellon University
19  *
20  *              Redone again for Intermezzo
21  *              Copyright (c) 1998 Peter J. Braam
22  *
23  *              Hacked up again for simulated OBD
24  *              Copyright (c) 1999 Stelias Computing, Inc.
25  *                (authors {pschwan,braam}@stelias.com)
26  *              Copyright (C) 1999 Seagate Technology, Inc.
27  *              Copyright (C) 2001 Cluster File Systems, Inc.
28  *
29  *
30  */
31
32 #define EXPORT_SYMTAB
33 #include <linux/config.h> /* for CONFIG_PROC_FS */
34 #include <linux/module.h>
35 #include <linux/errno.h>
36 #include <linux/kernel.h>
37 #include <linux/major.h>
38 #include <linux/kmod.h>   /* for request_module() */
39 #include <linux/sched.h>
40 #include <linux/lp.h>
41 #include <linux/slab.h>
42 #include <linux/ioport.h>
43 #include <linux/fcntl.h>
44 #include <linux/delay.h>
45 #include <linux/skbuff.h>
46 #include <linux/proc_fs.h>
47 #include <linux/fs.h>
48 #include <linux/poll.h>
49 #include <linux/init.h>
50 #include <linux/list.h>
51 #include <asm/io.h>
52 #include <asm/system.h>
53 #include <asm/poll.h>
54 #include <asm/uaccess.h>
55 #include <linux/miscdevice.h>
56
57 #define DEBUG_SUBSYSTEM S_CLASS
58
59 #include <linux/obd_support.h>
60 #include <linux/obd_class.h>
61
62 static int obd_init_magic;
63 unsigned long obd_memory = 0;
64 unsigned long obd_fail_loc = 0;
65 struct obd_device obd_dev[MAX_OBD_DEVICES];
66 struct list_head obd_types;
67
68
69 /*  opening /dev/obd */
70 static int obd_class_open(struct inode * inode, struct file * file)
71 {
72         ENTRY;
73
74         file->private_data = NULL;
75         MOD_INC_USE_COUNT;
76         RETURN(0);
77 }
78
79 /*  closing /dev/obd */
80 static int obd_class_release(struct inode * inode, struct file * file)
81 {
82         ENTRY;
83
84         if (file->private_data)
85                 file->private_data = NULL;
86
87         MOD_DEC_USE_COUNT;
88         RETURN(0);
89 }
90
91 int obd_class_name2dev(char *name)
92 {
93         int res = -1;
94         int i;
95
96         for (i=0; i < MAX_OBD_DEVICES; i++) {
97                 struct obd_device *obd = &obd_dev[i];
98                 if (obd->obd_name && strcmp(name, obd->obd_name) == 0) {
99                         res = i;
100                         return res;
101                 }
102         }
103
104         return res;
105 }
106
107 int obd_class_uuid2dev(char *name)
108 {
109         int res = -1;
110         int i;
111
112         for (i=0; i < MAX_OBD_DEVICES; i++) {
113                 struct obd_device *obd = &obd_dev[i];
114                 if (obd->obd_name && strncmp(name, obd->obd_uuid, 37) == 0) {
115                         res = i;
116                         return res;
117                 }
118         }
119
120         return res;
121 }
122
123 /*
124  * support functions: we could use inter-module communication, but this
125  * is more portable to other OS's
126  */
127 static struct obd_type *obd_search_type(char *nm)
128 {
129         struct list_head *tmp;
130         struct obd_type *type;
131         CDEBUG(D_INFO, "SEARCH %s\n", nm);
132
133         tmp = &obd_types;
134         while ( (tmp = tmp->next) != &obd_types ) {
135                 type = list_entry(tmp, struct obd_type, typ_chain);
136                 CDEBUG(D_INFO, "TYP %s\n", type->typ_name);
137                 if (strlen(type->typ_name) == strlen(nm) &&
138                     strcmp(type->typ_name, nm) == 0 ) {
139                         return type;
140                 }
141         }
142         return NULL;
143 }
144
145 static struct obd_type *obd_nm_to_type(char *nm)
146 {
147         struct obd_type *type = obd_search_type(nm);
148
149 #ifdef CONFIG_KMOD
150         if ( !type ) {
151                 if ( !request_module(nm) ) {
152                         CDEBUG(D_INFO, "Loaded module '%s'\n", nm);
153                         type = obd_search_type(nm);
154                 } else {
155                         CDEBUG(D_INFO, "Can't load module '%s'\n", nm);
156                 }
157         }
158 #endif
159         return type;
160 }
161
162 inline void obd_data2conn(struct obd_conn *conn, struct obd_ioctl_data *data)
163 {
164         conn->addr = data->ioc_addr;
165         conn->cookie = data->ioc_cookie;
166 }
167
168
169 inline void obd_conn2data(struct obd_ioctl_data *data, struct obd_conn *conn)
170 {
171         data->ioc_addr = conn->addr;
172         data->ioc_cookie = conn->cookie;
173 }
174
175
176 /* to control /dev/obd */
177 static int obd_class_ioctl (struct inode * inode, struct file * filp,
178                             unsigned int cmd, unsigned long arg)
179 {
180         /* NOTE this must be larger than any of the ioctl data structs */
181         char buf[1024];
182         int len = 1024;
183         struct obd_ioctl_data *data;
184         struct obd_device *obd = filp->private_data;
185         struct obd_conn conn;
186         int rw = OBD_BRW_READ;
187         int err = 0;
188         ENTRY;
189
190         memset(buf, 0, sizeof(buf));
191
192         if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS &&
193             cmd != OBD_IOC_LIST &&
194             cmd != OBD_IOC_NAME2DEV && cmd != OBD_IOC_NEWDEV) {
195                 CERROR("OBD ioctl: No device\n");
196                 RETURN(-EINVAL);
197         }
198         if (obd_ioctl_getdata(buf, &len, (void *)arg)) {
199                 CERROR("OBD ioctl: data error\n");
200                 RETURN(-EINVAL);
201         }
202         data = (struct obd_ioctl_data *)buf;
203
204         switch (cmd) {
205         case TCGETS:
206                 RETURN(-EINVAL);
207         case OBD_IOC_DEVICE: {
208                 CDEBUG(D_IOCTL, "\n");
209                 if (data->ioc_dev >= MAX_OBD_DEVICES || data->ioc_dev < 0) {
210                         CERROR("OBD ioctl: DEVICE insufficient devices\n");
211                         RETURN(-EINVAL);
212                 }
213                 CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev);
214
215                 filp->private_data = &obd_dev[data->ioc_dev];
216                 RETURN(0);
217         }
218
219         case OBD_IOC_LIST: {
220                 int i;
221                 char *buf = data->ioc_bulk;
222                 int remains = data->ioc_inllen1;
223
224                 if (!data->ioc_inlbuf1) {
225                         CERROR("No buffer passed!\n");
226                         RETURN(-EINVAL);
227                 }
228
229
230                 for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
231                         int l;
232                         struct obd_device *obd = &obd_dev[i];
233                         if (!obd->obd_type) 
234                                 continue;
235                         l = snprintf(buf, remains, "%2d %s %s %s\n",
236                                      i, obd->obd_type->typ_name, 
237                                      obd->obd_name, obd->obd_uuid);
238                         buf +=l;
239                         remains -=l;
240                         if (remains <= 0) { 
241                                 CERROR("not enough space for device listing\n");
242                                 break;
243                         }
244                 }
245
246                 err = copy_to_user((int *)arg, data, len);
247                 RETURN(err);
248         }
249
250
251         case OBD_IOC_NAME2DEV: {
252                 /* Resolve a device name.  This does not change the
253                  * currently selected device.
254                  */
255                 int dev;
256
257                 if (!data->ioc_inlbuf1) {
258                         CERROR("No name passed!\n");
259                         RETURN(-EINVAL);
260                 }
261                 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
262                 dev = obd_class_name2dev(data->ioc_inlbuf1);
263                 data->ioc_dev = dev;
264                 if (dev == -1) {
265                         CDEBUG(D_IOCTL, "No device for name %s!\n",
266                                data->ioc_inlbuf1);
267                         RETURN(-EINVAL);
268                 }
269
270                 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
271                        dev);
272                 err = copy_to_user((int *)arg, data, sizeof(*data));
273                 RETURN(err);
274         }
275
276         case OBD_IOC_UUID2DEV: {
277                 /* Resolve a device uuid.  This does not change the
278                  * currently selected device.
279                  */
280                 int dev;
281
282                 if (!data->ioc_inlbuf1) {
283                         CERROR("No UUID passed!\n");
284                         RETURN(-EINVAL);
285                 }
286                 CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
287                 dev = obd_class_uuid2dev(data->ioc_inlbuf1);
288                 data->ioc_dev = dev;
289                 if (dev == -1) {
290                         CDEBUG(D_IOCTL, "No device for name %s!\n",
291                                data->ioc_inlbuf1);
292                         RETURN(-EINVAL);
293                 }
294
295                 CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
296                        dev);
297                 err = copy_to_user((int *)arg, data, sizeof(*data));
298                 RETURN(err);
299         }
300
301         case OBD_IOC_NEWDEV: {
302                 int dev = -1;
303                 int i;
304
305                 filp->private_data = NULL;
306                 for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
307                         struct obd_device *obd = &obd_dev[i];
308                         if (!obd->obd_type) {
309                                 filp->private_data = obd;
310                                 dev = i;
311                                 break;
312                         }
313                 }
314
315
316                 data->ioc_dev = dev;
317                 if (dev == -1)
318                         RETURN(-EINVAL);
319
320                 err = copy_to_user((int *)arg, data, sizeof(*data));
321                 RETURN(err);
322         }
323
324         case OBD_IOC_ATTACH: {
325                 struct obd_type *type;
326
327                 /* have we attached a type to this device */
328                 if (obd->obd_flags & OBD_ATTACHED) {
329                         CERROR("OBD: Device %d already typed as %s.\n",
330                                obd->obd_minor, MKSTR(obd->obd_type->typ_name));
331                         RETURN(-EBUSY);
332                 }
333
334                 CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n", 
335                        MKSTR(data->ioc_inlbuf1),
336                        MKSTR(data->ioc_inlbuf2), MKSTR(data->ioc_inlbuf3));
337
338                 /* find the type */
339                 type = obd_nm_to_type(data->ioc_inlbuf1);
340                 if (!type) {
341                         CERROR("OBD: unknown type dev %d\n", obd->obd_minor);
342                         RETURN(-EINVAL);
343                 }
344
345                 obd->obd_type = type;
346                 obd->obd_multi_count = 0;
347                 INIT_LIST_HEAD(&obd->obd_exports);
348
349                 /* do the attach */
350                 if (OBT(obd) && OBP(obd, attach))
351                         err = OBP(obd,attach)(obd, sizeof(*data), data);
352                 if (err) {
353                         obd->obd_type = NULL;
354                 } else {
355                         obd->obd_flags |= OBD_ATTACHED;
356                         type->typ_refcnt++;
357                         CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
358                                obd->obd_minor, data->ioc_inlbuf1);
359                         obd->obd_proc_entry =
360                                 proc_lustre_register_obd_device(obd);
361                         if (data->ioc_inlbuf2) {
362                                 int len = strlen(data->ioc_inlbuf2) + 1;
363                                 OBD_ALLOC(obd->obd_name, len + 1);
364                                 if (!obd->obd_name) {
365                                         CERROR("no memory\n");
366                                         LBUG();
367                                 }
368                                 memcpy(obd->obd_name, data->ioc_inlbuf2, len + 1);
369                         }
370                         if (data->ioc_inlbuf3) {
371                                 int len = strlen(data->ioc_inlbuf3);
372                                 if (len > 37) { 
373                                         CERROR("uuid should be shorter than 37 bytes\n");
374                                         if (obd->obd_name)
375                                                 OBD_FREE(obd->obd_name, 
376                                                          strlen(obd->obd_name) + 1);
377                                         RETURN(-EINVAL);
378                                 }
379                                 memcpy(obd->obd_uuid, data->ioc_inlbuf3, 
380                                        sizeof(obd->obd_uuid));
381                         }
382
383                         MOD_INC_USE_COUNT;
384                 }
385
386                 RETURN(err);
387         }
388
389         case OBD_IOC_DETACH: {
390                 ENTRY;
391                 if (obd->obd_flags & OBD_SET_UP) {
392                         CERROR("OBD device %d still set up\n", obd->obd_minor);
393                         RETURN(-EBUSY);
394                 }
395                 if (! (obd->obd_flags & OBD_ATTACHED) ) {
396                         CERROR("OBD device %d not attached\n", obd->obd_minor);
397                         RETURN(-ENODEV);
398                 }
399                 if ( !list_empty(&obd->obd_exports) ) {
400                         CERROR("OBD device %d has exports\n",
401                                obd->obd_minor);
402                         RETURN(-EBUSY);
403                 }
404
405                 if (obd->obd_name) {
406                         OBD_FREE(obd->obd_name, strlen(obd->obd_name)+ 1);
407                         obd->obd_name = NULL;
408                 }
409
410                 if (obd->obd_proc_entry)
411                         proc_lustre_release_obd_device(obd);
412
413                 obd->obd_flags &= ~OBD_ATTACHED;
414                 obd->obd_type->typ_refcnt--;
415                 obd->obd_type = NULL;
416                 MOD_DEC_USE_COUNT;
417                 RETURN(0);
418         }
419
420         case OBD_IOC_SETUP: {
421                 /* have we attached a type to this device? */
422                 if (!(obd->obd_flags & OBD_ATTACHED)) {
423                         CERROR("Device %d not attached\n", obd->obd_minor);
424                         RETURN(-ENODEV);
425                 }
426
427                 /* has this been done already? */
428                 if ( obd->obd_flags & OBD_SET_UP ) {
429                         CERROR("Device %d already setup (type %s)\n",
430                                obd->obd_minor, obd->obd_type->typ_name);
431                         RETURN(-EBUSY);
432                 }
433
434                 if ( OBT(obd) && OBP(obd, setup) )
435                         err = obd_setup(obd, sizeof(*data), data);
436
437                 if (!err) {
438                         obd->obd_type->typ_refcnt++;
439                         obd->obd_flags |= OBD_SET_UP;
440                 }
441
442                 RETURN(err);
443         }
444         case OBD_IOC_CLEANUP: {
445                 /* have we attached a type to this device? */
446                 if (!(obd->obd_flags & OBD_ATTACHED)) {
447                         CERROR("Device %d not attached\n", obd->obd_minor);
448                         RETURN(-ENODEV);
449                 }
450
451                 if ( OBT(obd) && OBP(obd, cleanup) )
452                         err = obd_cleanup(obd);
453
454                 if (!err) {
455                         obd->obd_flags &= ~OBD_SET_UP;
456                         obd->obd_type->typ_refcnt--;
457                 }
458                 RETURN(err);
459         }
460
461         case OBD_IOC_CONNECT: {
462                 obd_data2conn(&conn, data); 
463
464                 err = obd_connect(&conn, obd);
465
466                 CDEBUG(D_IOCTL, "assigned connection %d\n", conn.oc_id);
467                 obd_conn2data(data, &conn);
468                 if (err)
469                         RETURN(err);
470
471                 err = copy_to_user((int *)arg, data, sizeof(*data));
472                 RETURN(err);
473         }
474
475         case OBD_IOC_DISCONNECT: {
476                 obd_data2conn(&conn, data);
477                 err = obd_disconnect(&conn);
478                 RETURN(err);
479         }
480
481         case OBD_IOC_DEC_USE_COUNT: {
482                 MOD_DEC_USE_COUNT;
483                 RETURN(0);
484         }
485
486         case OBD_IOC_CREATE: {
487                 obd_data2conn(&conn, data);
488
489                 err = obd_create(&conn, &data->ioc_obdo1);
490                 if (err)
491                         RETURN(err);
492
493                 err = copy_to_user((int *)arg, data, sizeof(*data));
494                 RETURN(err);
495         }
496
497         case OBD_IOC_GETATTR: {
498
499                 obd_data2conn(&conn, data);
500                 err = obd_getattr(&conn, &data->ioc_obdo1);
501                 if (err)
502                         RETURN(err);
503
504                 err = copy_to_user((int *)arg, data, sizeof(*data));
505                 RETURN(err);
506         }
507
508         case OBD_IOC_SETATTR: {
509                 obd_data2conn(&conn, data);
510                 err = obd_setattr(&conn, &data->ioc_obdo1);
511                 if (err)
512                         RETURN(err);
513
514                 err = copy_to_user((int *)arg, data, sizeof(*data));
515                 RETURN(err);
516         }
517
518         case OBD_IOC_DESTROY: {
519                 obd_data2conn(&conn, data);
520
521                 err = obd_destroy(&conn, &data->ioc_obdo1);
522                 if (err)
523                         RETURN(err);
524
525                 err = copy_to_user((int *)arg, data, sizeof(*data));
526                 RETURN(err);
527         }
528
529         case OBD_IOC_BRW_WRITE:
530                 rw = OBD_BRW_WRITE;
531         case OBD_IOC_BRW_READ: {
532                 /* FIXME: use a better ioctl data struct than obd_ioctl_data.
533                  *        We don't really support multiple-obdo I/Os here,
534                  *        for example offset and count are not per-obdo.
535                  */
536                 struct obdo     *obdos[2] = { NULL, NULL };
537                 obd_count       oa_bufs[2] = { 0, 0 };
538                 struct page     **bufs = NULL;
539                 obd_size        *counts = NULL;
540                 obd_off         *offsets = NULL;
541                 obd_flag        *flags = NULL;
542                 int             num = 1;
543                 int             pages;
544                 int             i, j;
545
546                 obd_data2conn(&conn, data);
547
548                 pages = oa_bufs[0] = data->ioc_plen1 / PAGE_SIZE;
549                 if (data->ioc_obdo2.o_id) {
550                         num = 2;
551                         oa_bufs[1] = data->ioc_plen2 / PAGE_SIZE;
552                         pages += oa_bufs[1];
553                 }
554
555                 CDEBUG(D_INODE, "BRW %s with %dx%d pages\n",
556                        rw == OBD_BRW_READ ? "read" : "write",
557                        num, oa_bufs[0]);
558                 OBD_ALLOC(bufs, pages * sizeof(*bufs));
559                 OBD_ALLOC(counts, pages * sizeof(*counts));
560                 OBD_ALLOC(offsets, pages * sizeof(*offsets));
561                 OBD_ALLOC(flags, pages * sizeof(*flags));
562                 if (!bufs || !counts || !offsets || !flags) {
563                         CERROR("no memory for %d BRW per-page data\n", pages);
564                         err = -ENOMEM;
565                         GOTO(brw_free, err);
566                 }
567
568                 obdos[0] = &data->ioc_obdo1;
569                 if (num > 1)
570                         obdos[1] = &data->ioc_obdo2;
571
572                 for (i = 0, pages = 0; i < num; i++) {
573                         unsigned long off;
574                         void *from;
575
576                         from = (&data->ioc_pbuf1)[i];
577                         off = data->ioc_offset;
578
579                         for (j = 0; j < oa_bufs[i];
580                              j++, pages++, off += PAGE_SIZE, from += PAGE_SIZE){
581                                 unsigned long to;
582
583                                 to = __get_free_pages(GFP_KERNEL, 0);
584                                 if (!to) {
585                                 /*      ||
586                                     copy_from_user((void *)to,from,PAGE_SIZE))
587                                         free_pages(to, 0);
588                                  */
589                                         CERROR("no memory for brw pages\n");
590                                         err = -ENOMEM;
591                                         GOTO(brw_cleanup, err);
592                                 }
593                                 bufs[pages] = virt_to_page(to);
594                                 counts[pages] = PAGE_SIZE;
595                                 offsets[pages] = off;
596                                 flags[pages] = 0;
597                         }
598                 }
599
600                 err = obd_brw(rw, &conn, num, obdos, oa_bufs, bufs,
601                               counts, offsets, flags, NULL);
602
603                 EXIT;
604         brw_cleanup:
605                 i = pages;
606                 while (i-- > 0)
607                         __free_pages(bufs[i], 0);
608         brw_free:
609                 OBD_FREE(bufs, pages * sizeof(*bufs));
610                 OBD_FREE(counts, pages * sizeof(*counts));
611                 OBD_FREE(offsets, pages * sizeof(*offsets));
612                 OBD_FREE(flags, pages * sizeof(*flags));
613                 return err;
614         }
615         default: {
616                 obd_data2conn(&conn, data);
617
618                 err = obd_iocontrol(cmd, &conn, sizeof(*data), data, NULL);
619                 if (err)
620                         RETURN(err);
621
622                 err = copy_to_user((int *)arg, data, sizeof(*data));
623                 RETURN(err);
624         }
625         }
626 } /* obd_class_ioctl */
627
628
629 /* Driver interface done, utility functions follow */
630 int obd_register_type(struct obd_ops *ops, char *nm)
631 {
632         struct obd_type *type;
633
634         ENTRY;
635
636         if (obd_init_magic != 0x11223344) {
637                 CERROR("bad magic for type\n");
638                 RETURN(-EINVAL);
639         }
640
641         if (obd_nm_to_type(nm)) {
642                 CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
643                 RETURN(-EEXIST);
644         }
645
646         OBD_ALLOC(type, sizeof(*type));
647         if (!type)
648                 RETURN(-ENOMEM);
649         INIT_LIST_HEAD(&type->typ_chain);
650         MOD_INC_USE_COUNT;
651         list_add(&type->typ_chain, obd_types.next);
652         type->typ_ops = ops;
653         type->typ_name = nm;
654         RETURN(0);
655 }
656
657 int obd_unregister_type(char *nm)
658 {
659         struct obd_type *type = obd_nm_to_type(nm);
660
661         ENTRY;
662
663         if ( !type ) {
664                 MOD_DEC_USE_COUNT;
665                 CERROR("unknown obd type\n");
666                 RETURN(-EINVAL);
667         }
668
669         if ( type->typ_refcnt ) {
670                 MOD_DEC_USE_COUNT;
671                 CERROR("type %s has refcount (%d)\n", nm, type->typ_refcnt);
672                 RETURN(-EBUSY);
673         }
674
675         list_del(&type->typ_chain);
676         OBD_FREE(type, sizeof(*type));
677         MOD_DEC_USE_COUNT;
678         RETURN(0);
679 } /* obd_unregister_type */
680
681 /* declare character device */
682 static struct file_operations obd_psdev_fops = {
683         ioctl: obd_class_ioctl,       /* ioctl */
684         open: obd_class_open,        /* open */
685         release: obd_class_release,     /* release */
686 };
687
688 /* modules setup */
689 #define OBD_MINOR 241
690 static struct miscdevice obd_psdev = {
691         OBD_MINOR,
692         "obd_psdev",
693         &obd_psdev_fops
694 };
695
696 EXPORT_SYMBOL(obd_register_type);
697 EXPORT_SYMBOL(obd_unregister_type);
698
699 EXPORT_SYMBOL(obd_dev);
700 EXPORT_SYMBOL(obd_class_name2dev);
701 EXPORT_SYMBOL(obd_class_uuid2dev);
702 EXPORT_SYMBOL(gen_connect);
703 EXPORT_SYMBOL(gen_client);
704 EXPORT_SYMBOL(gen_conn2obd);
705 EXPORT_SYMBOL(gen_cleanup);
706 EXPORT_SYMBOL(gen_disconnect);
707 EXPORT_SYMBOL(gen_copy_data);
708 EXPORT_SYMBOL(obdo_cachep);
709
710 /* EXPORT_SYMBOL(gen_multi_attach); */
711 EXPORT_SYMBOL(gen_multi_setup);
712 EXPORT_SYMBOL(gen_multi_cleanup);
713 EXPORT_SYMBOL(obd_memory);
714 EXPORT_SYMBOL(obd_fail_loc);
715
716 static int __init init_obdclass(void)
717 {
718         int err;
719         int i;
720
721         printk(KERN_INFO "OBD class driver  v0.9, info@clusterfs.com\n");
722
723         INIT_LIST_HEAD(&obd_types);
724
725         if ((err = misc_register(&obd_psdev))) {
726                 CERROR("cannot register %d err %d\n", OBD_MINOR, err);
727                 return err;
728         }
729
730         for (i = 0; i < MAX_OBD_DEVICES; i++) {
731                 memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
732                 obd_dev[i].obd_minor = i;
733                 INIT_LIST_HEAD(&obd_dev[i].obd_exports);
734         }
735
736         err = obd_init_caches();
737         if (err)
738                 return err;
739         obd_sysctl_init();
740         obd_init_magic = 0x11223344;
741         return 0;
742 }
743
744 static void __exit cleanup_obdclass(void)
745 {
746         int i;
747         ENTRY;
748
749         misc_deregister(&obd_psdev);
750         for (i = 0; i < MAX_OBD_DEVICES; i++) {
751                 struct obd_device *obd = &obd_dev[i];
752                 if (obd->obd_type && (obd->obd_flags & OBD_SET_UP) &&
753                     OBT(obd) && OBP(obd, detach)) {
754                         /* XXX should this call generic detach otherwise? */
755                         OBP(obd, detach)(obd);
756                 }
757         }
758
759         obd_cleanup_caches();
760         obd_sysctl_clean();
761         CERROR("obd memory leaked: %ld bytes\n", obd_memory);
762         obd_init_magic = 0;
763         EXIT;
764 }
765
766 MODULE_AUTHOR("Cluster File Systems, Inc. <braam@clusterfs.com>");
767 MODULE_DESCRIPTION("Lustre Class Driver v1.0");
768 MODULE_LICENSE("GPL");
769
770 module_init(init_obdclass);
771 module_exit(cleanup_obdclass);