2 * An implementation of a loadable kernel mode driver providing
3 * multiple kernel/user space bidirectional communications links.
5 * Author: Alan Cox <alan@cymru.net>
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.
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>
16 * Changes for Linux 2.1
17 * Copyright (c) 1997 Carnegie-Mellon University
19 * Redone again for Intermezzo
20 * Copyright (c) 1998 Peter J. Braam
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.
32 #include <linux/config.h> /* for CONFIG_PROC_FS */
33 #include <linux/module.h>
34 #include <linux/errno.h>
35 #include <linux/kernel.h>
36 #include <linux/major.h>
37 #include <linux/sched.h>
39 #include <linux/malloc.h>
40 #include <linux/ioport.h>
41 #include <linux/fcntl.h>
42 #include <linux/delay.h>
43 #include <linux/skbuff.h>
44 #include <linux/proc_fs.h>
45 #include <linux/vmalloc.h>
47 #include <linux/poll.h>
48 #include <linux/init.h>
49 #include <linux/list.h>
51 #include <asm/segment.h>
52 #include <asm/system.h>
54 #include <asm/uaccess.h>
56 #include <linux/obd_support.h>
57 #include <linux/obd_class.h>
59 static int obd_init_magic;
60 int obd_print_entry = 1;
61 int obd_debug_level = 4095;
62 struct obd_device obd_dev[MAX_OBD_DEVICES];
63 struct list_head obd_types;
65 /* called when opening /dev/obdNNN */
66 static int obd_class_open(struct inode * inode, struct file * file)
73 dev = MINOR(inode->i_rdev);
74 if (dev >= MAX_OBD_DEVICES)
76 obd_dev[dev].obd_refcnt++;
77 CDEBUG(D_PSDEV, "Refcount now %d\n", obd_dev[dev].obd_refcnt++);
84 /* called when closing /dev/obdNNN */
85 static int obd_class_release(struct inode * inode, struct file * file)
92 dev = MINOR(inode->i_rdev);
93 if (dev >= MAX_OBD_DEVICES)
95 fsync_dev(inode->i_rdev);
96 if (obd_dev[dev].obd_refcnt <= 0)
97 printk(KERN_ALERT "presto_psdev_release: refcount(%d) <= 0\n",
98 obd_dev[dev].obd_refcnt);
99 obd_dev[dev].obd_refcnt--;
101 CDEBUG(D_PSDEV, "Refcount now %d\n", obd_dev[dev].obd_refcnt++);
109 /* support function */
110 static struct obd_type *obd_nm_to_type(char *nm)
112 struct list_head *tmp;
113 struct obd_type *type;
114 CDEBUG(D_IOCTL, "SEARCH %s\n", nm);
117 while ( (tmp = tmp->next) != &obd_types ) {
118 type = list_entry(tmp, struct obd_type, typ_chain);
119 CDEBUG(D_IOCTL, "TYP %s\n", type->typ_name);
120 if (strlen(type->typ_name) == strlen(nm) &&
121 strcmp(type->typ_name, nm) == 0 ) {
129 static int getdata(int len, void **data)
136 CDEBUG(D_IOCTL, "getdata: len %d, add %p\n", len, *data);
138 OBD_ALLOC(tmp, void *, len);
143 if ( copy_from_user(tmp, *data, len)) {
152 /* to control /dev/obdNNN */
153 static int obd_class_ioctl (struct inode * inode, struct file * filp,
154 unsigned int cmd, unsigned long arg)
157 struct obd_device *obddev;
158 struct obd_conn conn;
159 long int cli_id; /* connect, disconnect */
164 dev = MINOR(inode->i_rdev);
165 if (dev > MAX_OBD_DEVICES)
167 obddev = &obd_dev[dev];
168 conn.oc_dev = obddev;
171 case OBD_IOC_ATTACH: {
172 struct obd_type *type;
173 struct oic_attach input;
175 /* have we attached a type to this device */
176 if ( obddev->obd_type || (obddev->obd_flags & OBD_ATTACHED) ){
177 CDEBUG(D_IOCTL, "OBD Device %d already attached to type %s.\n", dev, obddev->obd_type->typ_name);
181 /* get data structures */
182 err = copy_from_user(&input, (void *) arg, sizeof(input));
186 if ( (err = getdata(input.att_typelen + 1, &input.att_type)) )
191 type = obd_nm_to_type(input.att_type);
192 OBD_FREE(input.att_type, input.att_typelen + 1);
194 printk("Unknown obd type dev %d\n", dev);
197 obddev->obd_type = type;
199 /* get the attach data */
200 if ( (err = getdata(input.att_datalen, &input.att_data)) ) {
204 INIT_LIST_HEAD(&obddev->obd_gen_clients);
205 obddev->obd_multi_count = 0;
207 CDEBUG(D_IOCTL, "Attach %d, datalen %d, type %s\n",
208 dev, input.att_datalen, obddev->obd_type->typ_name);
209 if (!obddev->obd_type->typ_ops || !OBP(obddev,attach)) {
210 obddev->obd_flags |= OBD_ATTACHED;
217 err = OBP(obddev,attach)(obddev,
218 input.att_datalen, input.att_data);
219 OBD_FREE(input.att_data, input.att_datalen);
222 obddev->obd_flags &= ~OBD_ATTACHED;
223 obddev->obd_type = NULL;
225 obddev->obd_flags |= OBD_ATTACHED;
232 case OBD_IOC_DETACH: {
234 if (obddev->obd_flags & OBD_SET_UP)
236 if (! (obddev->obd_flags & OBD_ATTACHED) )
238 if ( !list_empty(&obddev->obd_gen_clients) )
241 obddev->obd_flags &= ~OBD_ATTACHED;
242 obddev->obd_type->typ_refcnt--;
243 obddev->obd_type = NULL;
249 case OBD_IOC_FORMAT: {
255 /* have we attached a type to this device */
256 if ( !obddev->obd_type ) {
257 CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
261 /* get main structure */
262 err = copy_from_user(&input, (void *) arg, sizeof(input));
266 err = getdata(input.format_datalen, &input.format_data);
270 if (!obddev->obd_type->typ_ops ||
271 !obddev->obd_type->typ_ops->o_format )
275 CDEBUG(D_IOCTL, "Format %d, type %s\n", dev,
276 obddev->obd_type->typ_name);
277 err = obddev->obd_type->typ_ops->o_format
278 (obddev, input.format_datalen, input.format_data);
280 OBD_FREE(input.format_data, input.format_datalen);
283 case OBD_IOC_PARTITION: {
289 /* have we attached a type to this device */
290 if ( !obddev->obd_type ) {
291 CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
295 /* get main structure */
296 err = copy_from_user(&input, (void *) arg, sizeof(input));
300 err = getdata(input.part_datalen, &input.part_data);
304 if (!obddev->obd_type->typ_ops ||
305 !obddev->obd_type->typ_ops->o_partition )
308 /* do the partition */
309 CDEBUG(D_IOCTL, "Partition %d, type %s\n", dev,
310 obddev->obd_type->typ_name);
311 err = obddev->obd_type->typ_ops->o_partition
312 (obddev, input.part_datalen, input.part_data);
314 OBD_FREE(input.part_data, input.part_datalen);
319 struct ioc_mv_s mvdata;
324 obdattr *srcoa, *tgtoa;
326 if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
327 (!(obddev->obd_flags & OBD_ATTACHED))) {
328 CDEBUG(D_IOCTL, "Device not attached or set up\n");
332 /* get main structure */
333 err = copy_from_user(&input, (void *) arg, sizeof(input));
338 err = copy_from_user(&mvdata, input.part_data, sizeof(mvdata));
342 if (!obddev->obd_type->typ_ops ||
343 !obddev->obd_type->typ_ops->o_copy )
346 /* do the partition */
347 CDEBUG(D_IOCTL, "Copy %d, type %s src %ld tgt %ld\n", dev,
348 obddev->obd_type->typ_name, mvdata.src, mvdata.tgt);
350 conn.oc_id = mvdata.conn_id;
351 srcoa = obd_oa_fromid(&conn, mvdata.src);
354 tgtoa = obd_oa_fromid(&conn, mvdata.tgt);
360 err = obddev->obd_type->typ_ops->o_copy(&conn,srcoa, tgtoa);
367 struct ioc_mv_s mvdata;
372 obdattr *srcoa, *tgtoa;
374 if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
375 (!(obddev->obd_flags & OBD_ATTACHED))) {
376 CDEBUG(D_IOCTL, "Device not attached or set up\n");
380 /* get main structure */
381 err = copy_from_user(&input, (void *) arg, sizeof(input));
386 CDEBUG(D_IOCTL, "Migrate copying %d\n", sizeof(mvdata));
387 err = copy_from_user(&mvdata, input.part_data, sizeof(mvdata));
391 if (!obddev->obd_type->typ_ops ||
392 !obddev->obd_type->typ_ops->o_copy )
395 /* do the partition */
396 CDEBUG(D_IOCTL, "Migrate %d, type %s conn %d src %ld tgt %ld\n", dev,
397 obddev->obd_type->typ_name, mvdata.conn_id, mvdata.src, mvdata.tgt);
400 if ( ! (srcoa = obd_empty_oa()) )
402 if ( ! (tgtoa = obd_empty_oa()) ) {
407 srcoa->i_ino = mvdata.src;
408 tgtoa->i_ino = mvdata.tgt;
410 conn.oc_id = mvdata.conn_id;
412 err = obddev->obd_type->typ_ops->o_migrate(&conn, tgtoa, srcoa);
419 case OBD_IOC_SETUP: {
425 /* have we attached a type to this device */
426 if (!(obddev->obd_flags & OBD_ATTACHED)) {
427 CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
431 /* has this been done already? */
432 if ( obddev->obd_flags & OBD_SET_UP ) {
433 CDEBUG(D_IOCTL, "Device %d already setup (type %s)\n",
434 dev, obddev->obd_type->typ_name);
438 /* get main structure */
439 err = copy_from_user(&input, (void *) arg, sizeof(input));
443 err = getdata(input.setup_datalen, &input.setup_data);
449 CDEBUG(D_IOCTL, "Setup %d, type %s\n", dev,
450 obddev->obd_type->typ_name);
451 if ( !obddev->obd_type->typ_ops ||
452 !obddev->obd_type->typ_ops->o_setup ) {
453 obddev->obd_flags |= OBD_SET_UP;
457 err = obddev->obd_type->typ_ops->o_setup
458 (obddev, input.setup_datalen, input.setup_data);
461 obddev->obd_flags &= ~OBD_SET_UP;
463 obddev->obd_type->typ_refcnt++;
464 obddev->obd_flags |= OBD_SET_UP;
468 case OBD_IOC_CLEANUP: {
471 /* has this minor been registered? */
472 if (!obddev->obd_type)
475 if ( !obddev->obd_type->typ_refcnt )
476 printk("OBD_CLEANUP: refcount wrap!\n");
478 if ( !obddev->obd_flags & OBD_SET_UP )
481 if ( !obddev->obd_type->typ_ops->o_cleanup )
484 /* cleanup has no argument */
485 rc = OBP(obddev, cleanup)(obddev);
490 obddev->obd_flags &= ~OBD_SET_UP;
491 obddev->obd_type->typ_refcnt--;
494 case OBD_IOC_CONNECT:
497 if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
498 (!(obddev->obd_flags & OBD_ATTACHED))) {
499 CDEBUG(D_IOCTL, "Device not attached or set up\n");
504 if (obddev->obd_type->typ_ops->o_connect(&conn))
507 return copy_to_user((int *)arg, &conn.oc_id,
510 case OBD_IOC_DISCONNECT:
511 /* frees data structures */
512 /* has this minor been registered? */
513 if (!obddev->obd_type)
516 get_user(cli_id, (int *) arg);
519 OBP(obddev, disconnect)(&conn);
523 /* sync doesn't need a connection ID, because it knows
524 * what device it was called on, and can thus get the
525 * superblock that it needs. */
526 /* has this minor been registered? */
527 if (!obddev->obd_type)
530 if (!obddev->u.ext2.ext2_sb || !obddev->u.ext2.ext2_sb->s_dev) {
531 CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
534 if ((err = fsync_dev(obddev->u.ext2.ext2_sb->s_dev)))
535 CDEBUG(D_IOCTL, "sync: fsync_dev failure\n");
537 CDEBUG(D_IOCTL, "sync: success\n");
540 return put_user(err, (int *) arg);
542 case OBD_IOC_CREATE: {
544 struct oic_create_s foo;
546 if ( copy_from_user(&foo, (const void *)arg, sizeof(foo)) )
549 /* has this minor been registered? */
550 if ( !(obddev->obd_flags & OBD_ATTACHED) ||
551 !(obddev->obd_flags & OBD_SET_UP))
553 conn.oc_id = foo.conn_id;
555 i_ino = OBP(obddev, create)(&conn, foo.prealloc, &err);
557 CDEBUG(D_IOCTL, "create: obd_inode_new failure\n");
558 /* 0 is the only error value */
559 return put_user(0, (int *) arg);
562 return put_user(i_ino, (int *) arg);
564 case OBD_IOC_DESTROY:
567 unsigned int conn_id;
573 if ( ! (oa = obd_empty_oa()) )
576 /* has this minor been registered? */
577 if (!obddev->obd_type)
581 copy_from_user(&destroy, (int *)arg, sizeof(struct destroy_s));
582 if ( !obddev->obd_type ||
583 !obddev->obd_type->typ_ops->o_destroy)
586 oa->i_ino = destroy.ino;
587 conn.oc_id = destroy.conn_id;
588 rc = obddev->obd_type->typ_ops->o_destroy(&conn, oa);
589 OBD_FREE(oa, sizeof(*oa));
592 case OBD_IOC_SETATTR:
594 struct oic_attr_s foo;
598 if ( ! (oa = obd_empty_oa()) )
601 /* has this minor been registered? */
602 if (!obddev->obd_type)
605 rc = copy_from_user(&foo, (int *)arg, sizeof(foo));
609 if ( !obddev->obd_type ||
610 !obddev->obd_type->typ_ops->o_setattr)
614 inode_setattr(oa, &foo.iattr);
615 conn.oc_id = foo.conn_id;
616 rc = obddev->obd_type->typ_ops->o_setattr(&conn, oa);
617 OBD_FREE(oa, sizeof(*oa));
621 case OBD_IOC_GETATTR:
625 unsigned int conn_id;
631 rc = copy_from_user(&foo, (int *)arg, sizeof(foo));
635 conn.oc_id = foo.conn_id;
636 oa = obd_oa_fromid(&conn, foo.ino);
640 inode_to_iattr(oa, &iattr);
641 rc = copy_to_user((int *)arg, &iattr, sizeof(iattr));
649 struct oic_rw_s rw_s; /* read, write ioctl str */
651 rc = copy_from_user(&rw_s, (int *)arg, sizeof(rw_s));
656 conn.oc_id = rw_s.conn_id;
657 if ( ! (oa = obd_oa_fromid(&conn, rw_s.id)) )
661 if ( !obddev->obd_type->typ_ops ||
662 !obddev->obd_type->typ_ops->o_read )
665 rc = obddev->obd_type->typ_ops->o_read
666 (&conn, oa, rw_s.buf, &rw_s.count, rw_s.offset);
670 rc = copy_to_user((int*)arg, &rw_s.count, sizeof(rw_s.count));
674 OBD_FREE(oa, sizeof(*oa));
678 case OBD_IOC_WRITE: {
681 struct oic_rw_s rw_s; /* read, write ioctl str */
683 rc = copy_from_user(&rw_s, (int *)arg, sizeof(rw_s));
687 conn.oc_id = rw_s.conn_id;
688 oa = obd_oa_fromid(&conn, rw_s.id);
693 if ( !obddev->obd_type->typ_ops ||
694 !obddev->obd_type->typ_ops->o_write )
697 rc = obddev->obd_type->typ_ops->o_write
698 (&conn, oa, rw_s.buf, &rw_s.count, rw_s.offset);
702 rc = copy_to_user((int*)arg, &rw_s.count, sizeof(rw_s.count));
705 OBD_FREE(oa, sizeof(*oa));
708 case OBD_IOC_PREALLOCATE: {
709 struct oic_prealloc_s prealloc;
712 /* has this minor been registered? */
713 if (!obddev->obd_type)
717 rc = copy_from_user(&prealloc, (int *)arg, sizeof(prealloc));
721 if ( !(obddev->obd_flags & OBD_ATTACHED) ||
722 !(obddev->obd_flags & OBD_SET_UP)) {
723 CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
727 if (!obddev->obd_type ||
728 !obddev->obd_type->typ_ops->o_preallocate)
730 conn.oc_id = prealloc.cli_id;
731 rc = obddev->obd_type->typ_ops->o_preallocate
732 (&conn, &prealloc.alloc, prealloc.inodes);
736 return copy_to_user((int *)arg, &prealloc, sizeof(prealloc));
741 unsigned int conn_id;
745 /* has this minor been registered? */
746 if (!obddev->obd_type)
749 tmp = (void *)arg + sizeof(unsigned int);
750 get_user(conn_id, (int *) arg);
751 if ( !obddev->obd_type ||
752 !obddev->obd_type->typ_ops->o_statfs)
755 conn.oc_id = conn_id;
756 rc = obddev->obd_type->typ_ops->o_statfs(&conn, &buf);
759 rc = copy_to_user(tmp, &buf, sizeof(buf));
764 printk("invalid ioctl: cmd = %x, arg = %lx\n", cmd, arg);
769 /* Driver interface done, utility functions follow */
771 int obd_register_type(struct obd_ops *ops, char *nm)
773 struct obd_type *type;
776 if (obd_init_magic != 0x11223344) {
781 if ( obd_nm_to_type(nm) ) {
782 CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
787 OBD_ALLOC(type, struct obd_type * , sizeof(*type));
792 memset(type, 0, sizeof(*type));
793 INIT_LIST_HEAD(&type->typ_chain);
795 list_add(&type->typ_chain, obd_types.next);
802 int obd_unregister_type(char *nm)
804 struct obd_type *type = obd_nm_to_type(nm);
808 printk("OBD: NO TYPE\n");
813 if ( type->typ_refcnt ) {
815 printk("OBD: refcount wrap\n");
820 list_del(&type->typ_chain);
821 OBD_FREE(type, sizeof(*type));
826 /* declare character device */
827 static struct file_operations obd_psdev_fops = {
831 NULL, /* presto_psdev_readdir */
833 obd_class_ioctl, /* ioctl */
834 NULL, /* presto_psdev_mmap */
835 obd_class_open, /* open */
837 obd_class_release, /* release */
840 NULL, /* check_media_change */
841 NULL, /* revalidate */
852 printk(KERN_INFO "OBD class driver v0.002, braam@stelias.com\n");
854 INIT_LIST_HEAD(&obd_types);
856 if (register_chrdev(OBD_PSDEV_MAJOR,"obd_psdev",
858 printk(KERN_ERR "obd_psdev: unable to get major %d\n",
863 for (i = 0; i < MAX_OBD_DEVICES; i++) {
864 memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
865 obd_dev[i].obd_minor = i;
866 INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients);
870 obd_init_magic = 0x11223344;
874 EXPORT_SYMBOL(obd_register_type);
875 EXPORT_SYMBOL(obd_unregister_type);
877 EXPORT_SYMBOL(obd_print_entry);
878 EXPORT_SYMBOL(obd_debug_level);
879 EXPORT_SYMBOL(obd_dev);
881 EXPORT_SYMBOL(gen_connect);
882 EXPORT_SYMBOL(gen_client);
883 EXPORT_SYMBOL(gen_cleanup);
884 EXPORT_SYMBOL(gen_disconnect);
885 EXPORT_SYMBOL(gen_copy_data);
887 /* EXPORT_SYMBOL(gen_multi_attach); */
888 EXPORT_SYMBOL(gen_multi_setup);
889 EXPORT_SYMBOL(gen_multi_cleanup);
893 int init_module(void)
898 void cleanup_module(void)
903 unregister_chrdev(OBD_PSDEV_MAJOR, "obd_psdev");
904 for (i = 0; i < MAX_OBD_DEVICES; i++) {
905 struct obd_device *obddev = &obd_dev[i];
906 if ( obddev->obd_type &&
907 (obddev->obd_flags & OBD_SET_UP) &&
908 obddev->obd_type->typ_ops->o_detach ) {
909 OBP(obddev, detach)(obddev);