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