Whamcloud - gitweb
obdfs/flushd.c: removed iput() from dequeue routine, as we no longer remove
[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 __FUNCTION__ ": 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 buf[1024];
160         void *tmp_buf = buf;
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 = tmp_buf;
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                 /* get data structures */
193                 err = copy_from_user(input, (void *)arg, sizeof(*input));
194                 if ( err ) {
195                         EXIT;
196                         return err;
197                 }
198
199                 err = getdata(input->att_typelen + 1, &input->att_type);
200                 if ( err ) {
201                         EXIT;
202                         return err;
203                 }
204
205                 /* find the type */
206                 type = obd_nm_to_type(input->att_type);
207                 OBD_FREE(input->att_type, input->att_typelen + 1);
208                 if ( !type ) {
209                         printk(__FUNCTION__ ": unknown obd type dev %d\n",
210                                dev);
211                         EXIT;
212                         return -EINVAL;
213                 }
214                 obddev->obd_type = type;
215                 
216                 /* get the attach data */
217                 err = getdata(input->att_datalen, &input->att_data);
218                 if ( err ) {
219                         EXIT;
220                         return err;
221                 }
222
223                 INIT_LIST_HEAD(&obddev->obd_gen_clients);
224                 obddev->obd_multi_count = 0;
225
226                 CDEBUG(D_IOCTL, "Attach %d, datalen %d, type %s\n", 
227                        dev, input->att_datalen, obddev->obd_type->typ_name);
228                 /* maybe we are done */
229                 if ( !OBT(obddev) || !OBP(obddev, attach) ) {
230                         obddev->obd_flags |=  OBD_ATTACHED;
231                         type->typ_refcnt++;
232                         CDEBUG(D_IOCTL, "Dev %d refcount now %d\n", dev,
233                                type->typ_refcnt);
234                         MOD_INC_USE_COUNT;
235                         EXIT;
236                         return 0;
237                 }
238
239                 /* do the attach */
240                 err = OBP(obddev, attach)(obddev, input->att_datalen,
241                                           input->att_data);
242                 OBD_FREE(input->att_data, input->att_datalen);
243
244                 if ( err ) {
245                         obddev->obd_flags &= ~OBD_ATTACHED;
246                         obddev->obd_type = NULL;
247                         EXIT;
248                 } else {
249                         obddev->obd_flags |=  OBD_ATTACHED;
250                         type->typ_refcnt++;
251                         CDEBUG(D_IOCTL, "Dev %d refcount now %d\n", dev,
252                                type->typ_refcnt);
253                         MOD_INC_USE_COUNT;
254                         EXIT;
255                 }
256                 return err;
257         }
258
259         case OBD_IOC_DETACH: {
260
261                 ENTRY;
262                 if (obddev->obd_flags & OBD_SET_UP) {
263                         EXIT;
264                         return -EBUSY;
265                 }
266                 if (! (obddev->obd_flags & OBD_ATTACHED) ) {
267                         CDEBUG(D_IOCTL, "Device not attached\n");
268                         EXIT;
269                         return -ENODEV;
270                 }
271                 if ( !list_empty(&obddev->obd_gen_clients) ) {
272                         CDEBUG(D_IOCTL, "Device has connected clients\n");
273                         EXIT;
274                         return -EBUSY;
275                 }
276
277                 CDEBUG(D_IOCTL, "Detach %d, type %s\n", dev,
278                        obddev->obd_type->typ_name);
279                 obddev->obd_flags &= ~OBD_ATTACHED;
280                 obddev->obd_type->typ_refcnt--;
281                 CDEBUG(D_IOCTL, "Dev %d refcount now %d\n", dev,
282                        obddev->obd_type->typ_refcnt);
283                 obddev->obd_type = NULL;
284                 MOD_DEC_USE_COUNT;
285                 EXIT;
286                 return 0;
287         }
288
289         case OBD_IOC_SETUP: {
290                 struct ioc_setup {
291                         int setup_datalen;
292                         void *setup_data;
293                 } *setup;
294                 setup = tmp_buf;
295
296                 ENTRY;
297                 /* have we attached a type to this device */
298                 if (!(obddev->obd_flags & OBD_ATTACHED)) {
299                         CDEBUG(D_IOCTL, "Device not attached\n");
300                         EXIT;
301                         return -ENODEV;
302                 }
303
304                 /* has this been done already? */
305                 if ( obddev->obd_flags & OBD_SET_UP ) {
306                         CDEBUG(D_IOCTL, "Device %d already setup (type %s)\n",
307                                dev, obddev->obd_type->typ_name);
308                         EXIT;
309                         return -EBUSY;
310                 }
311
312                 /* get main structure */
313                 err = copy_from_user(setup, (void *) arg, sizeof(*setup));
314                 if (err) {
315                         EXIT;
316                         return err;
317                 }
318
319                 err = getdata(setup->setup_datalen, &setup->setup_data);
320                 if (err) {
321                         EXIT;
322                         return err;
323                 }
324
325                 /* do the setup */
326                 CDEBUG(D_IOCTL, "Setup %d, type %s\n", dev, 
327                        obddev->obd_type->typ_name);
328                 if ( !OBT(obddev) || !OBP(obddev, setup) ) {
329                         obddev->obd_type->typ_refcnt++;
330                         CDEBUG(D_IOCTL, "Dev %d refcount now %d\n",
331                                dev, obddev->obd_type->typ_refcnt);
332                         obddev->obd_flags |= OBD_SET_UP;
333                         EXIT;
334                         return 0;
335                 }
336
337                 err = OBP(obddev, setup)(obddev, setup->setup_datalen,
338                                          setup->setup_data);
339
340                 if ( err )  {
341                         obddev->obd_flags &= ~OBD_SET_UP;
342                         EXIT;
343                 } else {
344                         obddev->obd_type->typ_refcnt++;
345                         CDEBUG(D_IOCTL, "Dev %d refcount now %d\n",
346                                dev, obddev->obd_type->typ_refcnt);
347                         obddev->obd_flags |= OBD_SET_UP;
348                         EXIT;
349                 }
350                 return err;
351         }
352         case OBD_IOC_CLEANUP: {
353                 ENTRY;
354                 /* has this minor been registered? */
355                 if (!obddev->obd_type) {
356                         CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
357                         EXIT;
358                         return -ENODEV;
359                 }
360
361                 if ( !obddev->obd_type->typ_refcnt ) {
362                         CDEBUG(D_IOCTL, "dev %d has refcount (%d)!\n",
363                                dev, obddev->obd_type->typ_refcnt);
364                         EXIT;
365                         return -EBUSY;
366                 }
367
368                 if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
369                      (!(obddev->obd_flags & OBD_ATTACHED))) {
370                         CDEBUG(D_IOCTL, "device not attached or set up\n");
371                         EXIT;
372                         return -ENODEV;
373                 }
374
375                 if ( !OBT(obddev) || !OBP(obddev, cleanup) )
376                         goto cleanup_out;
377
378                 /* cleanup has no argument */
379                 err = OBP(obddev, cleanup)(obddev);
380                 if ( err ) {
381                         EXIT;
382                         return err;
383                 }
384
385         cleanup_out: 
386                 obddev->obd_flags &= ~OBD_SET_UP;
387                 obddev->obd_type->typ_refcnt--;
388                 CDEBUG(D_IOCTL, "Dev %d refcount now %d\n", dev,
389                        obddev->obd_type->typ_refcnt);
390                 EXIT;
391                 return 0;
392         }
393         case OBD_IOC_CONNECT:
394         {
395                 if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
396                      (!(obddev->obd_flags & OBD_ATTACHED))) {
397                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
398                         return -ENODEV;
399                 }
400
401                 if ( !OBT(obddev) || !OBP(obddev, connect) )
402                         return -EOPNOTSUPP;
403                 
404                 err = OBP(obddev, connect)(&conn);
405                 if ( err )
406                         return err;
407
408                 return copy_to_user((int *)arg, &conn.oc_id,
409                                     sizeof(uint32_t));
410         }
411         case OBD_IOC_DISCONNECT:
412                 /* frees data structures */
413                 /* has this minor been registered? */
414                 if (!obddev->obd_type)
415                         return -ENODEV;
416
417                 get_user(cli_id, (int *) arg);
418                 conn.oc_id = cli_id;
419
420                 if ( !OBT(obddev) || !OBP(obddev, disconnect))
421                         return -EOPNOTSUPP;
422                 
423                 OBP(obddev, disconnect)(&conn);
424                 return 0;
425
426         case OBD_IOC_SYNC: {
427                 struct oic_range_s *range = tmp_buf;
428
429                 if (!obddev->obd_type)
430                         return -ENODEV;
431
432                 err = copy_from_user(range, (const void *)arg,  sizeof(*range));
433
434                 if ( err ) {
435                         EXIT;
436                         return err;
437                 }
438                         
439                 if ( !OBT(obddev) || !OBP(obddev, sync) ) {
440                         err = -EOPNOTSUPP;
441                         EXIT;
442                         return err;
443                 }
444
445                 /* XXX sync needs to be tested/verified */
446                 err = OBP(obddev, sync)(&conn, &range->obdo, range->count,
447                                         range->offset);
448
449                 if ( err ) {
450                         EXIT;
451                         return err;
452                 }
453                         
454                 return put_user(err, (int *) arg);
455         }
456         case OBD_IOC_CREATE: {
457                 struct oic_attr_s *attr = tmp_buf;
458
459                 err = copy_from_user(attr, (const void *)arg,  sizeof(*attr));
460                 if (err) {
461                         EXIT;
462                         return err;
463                 }
464
465                 /* has this minor been registered? */
466                 if ( !(obddev->obd_flags & OBD_ATTACHED) ||
467                      !(obddev->obd_flags & OBD_SET_UP)) {
468                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
469                         return -ENODEV;
470                 }
471                 conn.oc_id = attr->conn_id;
472
473                 if ( !OBT(obddev) || !OBP(obddev, create) )
474                         return -EOPNOTSUPP;
475
476                 err = OBP(obddev, create)(&conn, &attr->obdo);
477                 if (err) {
478                         EXIT;
479                         return err;
480                 }
481
482                 err = copy_to_user((int *)arg, attr, sizeof(*attr));
483                 EXIT;
484                 return err;
485         }
486
487         case OBD_IOC_DESTROY: {
488                 struct oic_attr_s *attr = tmp_buf;
489                 
490                 /* has this minor been registered? */
491                 if (!obddev->obd_type)
492                         return -ENODEV;
493
494                 err = copy_from_user(attr, (int *)arg, sizeof(*attr));
495                 if ( err ) {
496                         EXIT;
497                         return err;
498                 }
499
500                 if ( !OBT(obddev) || !OBP(obddev, destroy) )
501                         return -EOPNOTSUPP;
502
503                 conn.oc_id = attr->conn_id;
504                 err = OBP(obddev, destroy)(&conn, &attr->obdo);
505                 EXIT;
506                 return err;
507         }
508
509         case OBD_IOC_SETATTR: {
510                 struct oic_attr_s *attr = tmp_buf;
511
512                 /* has this minor been registered? */
513                 if (!obddev->obd_type)
514                         return -ENODEV;
515
516                 err = copy_from_user(attr, (int *)arg, sizeof(*attr));
517                 if (err)
518                         return err;
519
520                 if ( !OBT(obddev) || !OBP(obddev, setattr) )
521                         return -EOPNOTSUPP;
522                 
523                 conn.oc_id = attr->conn_id;
524                 err = OBP(obddev, setattr)(&conn, &attr->obdo);
525                 EXIT;
526                 return err;
527         }
528
529         case OBD_IOC_GETATTR: {
530                 struct oic_attr_s *attr = tmp_buf;
531
532                 err = copy_from_user(attr, (int *)arg, sizeof(*attr));
533                 if (err)
534                         return err;
535
536                 conn.oc_id = attr->conn_id;
537                 ODEBUG(&attr->obdo);
538                 err = OBP(obddev, getattr)(&conn, &attr->obdo);
539                 if ( err ) {
540                         EXIT;
541                         return err;
542                 }
543
544                 err = copy_to_user((int *)arg, attr, sizeof(*attr));
545                 EXIT;
546                 return err;
547         }
548
549         case OBD_IOC_READ: {
550                 int err;
551                 struct oic_rw_s *rw_s = tmp_buf;  /* read, write ioctl str */
552
553                 err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
554                 if ( err ) {
555                         EXIT;
556                         return err;
557                 }
558
559                 conn.oc_id = rw_s->conn_id;
560
561                 if ( !OBT(obddev) || !OBP(obddev, read) ) {
562                         err = -EOPNOTSUPP;
563                         EXIT;
564                         return err;
565                 }
566
567
568                 err = OBP(obddev, read)(&conn, &rw_s->obdo, rw_s->buf, 
569                                         &rw_s->count, rw_s->offset);
570                 
571                 ODEBUG(&rw_s->obdo);
572                 CDEBUG(D_INODE, "READ: conn %d, count %Ld, offset %Ld, '%s'\n",
573                        rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf);
574                 if ( err ) {
575                         EXIT;
576                         return err;
577                 }
578                         
579                 err = copy_to_user((int*)arg, &rw_s->count, sizeof(rw_s->count));
580                 EXIT;
581                 return err;
582         }
583
584         case OBD_IOC_WRITE: {
585                 struct oic_rw_s *rw_s = tmp_buf;  /* read, write ioctl str */
586
587                 err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s));
588                 if ( err ) {
589                         EXIT;
590                         return err;
591                 }
592
593                 conn.oc_id = rw_s->conn_id;
594
595                 if ( !OBT(obddev) || !OBP(obddev, write) ) {
596                         err = -EOPNOTSUPP;
597                         return err;
598                 }
599
600                 CDEBUG(D_INODE, "WRITE: conn %d, count %Ld, offset %Ld, '%s'\n",
601                        rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf);
602                 err = OBP(obddev, write)(&conn, &rw_s->obdo, rw_s->buf, 
603                                          &rw_s->count, rw_s->offset);
604                 ODEBUG(&rw_s->obdo);
605                 if ( err ) {
606                         EXIT;
607                         return err;
608                 }
609
610                 err = copy_to_user((int *)arg, &rw_s->count,
611                                    sizeof(rw_s->count));
612                 EXIT;
613                 return err;
614         }
615         case OBD_IOC_PREALLOCATE: {
616                 struct oic_prealloc_s *prealloc = tmp_buf;
617
618                 /* has this minor been registered? */
619                 if (!obddev->obd_type)
620                         return -ENODEV;
621
622                 err = copy_from_user(prealloc, (int *)arg, sizeof(*prealloc));
623                 if (err) 
624                         return -EFAULT;
625
626                 if ( !(obddev->obd_flags & OBD_ATTACHED) ||
627                      !(obddev->obd_flags & OBD_SET_UP)) {
628                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
629                         return -ENODEV;
630                 }
631
632                 if ( !OBT(obddev) || !OBP(obddev, preallocate) )
633                         return -EOPNOTSUPP;
634
635                 conn.oc_id = prealloc->conn_id;
636                 err = OBP(obddev, preallocate)(&conn, &prealloc->alloc,
637                                                prealloc->ids);
638                 if ( err ) {
639                         EXIT;
640                         return err;
641                 }
642
643                 err =copy_to_user((int *)arg, prealloc, sizeof(*prealloc));
644                 EXIT;
645                 return err;
646         }
647         case OBD_IOC_STATFS: {
648                 struct statfs *tmp;
649                 unsigned int conn_id;
650                 struct statfs buf;
651
652                 /* has this minor been registered? */
653                 if (!obddev->obd_type)
654                         return -ENODEV;
655
656                 tmp = (void *)arg + sizeof(unsigned int);
657                 get_user(conn_id, (int *) arg);
658
659                 if ( !OBT(obddev) || !OBP(obddev, statfs) )
660                         return -EOPNOTSUPP;
661
662                 conn.oc_id = conn_id;
663                 err = OBP(obddev, statfs)(&conn, &buf);
664                 if ( err ) {
665                         EXIT;
666                         return err;
667                 }
668                 err = copy_to_user(tmp, &buf, sizeof(buf));
669                 EXIT;
670                 return err;
671                 
672         }
673         case OBD_IOC_COPY: {
674                 struct ioc_mv_s *mvdata = tmp_buf;
675
676                 if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
677                      (!(obddev->obd_flags & OBD_ATTACHED))) {
678                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
679                         return -ENODEV;
680                 }
681
682                 /* get main structure */
683                 err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata));
684                 if (err) {
685                         EXIT;
686                         return err;
687                 }
688
689                 if ( !OBT(obddev) || !OBP(obddev, copy) )
690                         return -EOPNOTSUPP;
691
692                 /* do the partition */
693                 CDEBUG(D_IOCTL, "Copy %d, type %s dst %Ld src %Ld\n", dev, 
694                        obddev->obd_type->typ_name, mvdata->dst.o_id, 
695                        mvdata->src.o_id);
696
697                 conn.oc_id = mvdata->src_conn_id;
698
699                 err = OBP(obddev, copy)(&conn, &mvdata->dst, 
700                                         &conn, &mvdata->src, 
701                                         mvdata->src.o_size, 0);
702                 return err;
703         }
704
705         case OBD_IOC_MIGR: {
706                 struct ioc_mv_s *mvdata = tmp_buf;
707
708                 if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
709                      (!(obddev->obd_flags & OBD_ATTACHED))) {
710                         CDEBUG(D_IOCTL, "Device not attached or set up\n");
711                         return -ENODEV;
712                 }
713
714                 err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata));
715                 if (err) {
716                         EXIT;
717                         return err;
718                 }
719
720                 CDEBUG(D_IOCTL, "Migrate copying %d bytes\n", sizeof(*mvdata));
721
722                 if ( !OBT(obddev) || !OBP(obddev, migrate) )
723                         return -EOPNOTSUPP;
724
725                 /* do the partition */
726                 CDEBUG(D_IOCTL, "Migrate %d, type %s conn %d src %Ld dst %Ld\n",
727                        dev, obddev->obd_type->typ_name, mvdata->src_conn_id,
728                        mvdata->src.o_id, mvdata->dst.o_id);
729
730                 conn.oc_id = mvdata->src_conn_id;
731                 err = OBP(obddev, migrate)(&conn, &mvdata->dst, &mvdata->src, 
732                                            mvdata->src.o_size, 0);
733
734                 return err;
735         }
736
737         default: {
738                 struct obd_type *type;
739                 struct oic_generic input;
740                 void *karg;
741
742                 /* get data structures */
743                 err = copy_from_user(&input, (void *)arg, sizeof(input));
744                 if ( err ) {
745                         EXIT;
746                         return err;
747                 }
748
749                 err = getdata(input.att_typelen + 1, &input.att_type);
750                 if ( err ) {
751                         EXIT;
752                         return err;
753                 }
754
755                 /* find the type */
756                 type = obd_nm_to_type(input.att_type);
757                 OBD_FREE(input.att_type, input.att_typelen + 1);
758                 if ( !type ) {
759                         printk(__FUNCTION__ ": unknown obd type dev %d\n", dev);
760                         EXIT;
761                         return -EINVAL;
762                 }
763                 
764                 if ( !type->typ_ops || !type->typ_ops->o_iocontrol ) {
765                         EXIT;
766                         return -EOPNOTSUPP;
767                 }
768                 conn.oc_id = input.att_connid;
769                 
770                 CDEBUG(D_IOCTL, "Calling ioctl %x for type %s, len %d\n",
771                        cmd, type->typ_name, input.att_datalen);
772
773                 /* get the generic data */
774                 karg = input.att_data;
775                 err = getdata(input.att_datalen, &karg);
776                 if ( err ) {
777                         EXIT;
778                         return err;
779                 }
780
781                 err = type->typ_ops->o_iocontrol(cmd, &conn, input.att_datalen, 
782                                                  karg, input.att_data);
783                 OBD_FREE(karg, input.att_datalen);
784
785                 EXIT;
786                 return err;
787         }
788         }
789 } /* obd_class_ioctl */
790
791 /* Driver interface done, utility functions follow */
792
793 int obd_register_type(struct obd_ops *ops, char *nm)
794 {
795         struct obd_type *type;
796
797
798         if (obd_init_magic != 0x11223344) {
799                 EXIT;
800                 return -EINVAL;
801         }
802
803         if  ( obd_nm_to_type(nm) ) {
804                 CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
805                 EXIT;
806                 return -EEXIST;
807         }
808         
809         OBD_ALLOC(type, struct obd_type * , sizeof(*type));
810         if ( !type ) {
811                 EXIT;
812                 return -ENOMEM;
813         }
814         memset(type, 0, sizeof(*type));
815         INIT_LIST_HEAD(&type->typ_chain);
816         MOD_INC_USE_COUNT;
817         list_add(&type->typ_chain, obd_types.next);
818         type->typ_ops = ops;
819         type->typ_name = nm;
820         EXIT;
821         return 0;
822 }
823         
824 int obd_unregister_type(char *nm)
825 {
826         struct obd_type *type = obd_nm_to_type(nm);
827
828         if ( !type ) {
829                 MOD_DEC_USE_COUNT;
830                 printk(KERN_INFO __FUNCTION__ ": unknown obd type\n");
831                 EXIT;
832                 return -EINVAL;
833         }
834
835         if ( type->typ_refcnt ) {
836                 MOD_DEC_USE_COUNT;
837                 printk(KERN_ALERT __FUNCTION__ ":type %s has refcount "
838                        "(%d)\n", nm, type->typ_refcnt);
839                 EXIT;
840                 return -EBUSY;
841         }
842
843         list_del(&type->typ_chain);
844         OBD_FREE(type, sizeof(*type));
845         MOD_DEC_USE_COUNT;
846         return 0;
847 } /* obd_unregister_type */
848
849 /* declare character device */
850 static struct file_operations obd_psdev_fops = {
851         NULL,                  /* llseek */
852         NULL,                  /* read */
853         NULL,                  /* write */
854         NULL,                  /* presto_psdev_readdir */
855         NULL,                  /* poll */
856         obd_class_ioctl,       /* ioctl */
857         NULL,                  /* presto_psdev_mmap */
858         obd_class_open,        /* open */
859         NULL,
860         obd_class_release,     /* release */
861         NULL,                  /* fsync */
862         NULL,                  /* fasync */
863         NULL,                  /* check_media_change */
864         NULL,                  /* revalidate */
865         NULL                   /* lock */
866 };
867
868
869 /* modules setup */
870
871 int init_obd(void)
872 {
873         int err;
874         int i;
875
876         printk(KERN_INFO "OBD class driver  v0.01, braam@stelias.com\n");
877         
878         INIT_LIST_HEAD(&obd_types);
879         
880         if (register_chrdev(OBD_PSDEV_MAJOR,"obd_psdev", 
881                             &obd_psdev_fops)) {
882                 printk(KERN_ERR __FUNCTION__ ": unable to get major %d\n", 
883                        OBD_PSDEV_MAJOR);
884                 return -EIO;
885         }
886
887         for (i = 0; i < MAX_OBD_DEVICES; i++) {
888                 memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
889                 obd_dev[i].obd_minor = i;
890                 INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients);
891         }
892
893         err = obd_init_obdo_cache();
894         if (err)
895                 return err;
896         obd_sysctl_init();
897         obd_init_magic = 0x11223344;
898         return 0;
899 }
900
901 EXPORT_SYMBOL(obd_register_type);
902 EXPORT_SYMBOL(obd_unregister_type);
903
904 EXPORT_SYMBOL(obd_print_entry);
905 EXPORT_SYMBOL(obd_debug_level);
906 EXPORT_SYMBOL(obd_dev);
907
908 EXPORT_SYMBOL(gen_connect);
909 EXPORT_SYMBOL(gen_client);
910 EXPORT_SYMBOL(gen_cleanup);
911 EXPORT_SYMBOL(gen_disconnect);
912 EXPORT_SYMBOL(gen_copy_data); 
913 EXPORT_SYMBOL(obdo_cachep);
914
915 /* EXPORT_SYMBOL(gen_multi_attach); */
916 EXPORT_SYMBOL(gen_multi_setup);
917 EXPORT_SYMBOL(gen_multi_cleanup);
918
919
920 #ifdef MODULE
921 int init_module(void)
922 {
923         return init_obd();
924 }
925
926 void cleanup_module(void)
927 {
928         int i;
929         ENTRY;
930
931         unregister_chrdev(OBD_PSDEV_MAJOR, "obd_psdev");
932         for (i = 0; i < MAX_OBD_DEVICES; i++) {
933                 struct obd_device *obddev = &obd_dev[i];
934                 if ( obddev->obd_type && 
935                      (obddev->obd_flags & OBD_SET_UP) &&
936                      OBT(obddev) && OBP(obddev, detach) ) {
937                         /* XXX should this call generic detach otherwise? */
938                         OBP(obddev, detach)(obddev);
939                 } 
940         }
941
942         obd_cleanup_obdo_cache();
943         obd_sysctl_clean();
944         obd_init_magic = 0;
945         EXIT;
946 }
947 #endif