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