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