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