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 ||
203 !obddev->obd_type->typ_ops->o_attach ) {
204 obddev->obd_flags |= OBD_ATTACHED;
211 err = obddev->obd_type->typ_ops->o_attach
212 (obddev, input.att_datalen, &input.att_data);
213 OBD_FREE(input.att_data, input.att_datalen);
216 obddev->obd_flags &= ~OBD_ATTACHED;
217 obddev->obd_type = NULL;
219 obddev->obd_flags |= OBD_ATTACHED;
225 case OBD_IOC_FORMAT: {
231 /* have we attached a type to this device */
232 if ( !obddev->obd_type ) {
233 CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
237 /* get main structure */
238 err = copy_from_user(&input, (void *) arg, sizeof(input));
242 err = getdata(input.format_datalen, &input.format_data);
246 if (!obddev->obd_type->typ_ops ||
247 !obddev->obd_type->typ_ops->o_format )
251 CDEBUG(D_IOCTL, "Format %d, type %s\n", dev,
252 obddev->obd_type->typ_name);
253 err = obddev->obd_type->typ_ops->o_format
254 (obddev, input.format_datalen, input.format_data);
256 OBD_FREE(input.format_data, input.format_datalen);
259 case OBD_IOC_PARTITION: {
265 /* have we attached a type to this device */
266 if ( !obddev->obd_type ) {
267 CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
271 /* get main structure */
272 err = copy_from_user(&input, (void *) arg, sizeof(input));
276 err = getdata(input.part_datalen, &input.part_data);
280 if (!obddev->obd_type->typ_ops ||
281 !obddev->obd_type->typ_ops->o_partition )
284 /* do the partition */
285 CDEBUG(D_IOCTL, "Partition %d, type %s\n", dev,
286 obddev->obd_type->typ_name);
287 err = obddev->obd_type->typ_ops->o_partition
288 (obddev, input.part_datalen, input.part_data);
290 OBD_FREE(input.part_data, input.part_datalen);
293 case OBD_IOC_SETUP_OBDDEV: {
299 /* have we attached a type to this device */
300 if (!(obddev->obd_flags & OBD_ATTACHED)) {
301 CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
305 /* has this been done already? */
306 if ( obddev->obd_flags & OBD_SET_UP ) {
307 CDEBUG(D_IOCTL, "Device %d already setup (type %s)\n",
308 dev, obddev->obd_type->typ_name);
312 /* get main structure */
313 err = copy_from_user(&input, (void *) arg, sizeof(input));
317 err = getdata(input.setup_datalen, &input.setup_data);
322 CDEBUG(D_IOCTL, "Setup %d, type %s\n", dev,
323 obddev->obd_type->typ_name);
324 if ( !obddev->obd_type->typ_ops ||
325 !obddev->obd_type->typ_ops->o_setup )
328 err = obddev->obd_type->typ_ops->o_setup
329 (obddev, input.setup_datalen, input.setup_data);
332 obddev->obd_flags &= ~OBD_SET_UP;
334 obddev->obd_flags |= OBD_SET_UP;
337 case OBD_IOC_CLEANUP_OBDDEV: {
340 /* has this minor been registered? */
341 if (!obddev->obd_type)
344 if ( !obddev->obd_type->typ_refcnt )
345 printk("OBD_CLEANUP: refcount wrap!\n");
347 if ( !obddev->obd_type->typ_ops->o_cleanup )
350 /* cleanup has no argument */
351 rc = obddev->obd_type->typ_ops->o_cleanup(obddev);
356 obddev->obd_flags = 0;
357 obddev->obd_type->typ_refcnt--;
358 obddev->obd_type = NULL;
362 case OBD_IOC_CONNECT:
364 struct obd_conn_info conninfo;
366 if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
367 (!(obddev->obd_flags & OBD_ATTACHED))) {
368 CDEBUG(D_IOCTL, "Device not attached or set up\n");
372 if (obddev->obd_type->typ_ops->o_connect(obddev, &conninfo))
375 return copy_to_user((int *)arg, &conninfo,
376 sizeof(struct obd_conn_info));
378 case OBD_IOC_DISCONNECT:
379 /* frees data structures */
380 /* has this minor been registered? */
381 if (!obddev->obd_type)
384 get_user(cli_id, (int *) arg);
386 obddev->obd_type->typ_ops->o_disconnect(cli_id);
390 /* sync doesn't need a connection ID, because it knows
391 * what device it was called on, and can thus get the
392 * superblock that it needs. */
393 /* has this minor been registered? */
394 if (!obddev->obd_type)
397 if (!obddev->u.sim.sim_sb || !obddev->u.sim.sim_sb->s_dev) {
398 CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
401 if ((err = fsync_dev(obddev->u.sim.sim_sb->s_dev)))
402 CDEBUG(D_IOCTL, "sync: fsync_dev failure\n");
404 CDEBUG(D_IOCTL, "sync: success\n");
407 return put_user(err, (int *) arg);
409 /* similarly, create doesn't need a connection ID for
410 * the same reasons. */
412 /* has this minor been registered? */
413 if (!obddev->obd_type)
417 if (!obddev->u.sim.sim_sb) {
418 CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
419 return put_user(-EINVAL, (int *) arg);
422 i_ino = obddev->obd_type->typ_ops->o_create(obddev, 0, &err);
424 CDEBUG(D_IOCTL, "create: obd_inode_new failure\n");
425 /* 0 is the only error value */
426 return put_user(0, (int *) arg);
429 return put_user(i_ino, (int *) arg);
430 case OBD_IOC_DESTROY:
433 unsigned int conn_id;
437 /* has this minor been registered? */
438 if (!obddev->obd_type)
442 copy_from_user(&destroy, (int *)arg, sizeof(struct destroy_s));
443 if ( !obddev->obd_type ||
444 !obddev->obd_type->typ_ops->o_destroy)
447 return obddev->obd_type->typ_ops->o_destroy(destroy.conn_id, destroy.ino);
449 case OBD_IOC_SETATTR:
453 unsigned int conn_id;
458 /* has this minor been registered? */
459 if (!obddev->obd_type)
463 err= copy_from_user(&foo, (int *)arg, sizeof(struct tmp));
467 if ( !obddev->obd_type ||
468 !obddev->obd_type->typ_ops->o_setattr)
471 inode_setattr(&holder, &foo.iattr);
472 return obddev->obd_type->typ_ops->o_setattr(foo.conn_id, foo.ino, &holder);
475 case OBD_IOC_GETATTR:
479 unsigned int conn_id;
484 copy_from_user(&foo, (int *)arg, sizeof(struct tmp));
486 if ( !obddev->obd_type ||
487 !obddev->obd_type->typ_ops->o_getattr)
490 if (obddev->obd_type->typ_ops->o_getattr(foo.conn_id,
494 inode_to_iattr(&holder, &iattr);
495 err = copy_to_user((int *)arg, &iattr, sizeof(iattr));
503 /* has this minor been registered? */
504 if (!obddev->obd_type)
507 err = copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
511 if ( !obddev->obd_type->typ_ops ||
512 !obddev->obd_type->typ_ops->o_read )
515 rw_s.count = obddev->obd_type->typ_ops->o_read2(rw_s.conn_id,
524 err = copy_to_user((int*)arg, &rw_s.count,
525 sizeof(unsigned long));
533 /* has this minor been registered? */
534 if (!obddev->obd_type)
538 err = copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
542 if ( !obddev->obd_type->typ_ops ||
543 !obddev->obd_type->typ_ops->o_read )
546 rw_s.count = obddev->obd_type->typ_ops->o_read(rw_s.conn_id,
555 err = copy_to_user((int*)arg, &rw_s.count,
556 sizeof(unsigned long));
563 /* has this minor been registered? */
564 if (!obddev->obd_type)
568 copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
569 CDEBUG(D_IOCTL, "\n");
570 if ( !obddev->obd_type->typ_ops->o_write )
573 obddev->obd_type->typ_ops->o_write(rw_s.conn_id,
580 printk("Result rw_s.count %ld\n", rw_s.count);
581 return (int)rw_s.count;
582 copy_to_user((int *)arg, &rw_s.count,
583 sizeof(unsigned long));
586 case OBD_IOC_PREALLOCATE:
587 /* has this minor been registered? */
588 if (!obddev->obd_type)
592 copy_from_user(&prealloc, (int *)arg,
593 sizeof(struct oic_prealloc_s));
595 if (!obddev->u.sim.sim_sb || !obddev->u.sim.sim_sb->s_dev) {
596 CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
600 if (!obddev->obd_type ||
601 !obddev->obd_type->typ_ops->o_preallocate)
605 obddev->obd_type->typ_ops->o_preallocate(prealloc.cli_id, prealloc.alloc,
606 prealloc.inodes, &err);
609 return copy_to_user((int *)arg, &prealloc,
610 sizeof(struct oic_prealloc_s));
614 unsigned int conn_id;
618 /* has this minor been registered? */
619 if (!obddev->obd_type)
622 tmp = (void *)arg + sizeof(unsigned int);
623 get_user(conn_id, (int *) arg);
624 if ( !obddev->obd_type ||
625 !obddev->obd_type->typ_ops->o_statfs)
628 rc = obddev->obd_type->typ_ops->o_statfs(conn_id, &buf);
631 rc = copy_to_user(tmp, &buf, sizeof(buf));
636 printk("invalid ioctl: cmd = %x, arg = %lx\n", cmd, arg);
641 /* Driver interface done, utility functions follow */
643 int obd_register_type(struct obd_ops *ops, char *nm)
645 struct obd_type *type;
647 if ( obd_nm_to_type(nm) ) {
648 CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
652 OBD_ALLOC(type, struct obd_type * , sizeof(*type));
655 memset(type, 0, sizeof(*type));
656 INIT_LIST_HEAD(&type->typ_chain);
658 list_add(&type->typ_chain, obd_types.next);
664 int obd_unregister_type(char *nm)
666 struct obd_type *type = obd_nm_to_type(nm);
671 if ( type->typ_refcnt )
674 list_del(&type->typ_chain);
675 OBD_FREE(type, sizeof(*type));
679 /* declare character device */
680 static struct file_operations obd_psdev_fops = {
684 NULL, /* presto_psdev_readdir */
686 obd_class_ioctl, /* ioctl */
687 NULL, /* presto_psdev_mmap */
688 obd_class_open, /* open */
690 obd_class_release, /* release */
693 NULL, /* check_media_change */
694 NULL, /* revalidate */
705 printk(KERN_INFO "OBD class driver v0.002, braam@stelias.com\n");
707 INIT_LIST_HEAD(&obd_types);
709 if (register_chrdev(OBD_PSDEV_MAJOR,"obd_psdev",
711 printk(KERN_ERR "obd_psdev: unable to get major %d\n",
716 for (i = 0; i < MAX_OBD_DEVICES; i++) {
717 memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
718 INIT_LIST_HEAD(&obd_dev[i].u.sim.sim_clients);
726 EXPORT_SYMBOL(obd_register_type);
727 EXPORT_SYMBOL(obd_unregister_type);
729 EXPORT_SYMBOL(obd_print_entry);
730 EXPORT_SYMBOL(obd_debug_level);
731 EXPORT_SYMBOL(obd_dev);
734 int init_module(void)
739 void cleanup_module(void)
744 unregister_chrdev(OBD_PSDEV_MAJOR, "obd_psdev");
745 for (i = 0; i < MAX_OBD_DEVICES; i++) {
746 struct obd_device *obddev = &obd_dev[i];
747 if ( obddev->obd_type &&
748 obddev->obd_type->typ_ops->o_cleanup_device )
749 return obddev->obd_type->typ_ops->o_cleanup_device(i);