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 int obd_print_entry = 1;
60 int obd_debug_level = 4095;
61 struct obd_device obd_dev[MAX_OBD_DEVICES];
62 struct list_head obd_types;
64 /* called when opening /dev/obdNNN */
65 static int obd_class_open(struct inode * inode, struct file * file)
72 dev = MINOR(inode->i_rdev);
73 if (dev >= MAX_OBD_DEVICES)
75 obd_dev[dev].obd_refcnt++;
76 CDEBUG(D_PSDEV, "Refcount now %d\n", obd_dev[dev].obd_refcnt++);
83 /* called when closing /dev/obdNNN */
84 static int obd_class_release(struct inode * inode, struct file * file)
91 dev = MINOR(inode->i_rdev);
92 if (dev >= MAX_OBD_DEVICES)
94 fsync_dev(inode->i_rdev);
95 if (obd_dev[dev].obd_refcnt <= 0)
96 printk(KERN_ALERT "presto_psdev_release: refcount(%d) <= 0\n",
97 obd_dev[dev].obd_refcnt);
98 obd_dev[dev].obd_refcnt--;
100 CDEBUG(D_PSDEV, "Refcount now %d\n", obd_dev[dev].obd_refcnt++);
108 /* support function */
109 static struct obd_type *obd_nm_to_type(char *nm)
111 struct list_head *tmp;
112 struct obd_type *type;
115 while ( (tmp = tmp->next) != &obd_types ) {
116 type = list_entry(tmp, struct obd_type, typ_chain);
117 if (strlen(type->typ_name) == strlen(nm) &&
118 strcmp(type->typ_name, nm) == 0 ) {
126 static int getdata(int len, void **data)
133 OBD_ALLOC(tmp, void *, len);
138 if ( copy_from_user(tmp, *data, len)) {
147 /* to control /dev/obdNNN */
148 static int obd_class_ioctl (struct inode * inode, struct file * filp,
149 unsigned int cmd, unsigned long arg)
152 struct obd_device *obddev;
153 struct oic_rw_s rw_s; /* read, write */
154 long int cli_id; /* connect, disconnect */
156 struct oic_prealloc_s prealloc; /* preallocate */
161 dev = MINOR(inode->i_rdev);
162 if (dev > MAX_OBD_DEVICES)
164 obddev = &obd_dev[dev];
167 case OBD_IOC_ATTACH: {
168 struct obd_type *type;
169 struct oic_attach input;
171 /* have we attached a type to this device */
172 if ( obddev->obd_type || (obddev->obd_flags & OBD_ATTACHED) ){
173 CDEBUG(D_IOCTL, "OBD Device %d already attached to type %s.\n", dev, obddev->obd_type->typ_name);
177 /* get data structures */
178 err = copy_from_user(&input, (void *) arg, sizeof(input));
182 if ( (err = getdata(input.att_typelen + 1, &input.att_type)) )
187 type = obd_nm_to_type(input.att_type);
188 OBD_FREE(input.att_type, input.att_typelen + 1);
190 printk("Unknown obd type dev %d\n", dev);
193 obddev->obd_type = type;
195 /* get the attach data */
196 if ( (err = getdata(input.att_datalen, &input.att_data)) ) {
200 CDEBUG(D_IOCTL, "Attach %d, type %s\n",
201 dev, obddev->obd_type->typ_name);
202 if (!obddev->obd_type->typ_ops || !OBP(obddev,attach)) {
203 obddev->obd_flags |= OBD_ATTACHED;
210 err = OBP(obddev,attach)(obddev,
211 input.att_datalen, &input.att_data);
212 OBD_FREE(input.att_data, input.att_datalen);
215 obddev->obd_flags &= ~OBD_ATTACHED;
216 obddev->obd_type = NULL;
218 obddev->obd_flags |= OBD_ATTACHED;
224 case OBD_IOC_FORMAT: {
230 /* have we attached a type to this device */
231 if ( !obddev->obd_type ) {
232 CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
236 /* get main structure */
237 err = copy_from_user(&input, (void *) arg, sizeof(input));
241 err = getdata(input.format_datalen, &input.format_data);
245 if (!obddev->obd_type->typ_ops ||
246 !obddev->obd_type->typ_ops->o_format )
250 CDEBUG(D_IOCTL, "Format %d, type %s\n", dev,
251 obddev->obd_type->typ_name);
252 err = obddev->obd_type->typ_ops->o_format
253 (obddev, input.format_datalen, input.format_data);
255 OBD_FREE(input.format_data, input.format_datalen);
258 case OBD_IOC_PARTITION: {
264 /* have we attached a type to this device */
265 if ( !obddev->obd_type ) {
266 CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
270 /* get main structure */
271 err = copy_from_user(&input, (void *) arg, sizeof(input));
275 err = getdata(input.part_datalen, &input.part_data);
279 if (!obddev->obd_type->typ_ops ||
280 !obddev->obd_type->typ_ops->o_partition )
283 /* do the partition */
284 CDEBUG(D_IOCTL, "Partition %d, type %s\n", dev,
285 obddev->obd_type->typ_name);
286 err = obddev->obd_type->typ_ops->o_partition
287 (obddev, input.part_datalen, input.part_data);
289 OBD_FREE(input.part_data, input.part_datalen);
292 case OBD_IOC_SETUP_OBDDEV: {
298 /* have we attached a type to this device */
299 if (!(obddev->obd_flags & OBD_ATTACHED)) {
300 CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
304 /* has this been done already? */
305 if ( obddev->obd_flags & OBD_SET_UP ) {
306 CDEBUG(D_IOCTL, "Device %d already setup (type %s)\n",
307 dev, obddev->obd_type->typ_name);
311 /* get main structure */
312 err = copy_from_user(&input, (void *) arg, sizeof(input));
316 err = getdata(input.setup_datalen, &input.setup_data);
321 CDEBUG(D_IOCTL, "Setup %d, type %s\n", dev,
322 obddev->obd_type->typ_name);
323 if ( !obddev->obd_type->typ_ops ||
324 !obddev->obd_type->typ_ops->o_setup ) {
325 obddev->obd_flags |= OBD_SET_UP;
329 err = obddev->obd_type->typ_ops->o_setup
330 (obddev, input.setup_datalen, input.setup_data);
333 obddev->obd_flags &= ~OBD_SET_UP;
335 obddev->obd_flags |= OBD_SET_UP;
338 case OBD_IOC_CLEANUP: {
341 /* has this minor been registered? */
342 if (!obddev->obd_type)
345 if ( !obddev->obd_type->typ_refcnt )
346 printk("OBD_CLEANUP: refcount wrap!\n");
348 if ( !obddev->obd_type->typ_ops->o_cleanup )
351 /* cleanup has no argument */
352 rc = OBP(obddev, cleanup)(obddev);
357 obddev->obd_flags = 0;
358 obddev->obd_type->typ_refcnt--;
359 obddev->obd_type = NULL;
363 case OBD_IOC_CONNECT:
365 struct obd_conn_info conninfo;
367 if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
368 (!(obddev->obd_flags & OBD_ATTACHED))) {
369 CDEBUG(D_IOCTL, "Device not attached or set up\n");
373 if (obddev->obd_type->typ_ops->o_connect(obddev, &conninfo))
376 return copy_to_user((int *)arg, &conninfo,
377 sizeof(struct obd_conn_info));
379 case OBD_IOC_DISCONNECT:
380 /* frees data structures */
381 /* has this minor been registered? */
382 if (!obddev->obd_type)
385 get_user(cli_id, (int *) arg);
387 OBP(obddev, disconnect)(cli_id);
391 /* sync doesn't need a connection ID, because it knows
392 * what device it was called on, and can thus get the
393 * superblock that it needs. */
394 /* has this minor been registered? */
395 if (!obddev->obd_type)
398 if (!obddev->u.sim.sim_sb || !obddev->u.sim.sim_sb->s_dev) {
399 CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
402 if ((err = fsync_dev(obddev->u.sim.sim_sb->s_dev)))
403 CDEBUG(D_IOCTL, "sync: fsync_dev failure\n");
405 CDEBUG(D_IOCTL, "sync: success\n");
408 return put_user(err, (int *) arg);
410 case OBD_IOC_CREATE: {
412 struct oic_create_s foo;
414 if ( copy_from_user(&foo, (const void *)arg, sizeof(foo)) )
417 /* has this minor been registered? */
418 if ( !(obddev->obd_flags & OBD_ATTACHED) ||
419 !(obddev->obd_flags & OBD_SET_UP))
423 if (!obddev->u.sim.sim_sb) {
424 CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
425 return put_user(-EINVAL, (int *) arg);
428 i_ino = OBP(obddev, create)(foo.conn_id, foo.prealloc, &err);
430 CDEBUG(D_IOCTL, "create: obd_inode_new failure\n");
431 /* 0 is the only error value */
432 return put_user(0, (int *) arg);
435 return put_user(i_ino, (int *) arg);
437 case OBD_IOC_DESTROY:
440 unsigned int conn_id;
444 /* has this minor been registered? */
445 if (!obddev->obd_type)
449 copy_from_user(&destroy, (int *)arg, sizeof(struct destroy_s));
450 if ( !obddev->obd_type ||
451 !obddev->obd_type->typ_ops->o_destroy)
454 return obddev->obd_type->typ_ops->o_destroy(destroy.conn_id, destroy.ino);
456 case OBD_IOC_SETATTR:
459 struct oic_attr_s foo;
462 /* has this minor been registered? */
463 if (!obddev->obd_type)
467 err= copy_from_user(&foo, (int *)arg, sizeof(foo));
471 if ( !obddev->obd_type ||
472 !obddev->obd_type->typ_ops->o_setattr)
475 inode_setattr(&holder, &foo.iattr);
476 return obddev->obd_type->typ_ops->o_setattr(foo.conn_id, foo.ino, &holder);
479 case OBD_IOC_GETATTR:
483 unsigned int conn_id;
488 copy_from_user(&foo, (int *)arg, sizeof(struct tmp));
490 if ( !obddev->obd_type ||
491 !obddev->obd_type->typ_ops->o_getattr)
494 if (obddev->obd_type->typ_ops->o_getattr(foo.conn_id,
498 inode_to_iattr(&holder, &iattr);
499 err = copy_to_user((int *)arg, &iattr, sizeof(iattr));
507 /* has this minor been registered? */
508 if (!obddev->obd_type)
511 err = copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
515 if ( !obddev->obd_type->typ_ops ||
516 !obddev->obd_type->typ_ops->o_read )
519 rw_s.count = obddev->obd_type->typ_ops->o_read2(rw_s.conn_id,
528 err = copy_to_user((int*)arg, &rw_s.count,
529 sizeof(unsigned long));
537 /* has this minor been registered? */
538 if (!obddev->obd_type)
542 err = copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
546 if ( !obddev->obd_type->typ_ops ||
547 !obddev->obd_type->typ_ops->o_read )
550 rw_s.count = obddev->obd_type->typ_ops->o_read(rw_s.conn_id,
559 err = copy_to_user((int*)arg, &rw_s.count,
560 sizeof(unsigned long));
567 /* has this minor been registered? */
568 if (!obddev->obd_type)
572 copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
573 CDEBUG(D_IOCTL, "\n");
574 if ( !obddev->obd_type->typ_ops->o_write )
577 obddev->obd_type->typ_ops->o_write(rw_s.conn_id,
584 printk("Result rw_s.count %ld\n", rw_s.count);
585 return (int)rw_s.count;
586 copy_to_user((int *)arg, &rw_s.count,
587 sizeof(unsigned long));
590 case OBD_IOC_PREALLOCATE:
591 /* has this minor been registered? */
592 if (!obddev->obd_type)
596 copy_from_user(&prealloc, (int *)arg,
597 sizeof(struct oic_prealloc_s));
599 if (!obddev->u.sim.sim_sb || !obddev->u.sim.sim_sb->s_dev) {
600 CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
604 if (!obddev->obd_type ||
605 !obddev->obd_type->typ_ops->o_preallocate)
609 obddev->obd_type->typ_ops->o_preallocate(prealloc.cli_id, prealloc.alloc,
610 prealloc.inodes, &err);
613 return copy_to_user((int *)arg, &prealloc,
614 sizeof(struct oic_prealloc_s));
618 unsigned int conn_id;
622 /* has this minor been registered? */
623 if (!obddev->obd_type)
626 tmp = (void *)arg + sizeof(unsigned int);
627 get_user(conn_id, (int *) arg);
628 if ( !obddev->obd_type ||
629 !obddev->obd_type->typ_ops->o_statfs)
632 rc = obddev->obd_type->typ_ops->o_statfs(conn_id, &buf);
635 rc = copy_to_user(tmp, &buf, sizeof(buf));
640 printk("invalid ioctl: cmd = %x, arg = %lx\n", cmd, arg);
645 /* Driver interface done, utility functions follow */
647 int obd_register_type(struct obd_ops *ops, char *nm)
649 struct obd_type *type;
651 if ( obd_nm_to_type(nm) ) {
652 CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
656 OBD_ALLOC(type, struct obd_type * , sizeof(*type));
659 memset(type, 0, sizeof(*type));
660 INIT_LIST_HEAD(&type->typ_chain);
662 list_add(&type->typ_chain, obd_types.next);
668 int obd_unregister_type(char *nm)
670 struct obd_type *type = obd_nm_to_type(nm);
675 if ( type->typ_refcnt )
678 list_del(&type->typ_chain);
679 OBD_FREE(type, sizeof(*type));
683 /* declare character device */
684 static struct file_operations obd_psdev_fops = {
688 NULL, /* presto_psdev_readdir */
690 obd_class_ioctl, /* ioctl */
691 NULL, /* presto_psdev_mmap */
692 obd_class_open, /* open */
694 obd_class_release, /* release */
697 NULL, /* check_media_change */
698 NULL, /* revalidate */
709 printk(KERN_INFO "OBD class driver v0.002, braam@stelias.com\n");
711 INIT_LIST_HEAD(&obd_types);
713 if (register_chrdev(OBD_PSDEV_MAJOR,"obd_psdev",
715 printk(KERN_ERR "obd_psdev: unable to get major %d\n",
720 for (i = 0; i < MAX_OBD_DEVICES; i++) {
721 memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
722 INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients);
730 EXPORT_SYMBOL(obd_register_type);
731 EXPORT_SYMBOL(obd_unregister_type);
733 EXPORT_SYMBOL(obd_print_entry);
734 EXPORT_SYMBOL(obd_debug_level);
735 EXPORT_SYMBOL(obd_dev);
737 EXPORT_SYMBOL(gen_connect);
738 EXPORT_SYMBOL(gen_client);
739 EXPORT_SYMBOL(gen_cleanup);
740 EXPORT_SYMBOL(gen_disconnect);
742 EXPORT_SYMBOL(gen_multi_attach);
743 EXPORT_SYMBOL(gen_multi_setup);
744 EXPORT_SYMBOL(gen_multi_cleanup);
748 int init_module(void)
753 void cleanup_module(void)
758 unregister_chrdev(OBD_PSDEV_MAJOR, "obd_psdev");
759 for (i = 0; i < MAX_OBD_DEVICES; i++) {
760 struct obd_device *obddev = &obd_dev[i];
761 if ( obddev->obd_type &&
762 obddev->obd_type->typ_ops->o_cleanup_device )
763 OBP(obddev, cleanup_device)(obddev);