Whamcloud - gitweb
- minor debugging fixes
[fs/lustre-release.git] / lustre / obdclass / class_obd.c
1 /*
2  *              An implementation of a loadable kernel mode driver providing
3  *              multiple kernel/user space bidirectional communications links.
4  *
5  *              Author:         Alan Cox <alan@cymru.net>
6  *
7  *              This program is free software; you can redistribute it and/or
8  *              modify it under the terms of the GNU General Public License
9  *              version 2 as published by the Free Software Foundation.
10  * 
11  *              Adapted to become the Linux 2.0 Coda pseudo device
12  *              Peter  Braam  <braam@maths.ox.ac.uk> 
13  *              Michael Callahan <mjc@emmy.smith.edu>           
14  *
15  *              Changes for Linux 2.1
16  *              Copyright (c) 1997 Carnegie-Mellon University
17  *
18  *              Redone again for Intermezzo
19  *              Copyright (c) 1998 Peter J. Braam
20  *
21  *              Hacked up again for simulated OBD
22  *              Copyright (c) 1999 Stelias Computing, Inc.
23  *                (authors {pschwan,braam}@stelias.com)
24  *              Copyright (C) 1999 Seagate Technology, Inc.
25  *              Copyright (C) 2001 Cluster File Systems, Inc.
26  *
27  * 
28  */
29
30 #define EXPORT_SYMTAB
31 #include <linux/config.h> /* for CONFIG_PROC_FS */
32 #include <linux/module.h>
33 #include <linux/errno.h>
34 #include <linux/kernel.h>
35 #include <linux/major.h>
36 #include <linux/kmod.h>   /* for request_module() */
37 #include <linux/sched.h>
38 #include <linux/lp.h>
39 #include <linux/slab.h>
40 #include <linux/ioport.h>
41 #include <linux/fcntl.h>
42 #include <linux/delay.h>
43 #include <linux/skbuff.h>
44 #include <linux/proc_fs.h>
45 #include <linux/fs.h>
46 #include <linux/poll.h>
47 #include <linux/init.h>
48 #include <linux/list.h>
49 #include <asm/io.h>
50 #include <asm/system.h>
51 #include <asm/poll.h>
52 #include <asm/uaccess.h>
53 #include <linux/miscdevice.h>
54
55 #define DEBUG_SUBSYSTEM S_CLASS
56
57 #include <linux/obd_support.h>
58 #include <linux/obd_class.h>
59
60 static int obd_init_magic;
61 int obd_print_entry = 1;
62 int obd_debug_level = ~0;
63 long obd_memory = 0;
64 struct obd_device obd_dev[MAX_OBD_DEVICES];
65 struct list_head obd_types;
66
67 /*  opening /dev/obd */
68 static int obd_class_open(struct inode * inode, struct file * file)
69 {
70         ENTRY;
71
72         file->private_data = NULL;
73         MOD_INC_USE_COUNT;
74         EXIT;
75         return 0;
76 }
77
78 /*  closing /dev/obd */
79 static int obd_class_release(struct inode * inode, struct file * file)
80 {
81         ENTRY;
82
83         if (file->private_data)
84                 file->private_data = NULL;
85
86         MOD_DEC_USE_COUNT;
87         EXIT;
88         return 0;
89 }
90
91 /* 
92  * support functions: we could use inter-module communication, but this 
93  * is more portable to other OS's
94  */
95 static struct obd_type *obd_search_type(char *nm)
96 {
97         struct list_head *tmp;
98         struct obd_type *type;
99         CDEBUG(D_INFO, "SEARCH %s\n", nm);
100         
101         tmp = &obd_types;
102         while ( (tmp = tmp->next) != &obd_types ) {
103                 type = list_entry(tmp, struct obd_type, typ_chain);
104                 CDEBUG(D_INFO, "TYP %s\n", type->typ_name);
105                 if (strlen(type->typ_name) == strlen(nm) &&
106                     strcmp(type->typ_name, nm) == 0 ) {
107                         return type;
108                 }
109         }
110         return NULL;
111 }
112
113 static struct obd_type *obd_nm_to_type(char *nm) 
114 {
115         struct obd_type *type = obd_search_type(nm);
116
117 #ifdef CONFIG_KMOD
118         if ( !type ) {
119                 if ( !request_module(nm) ) {
120                         CDEBUG(D_INFO, "Loaded module '%s'\n", nm);
121                         type = obd_search_type(nm);
122                 } else {
123                         CDEBUG(D_INFO, "Can't load module '%s'\n", nm);
124                 }
125         }
126 #endif
127         return type;
128 }
129
130 /* to control /dev/obd */
131 static int obd_class_ioctl (struct inode * inode, struct file * filp, 
132                             unsigned int cmd, unsigned long arg)
133 {
134         /* NOTE this must be larger than any of the ioctl data structs */
135         char buf[1024];
136         struct obd_ioctl_data *data;
137         struct obd_device *obd = filp->private_data;
138         struct obd_conn conn;
139         int err = 0;
140         ENTRY;
141
142         memset(buf, 0, sizeof(buf));
143
144         if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS) {
145                 CERROR("OBD ioctl: No device\n");
146                 return -EINVAL;
147         } 
148         if (obd_ioctl_getdata(buf, buf + 800, (void *)arg)) { 
149                 CERROR("OBD ioctl: data error\n");
150                 return -EINVAL;
151         }
152         data = (struct obd_ioctl_data *)buf;
153
154         switch (cmd) {
155         case TCGETS: { 
156                 EXIT;
157                 return -EINVAL;
158         }
159         case OBD_IOC_DEVICE: { 
160                 CDEBUG(D_IOCTL, "\n");
161                 if (data->ioc_dev >= MAX_OBD_DEVICES ||
162                     data->ioc_dev < 0) { 
163                         CERROR("OBD ioctl: DEVICE insufficient devices\n");
164                         return -EINVAL;
165                 }
166                 CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev);
167
168                 filp->private_data = &obd_dev[data->ioc_dev];
169                 EXIT;
170                 return 0;
171         }
172
173         case OBD_IOC_ATTACH: {
174                 struct obd_type *type;
175
176                 ENTRY;
177                 /* have we attached a type to this device */
178                 if ( obd->obd_flags & OBD_ATTACHED ) {
179                         CERROR("OBD: Device %d already typed as  %s.\n",
180                                obd->obd_minor, MKSTR(obd->obd_type->typ_name));
181                         return -EBUSY;
182                 }
183
184                 CDEBUG(D_IOCTL, "attach %s %s\n",  MKSTR(data->ioc_inlbuf1), 
185                        MKSTR(data->ioc_inlbuf2));
186
187                 /* find the type */
188                 type = obd_nm_to_type(data->ioc_inlbuf1);
189                 if ( !type ) {
190                         CERROR("OBD: unknown type dev %d\n", obd->obd_minor);
191                         return -EINVAL;
192                 }
193
194                 obd->obd_type = type;
195                 obd->obd_multi_count = 0;
196                 INIT_LIST_HEAD(&obd->obd_gen_clients);
197
198                 /* do the attach */
199                 if ( OBT(obd) && OBP(obd, attach) ) {
200                         err = OBP(obd, attach)(obd, sizeof(*data), data);
201                 }
202
203                 if ( err ) {
204                         obd->obd_type = NULL;
205                         EXIT;
206                 } else {
207                         obd->obd_flags |=  OBD_ATTACHED;
208                         type->typ_refcnt++;
209                         CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n", 
210                                obd->obd_minor, data->ioc_inlbuf1);
211                         obd->obd_proc_entry = 
212                                 proc_lustre_register_obd_device(obd);
213                         MOD_INC_USE_COUNT;
214                         EXIT;
215                 }
216
217                 return err;
218         }
219
220         case OBD_IOC_DETACH: {
221                 ENTRY;
222                 if (obd->obd_flags & OBD_SET_UP) {
223                         CERROR("OBD device %d still set up\n", obd->obd_minor);
224                         return -EBUSY;
225                 }
226                 if (! (obd->obd_flags & OBD_ATTACHED) ) {
227                         CERROR("OBD device %d not attached\n", obd->obd_minor);
228                         return -ENODEV;
229                 }
230                 if ( !list_empty(&obd->obd_gen_clients) ) {
231                         CERROR("OBD device %d has connected clients\n",
232                                obd->obd_minor);
233                         return -EBUSY;
234                 }
235
236                 if (obd->obd_proc_entry)
237                         proc_lustre_release_obd_device(obd);
238
239                 obd->obd_flags &= ~OBD_ATTACHED;
240                 obd->obd_type->typ_refcnt--;
241                 obd->obd_type = NULL;
242                 MOD_DEC_USE_COUNT;
243                 EXIT;
244                 return 0;
245         }
246
247         case OBD_IOC_SETUP: {
248                 ENTRY;
249                 /* have we attached a type to this device? */
250                 if (!(obd->obd_flags & OBD_ATTACHED)) {
251                         CERROR("Device %d not attached\n", obd->obd_minor);
252                         return -ENODEV;
253                 }
254
255                 /* has this been done already? */
256                 if ( obd->obd_flags & OBD_SET_UP ) {
257                         CERROR("Device %d already setup (type %s)\n",
258                                obd->obd_minor, obd->obd_type->typ_name);
259                         return -EBUSY;
260                 }
261
262                 if ( OBT(obd) && OBP(obd, setup) )
263                         err = OBP(obd, setup)(obd, sizeof(*data), data);
264
265                 if (!err) { 
266                         obd->obd_type->typ_refcnt++;
267                         obd->obd_flags |= OBD_SET_UP;
268                         EXIT;
269                 }
270
271                 return err;
272         }
273         case OBD_IOC_CLEANUP: {
274                 ENTRY;
275
276                 if ( !(obd->obd_flags & OBD_SET_UP) ) {
277                         EXIT;
278                         return -EINVAL;
279                 }
280
281                 err = obd_cleanup(obd);
282                 if ( err ) {
283                         EXIT;
284                         return err;
285                 }
286
287                 obd->obd_flags &= ~OBD_SET_UP;
288                 obd->obd_type->typ_refcnt--;
289                 EXIT;
290                 return 0;
291         }
292
293         case OBD_IOC_CONNECT:
294         {
295                 conn.oc_id = data->ioc_conn1;
296                 conn.oc_dev = obd; 
297
298                 err = obd_connect(&conn);
299
300                 CDEBUG(D_IOCTL, "assigned connection %d\n", conn.oc_id);
301                 data->ioc_conn1 = conn.oc_id;
302                 if ( err )
303                         return err;
304
305                 return copy_to_user((int *)arg, data, sizeof(*data));
306         }
307
308         case OBD_IOC_DISCONNECT: { 
309                 conn.oc_id = data->ioc_conn1;
310                 conn.oc_dev = obd;
311
312                 err = obd_disconnect(&conn);
313                 return err;
314         }               
315
316         case OBD_IOC_DEC_USE_COUNT: { 
317                 MOD_DEC_USE_COUNT;
318                 return 0;
319         }
320
321         case OBD_IOC_CREATE: {
322                 conn.oc_id = data->ioc_conn1;
323                 conn.oc_dev = obd;
324
325                 err = obd_create(&conn, &data->ioc_obdo1);
326                 if (err) {
327                         EXIT;
328                         return err;
329                 }
330
331                 err = copy_to_user((int *)arg, data, sizeof(*data));
332                 EXIT;
333                 return err;
334         }
335
336         case OBD_IOC_GETATTR: {
337                 conn.oc_id = data->ioc_conn1;
338                 conn.oc_dev = obd;
339
340                 err = obd_getattr(&conn, &data->ioc_obdo1);
341                 if (err) {
342                         EXIT;
343                         return err;
344                 }
345
346                 err = copy_to_user((int *)arg, data, sizeof(*data));
347                 EXIT;
348                 return err;
349         }
350
351         case OBD_IOC_SETATTR: {
352                 conn.oc_id = data->ioc_conn1;
353                 conn.oc_dev = obd;
354
355                 err = obd_setattr(&conn, &data->ioc_obdo1);
356                 if (err) {
357                         EXIT;
358                         return err;
359                 }
360
361                 err = copy_to_user((int *)arg, data, sizeof(*data));
362                 EXIT;
363                 return err;
364         }
365
366         case OBD_IOC_DESTROY: {
367                 conn.oc_id = data->ioc_conn1;
368                 conn.oc_dev = obd;
369
370                 err = obd_destroy(&conn, &data->ioc_obdo1);
371                 if (err) {
372                         EXIT;
373                         return err;
374                 }
375
376                 err = copy_to_user((int *)arg, data, sizeof(*data));
377                 EXIT;
378                 return err;
379         }
380
381 #if 0
382         case OBD_IOC_SYNC: {
383                 struct oic_range_s *range = tmp_buf;
384
385                 if (!obd->obd_type)
386                         return -ENODEV;
387
388                 err = copy_from_user(range, (const void *)arg,  sizeof(*range));
389
390                 if ( err ) {
391                         EXIT;
392                         return err;
393                 }
394                         
395                 if ( !OBT(obd) || !OBP(obd, sync) ) {
396                         err = -EOPNOTSUPP;
397                         EXIT;
398                         return err;
399                 }
400
401                 /* XXX sync needs to be tested/verified */
402                 err = OBP(obd, sync)(&conn, &range->obdo, range->count,
403                                         range->offset);
404
405                 if ( err ) {
406                         EXIT;
407                         return err;
408                 }
409                         
410                 return put_user(err, (int *) arg);
411         }
412
413         case OBD_IOC_READ: {
414                 int err;
415                 struct oic_rw_s *rw_s = tmp_buf;  /* read, write ioctl str */
416
417                 err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
418                 if ( err ) {
419                         EXIT;
420                         return err;
421                 }
422
423                 conn.oc_id = rw_s->conn_id;
424
425                 if ( !OBT(obd) || !OBP(obd, read) ) {
426                         err = -EOPNOTSUPP;
427                         EXIT;
428                         return err;
429                 }
430
431
432                 err = OBP(obd, read)(&conn, &rw_s->obdo, rw_s->buf, 
433                                         &rw_s->count, rw_s->offset);
434                 
435                 ODEBUG(&rw_s->obdo);
436                 CDEBUG(D_INFO, "READ: conn %d, count %Ld, offset %Ld, '%s'\n",
437                        rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf);
438                 if ( err ) {
439                         EXIT;
440                         return err;
441                 }
442                         
443                 err = copy_to_user((int*)arg, &rw_s->count, sizeof(rw_s->count));
444                 EXIT;
445                 return err;
446         }
447
448         case OBD_IOC_WRITE: {
449                 struct oic_rw_s *rw_s = tmp_buf;  /* read, write ioctl str */
450
451                 err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
452                 if ( err ) {
453                         EXIT;
454                         return err;
455                 }
456
457                 conn.oc_id = rw_s->conn_id;
458
459                 if ( !OBT(obd) || !OBP(obd, write) ) {
460                         err = -EOPNOTSUPP;
461                         return err;
462                 }
463
464                 CDEBUG(D_INFO, "WRITE: conn %d, count %Ld, offset %Ld, '%s'\n",
465                        rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf);
466
467                 err = OBP(obd, write)(&conn, &rw_s->obdo, rw_s->buf, 
468                                          &rw_s->count, rw_s->offset);
469                 ODEBUG(&rw_s->obdo);
470                 if ( err ) {
471                         EXIT;
472                         return err;
473                 }
474
475                 err = copy_to_user((int *)arg, &rw_s->count,
476                                    sizeof(rw_s->count));
477                 EXIT;
478                 return err;
479         }
480         case OBD_IOC_PREALLOCATE: {
481                 struct oic_prealloc_s *prealloc = tmp_buf;
482
483                 /* has this minor been registered? */
484                 if (!obd->obd_type)
485                         return -ENODEV;
486
487                 err = copy_from_user(prealloc, (int *)arg, sizeof(*prealloc));
488                 if (err) 
489                         return -EFAULT;
490
491                 if ( !(obd->obd_flags & OBD_ATTACHED) ||
492                      !(obd->obd_flags & OBD_SET_UP)) {
493                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
494                         return -ENODEV;
495                 }
496
497                 if ( !OBT(obd) || !OBP(obd, preallocate) )
498                         return -EOPNOTSUPP;
499
500                 conn.oc_id = prealloc->conn_id;
501                 err = OBP(obd, preallocate)(&conn, &prealloc->alloc,
502                                                prealloc->ids);
503                 if ( err ) {
504                         EXIT;
505                         return err;
506                 }
507
508                 err =copy_to_user((int *)arg, prealloc, sizeof(*prealloc));
509                 EXIT;
510                 return err;
511         }
512         case OBD_IOC_STATFS: {
513                 struct statfs *tmp;
514                 unsigned int conn_id;
515                 struct statfs buf;
516
517                 /* has this minor been registered? */
518                 if (!obd->obd_type)
519                         return -ENODEV;
520
521                 tmp = (void *)arg + sizeof(unsigned int);
522                 get_user(conn_id, (int *) arg);
523
524                 if ( !OBT(obd) || !OBP(obd, statfs) )
525                         return -EOPNOTSUPP;
526
527                 conn.oc_id = conn_id;
528                 err = OBP(obd, statfs)(&conn, &buf);
529                 if ( err ) {
530                         EXIT;
531                         return err;
532                 }
533                 err = copy_to_user(tmp, &buf, sizeof(buf));
534                 EXIT;
535                 return err;
536                 
537         }
538         case OBD_IOC_COPY: {
539                 struct ioc_mv_s *mvdata = tmp_buf;
540
541                 if ( (!(obd->obd_flags & OBD_SET_UP)) ||
542                      (!(obd->obd_flags & OBD_ATTACHED))) {
543                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
544                         return -ENODEV;
545                 }
546
547                 /* get main structure */
548                 err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata));
549                 if (err) {
550                         EXIT;
551                         return err;
552                 }
553
554                 if ( !OBT(obd) || !OBP(obd, copy) )
555                         return -EOPNOTSUPP;
556
557                 /* do the partition */
558                 CDEBUG(D_INFO, "Copy %d, type %s dst %Ld src %Ld\n", dev, 
559                        obd->obd_type->typ_name, mvdata->dst.o_id, 
560                        mvdata->src.o_id);
561
562                 conn.oc_id = mvdata->src_conn_id;
563
564                 err = OBP(obd, copy)(&conn, &mvdata->dst, 
565                                         &conn, &mvdata->src, 
566                                         mvdata->src.o_size, 0);
567                 return err;
568         }
569
570         case OBD_IOC_MIGR: {
571                 struct ioc_mv_s *mvdata = tmp_buf;
572
573                 if ( (!(obd->obd_flags & OBD_SET_UP)) ||
574                      (!(obd->obd_flags & OBD_ATTACHED))) {
575                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
576                         return -ENODEV;
577                 }
578
579                 err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata));
580                 if (err) {
581                         EXIT;
582                         return err;
583                 }
584
585                 CDEBUG(D_INFO, "Migrate copying %d bytes\n", sizeof(*mvdata));
586
587                 if ( !OBT(obd) || !OBP(obd, migrate) )
588                         return -EOPNOTSUPP;
589
590                 /* do the partition */
591                 CDEBUG(D_INFO, "Migrate %d, type %s conn %d src %Ld dst %Ld\n",
592                        dev, obd->obd_type->typ_name, mvdata->src_conn_id,
593                        mvdata->src.o_id, mvdata->dst.o_id);
594
595                 conn.oc_id = mvdata->src_conn_id;
596                 err = OBP(obd, migrate)(&conn, &mvdata->dst, &mvdata->src, 
597                                            mvdata->src.o_size, 0);
598
599                 return err;
600         }
601         case OBD_IOC_PUNCH: {
602                 struct oic_rw_s *rw_s = tmp_buf;  /* read, write ioctl str */
603
604                 err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
605                 if ( err ) {
606                         EXIT;
607                         return err;
608                 }
609
610                 conn.oc_id = rw_s->conn_id;
611
612                 if ( !OBT(obd) || !OBP(obd, punch) ) {
613                         err = -EOPNOTSUPP;
614                         return err;
615                 }
616
617                 CDEBUG(D_INFO, "PUNCH: conn %d, count %Ld, offset %Ld\n",
618                        rw_s->conn_id, rw_s->count, rw_s->offset);
619                 err = OBP(obd, punch)(&conn, &rw_s->obdo, rw_s->count,
620                                          rw_s->offset);
621                 ODEBUG(&rw_s->obdo);
622                 if ( err ) {
623                         EXIT;
624                         return err;
625                 }
626                 EXIT;
627                 return err;
628         }
629
630         default: {
631                 struct obd_type *type;
632                 struct oic_generic input;
633                 char *nm;
634                 void *karg;
635
636                 /* get data structures */
637                 err = copy_from_user(&input, (void *)arg, sizeof(input));
638                 if ( err ) {
639                         EXIT;
640                         return err;
641                 }
642
643                 err = getdata(input.att_typelen + 1, &input.att_type);
644                 if ( err ) {
645                         EXIT;
646                         return err;
647                 }
648
649                 /* find the type */
650                 nm = input.att_type;
651                 type = obd_nm_to_type(nm);
652 #ifdef CONFIG_KMOD
653                 if ( !type ) {
654                         if ( !request_module(nm) ) {
655                                 CDEBUG(D_INFO, "Loaded module '%s'\n", nm);
656                                 type = obd_nm_to_type(nm);
657                         } else {
658                                 CDEBUG(D_INFO, "Can't load module '%s'\n", nm);
659                         }
660                 }
661 #endif
662                 OBD_FREE(input.att_type, input.att_typelen + 1);
663                 if ( !type ) {
664                         CERROR("unknown obd type dev %d\n", dev);
665                         EXIT;
666                         return -EINVAL;
667                 }
668                 
669                 if ( !type->typ_ops || !type->typ_ops->o_iocontrol ) {
670                         EXIT;
671                         return -EOPNOTSUPP;
672                 }
673                 conn.oc_id = input.att_connid;
674                 
675                 CDEBUG(D_INFO, "Calling ioctl %x for type %s, len %d\n",
676                        cmd, type->typ_name, input.att_datalen);
677
678                 /* get the generic data */
679                 karg = input.att_data;
680                 err = getdata(input.att_datalen, &karg);
681                 if ( err ) {
682                         EXIT;
683                         return err;
684                 }
685
686                 err = type->typ_ops->o_iocontrol(cmd, &conn, input.att_datalen, 
687                                                  karg, input.att_data);
688                 OBD_FREE(karg, input.att_datalen);
689
690                 EXIT;
691                 return err;
692         }
693 #endif 
694         default:
695                 return -EINVAL;
696
697         }
698 } /* obd_class_ioctl */
699
700
701 /* Driver interface done, utility functions follow */
702 int obd_register_type(struct obd_ops *ops, char *nm)
703 {
704         struct obd_type *type;
705
706         if (obd_init_magic != 0x11223344) {
707                 CERROR("bad magic for type\n");
708                 EXIT;
709                 return -EINVAL;
710         }
711
712         if  ( obd_nm_to_type(nm) ) {
713                 CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
714                 EXIT;
715                 return -EEXIST;
716         }
717         
718         OBD_ALLOC(type, sizeof(*type));
719         if ( !type ) {
720                 EXIT;
721                 return -ENOMEM;
722         }
723         memset(type, 0, sizeof(*type));
724         INIT_LIST_HEAD(&type->typ_chain);
725         MOD_INC_USE_COUNT;
726         list_add(&type->typ_chain, obd_types.next);
727         type->typ_ops = ops;
728         type->typ_name = nm;
729         EXIT;
730         return 0;
731 }
732         
733 int obd_unregister_type(char *nm)
734 {
735         struct obd_type *type = obd_nm_to_type(nm);
736
737         if ( !type ) {
738                 MOD_DEC_USE_COUNT;
739                 CERROR("unknown obd type\n");
740                 EXIT;
741                 return -EINVAL;
742         }
743
744         if ( type->typ_refcnt ) {
745                 MOD_DEC_USE_COUNT;
746                 CERROR("type %s has refcount (%d)\n", nm, type->typ_refcnt);
747                 EXIT;
748                 return -EBUSY;
749         }
750
751         list_del(&type->typ_chain);
752         OBD_FREE(type, sizeof(*type));
753         MOD_DEC_USE_COUNT;
754         return 0;
755 } /* obd_unregister_type */
756
757 /* declare character device */
758 static struct file_operations obd_psdev_fops = {
759         ioctl: obd_class_ioctl,       /* ioctl */
760         open: obd_class_open,        /* open */
761         release: obd_class_release,     /* release */
762 };
763
764 /* modules setup */
765 #define OBD_MINOR 241
766 static struct miscdevice obd_psdev = {
767         OBD_MINOR,
768         "obd_psdev",
769         &obd_psdev_fops
770 };
771
772 int init_obd(void)
773 {
774         int err;
775         int i;
776
777         printk(KERN_INFO "OBD class driver  v0.01, braam@stelias.com\n");
778         
779         INIT_LIST_HEAD(&obd_types);
780         
781         if ( (err = misc_register(&obd_psdev)) ) { 
782                 CERROR("cannot register %d err %d\n", OBD_MINOR, err);
783                 return -EIO;
784         }
785
786         for (i = 0; i < MAX_OBD_DEVICES; i++) {
787                 memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
788                 obd_dev[i].obd_minor = i;
789                 INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients);
790         }
791
792         err = obd_init_obdo_cache();
793         if (err)
794                 return err;
795         obd_sysctl_init();
796         obd_init_magic = 0x11223344;
797         return 0;
798 }
799
800 EXPORT_SYMBOL(obd_register_type);
801 EXPORT_SYMBOL(obd_unregister_type);
802
803 EXPORT_SYMBOL(obd_print_entry);
804 EXPORT_SYMBOL(obd_debug_level);
805 EXPORT_SYMBOL(obd_dev);
806
807 EXPORT_SYMBOL(gen_connect);
808 EXPORT_SYMBOL(gen_client);
809 EXPORT_SYMBOL(gen_cleanup);
810 EXPORT_SYMBOL(gen_disconnect);
811 EXPORT_SYMBOL(gen_copy_data); 
812 EXPORT_SYMBOL(obdo_cachep);
813
814 /* EXPORT_SYMBOL(gen_multi_attach); */
815 EXPORT_SYMBOL(gen_multi_setup);
816 EXPORT_SYMBOL(gen_multi_cleanup);
817 EXPORT_SYMBOL(obd_memory);
818
819 #ifdef MODULE
820 int init_module(void)
821 {
822         return init_obd();
823 }
824
825 void cleanup_module(void)
826 {
827         int i;
828         ENTRY;
829
830         misc_deregister(&obd_psdev);
831         for (i = 0; i < MAX_OBD_DEVICES; i++) {
832                 struct obd_device *obd = &obd_dev[i];
833                 if ( obd->obd_type && 
834                      (obd->obd_flags & OBD_SET_UP) &&
835                      OBT(obd) && OBP(obd, detach) ) {
836                         /* XXX should this call generic detach otherwise? */
837                         OBP(obd, detach)(obd);
838                 } 
839         }
840
841         obd_cleanup_obdo_cache();
842         obd_sysctl_clean();
843         CDEBUG(D_MALLOC, "CLASS mem used %ld\n", obd_memory);
844         obd_init_magic = 0;
845         EXIT;
846 }
847 #endif