X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fobdclass%2Fclass_obd.c;h=545f66b14afeaea2e6216b9d59cbe6a8499f6ac6;hb=58c14f99437bf9858f817e0a17b5007831987aa8;hp=51904f84cb932759e06f85882194791acd615d4e;hpb=785d1cb36d8fab4c4750b0c65c92d92830acda8a;p=fs%2Flustre-release.git diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index 51904f8..545f66b 100644 --- a/lustre/obdclass/class_obd.c +++ b/lustre/obdclass/class_obd.c @@ -1,13 +1,12 @@ /* - * An implementation of a loadable kernel mode driver providing - * multiple kernel/user space bidirectional communications links. + * An implementation of a loadable kernel mode driver providing + * multiple kernel/user space bidirectional communications links. * - * Author: Alan Cox + * Author: Alan Cox * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. * * Adapted to become the Linux 2.0 Coda pseudo device * Peter Braam @@ -23,12 +22,12 @@ * Copyright (c) 1999 Stelias Computing, Inc. * (authors {pschwan,braam}@stelias.com) * Copyright (C) 1999 Seagate Technology, Inc. + * Copyright (C) 2001 Cluster File Systems, Inc. * * */ #define EXPORT_SYMTAB - #include /* for CONFIG_PROC_FS */ #include #include @@ -37,7 +36,7 @@ #include /* for request_module() */ #include #include -#include +#include #include #include #include @@ -49,891 +48,807 @@ #include #include #include -#include #include #include #include +#include #include #include static int obd_init_magic; -int obd_print_entry = 0; -int obd_debug_level = D_IOCTL|D_INODE|D_SUPER|D_WARNING|D_MALLOC|D_CACHE; +int obd_print_entry = 1; +int obd_debug_level = ~0; long obd_memory = 0; struct obd_device obd_dev[MAX_OBD_DEVICES]; struct list_head obd_types; -/* called when opening /dev/obdNNN */ +/* opening /dev/obd */ static int obd_class_open(struct inode * inode, struct file * file) { - int dev; ENTRY; - if (!inode) - return -EINVAL; - dev = MINOR(inode->i_rdev); - if (dev >= MAX_OBD_DEVICES) - return -ENODEV; - obd_dev[dev].obd_refcnt++; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - obd_dev[dev].obd_refcnt); - + file->private_data = NULL; MOD_INC_USE_COUNT; EXIT; return 0; } -/* called when closing /dev/obdNNN */ +/* closing /dev/obd */ static int obd_class_release(struct inode * inode, struct file * file) { - int dev; ENTRY; - if (!inode) - return -EINVAL; - dev = MINOR(inode->i_rdev); - if (dev >= MAX_OBD_DEVICES) - return -ENODEV; - fsync_dev(inode->i_rdev); - if (obd_dev[dev].obd_refcnt <= 0) - printk(KERN_ALERT __FUNCTION__ ": refcount(%d) <= 0\n", - obd_dev[dev].obd_refcnt); - obd_dev[dev].obd_refcnt--; - - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - obd_dev[dev].obd_refcnt); - MOD_DEC_USE_COUNT; + if (file->private_data) + file->private_data = NULL; + MOD_DEC_USE_COUNT; EXIT; return 0; } -/* support function */ -static struct obd_type *obd_nm_to_type(char *nm) +/* + * support functions: we could use inter-module communication, but this + * is more portable to other OS's + */ +static struct obd_type *obd_search_type(char *nm) { - struct list_head *tmp; - struct obd_type *type; - CDEBUG(D_INFO, "SEARCH %s\n", nm); - - tmp = &obd_types; - while ( (tmp = tmp->next) != &obd_types ) { - type = list_entry(tmp, struct obd_type, typ_chain); - CDEBUG(D_INFO, "TYP %s\n", type->typ_name); - if (strlen(type->typ_name) == strlen(nm) && - strcmp(type->typ_name, nm) == 0 ) { - return type; - } - } + struct list_head *tmp; + struct obd_type *type; + CDEBUG(D_INFO, "SEARCH %s\n", nm); + + tmp = &obd_types; + while ( (tmp = tmp->next) != &obd_types ) { + type = list_entry(tmp, struct obd_type, typ_chain); + CDEBUG(D_INFO, "TYP %s\n", type->typ_name); + if (strlen(type->typ_name) == strlen(nm) && + strcmp(type->typ_name, nm) == 0 ) { + return type; + } + } return NULL; } - -static int getdata(int len, void **data) +static struct obd_type *obd_nm_to_type(char *nm) { - void *tmp = NULL; + struct obd_type *type = obd_search_type(nm); - if (!len) { - *data = NULL; - return 0; - } - - CDEBUG(D_MALLOC, "len %d, add %p\n", len, *data); - - OBD_ALLOC(tmp, void *, len); - if ( !tmp ) - return -ENOMEM; - - memset(tmp, 0, len); - if ( copy_from_user(tmp, *data, len)) { - OBD_FREE(tmp, len); - return -EFAULT; +#ifdef CONFIG_KMOD + if ( !type ) { + if ( !request_module(nm) ) { + CDEBUG(D_PSDEV, "Loaded module '%s'\n", nm); + type = obd_search_type(nm); + } else { + CDEBUG(D_PSDEV, "Can't load module '%s'\n", nm); + } } - *data = tmp; - - return 0; +#endif + return type; } -/* to control /dev/obdNNN */ +/* to control /dev/obd */ static int obd_class_ioctl (struct inode * inode, struct file * filp, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { - struct obd_device *obddev; - /* NOTE this must be larger than any of the ioctl data structs */ - char buf[1024]; - void *tmp_buf = buf; + /* NOTE this must be larger than any of the ioctl data structs */ + char buf[1024]; + struct obd_ioctl_data *data; + struct obd_device *obd = filp->private_data; struct obd_conn conn; - int err, dev; - long int cli_id; /* connect, disconnect */ + int err = 0; + ENTRY; - if (!inode) { - CDEBUG(D_IOCTL, "invalid inode\n"); - return -EINVAL; - } - - dev = MINOR(inode->i_rdev); - if (dev > MAX_OBD_DEVICES) - return -ENODEV; - obddev = &obd_dev[dev]; - conn.oc_dev = obddev; + memset(buf, 0, sizeof(buf)); - switch (cmd) { - case TCGETS: + if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS) { + printk("OBD ioctl: No device\n"); + return -EINVAL; + } + if (obd_ioctl_getdata(buf, buf + 800, (void *)arg)) { + printk("OBD ioctl: data error\n"); return -EINVAL; - case OBD_IOC_ATTACH: { - struct obd_type *type; - struct oic_generic *input = tmp_buf; - char *nm; - - ENTRY; - /* have we attached a type to this device */ - if ( obddev->obd_type || - (obddev->obd_flags & OBD_ATTACHED) ){ - CDEBUG(D_IOCTL, - "OBD Device %d already attached to type %s.\n", - dev, obddev->obd_type->typ_name); - EXIT; - return -EBUSY; - } - - /* get data structures */ - err = copy_from_user(input, (void *)arg, sizeof(*input)); - if ( err ) { - EXIT; - return err; - } - - err = getdata(input->att_typelen + 1, &input->att_type); - if ( err ) { - EXIT; - return err; - } - - /* find the type */ - nm = input->att_type; - type = obd_nm_to_type(nm); -#ifdef CONFIG_KMOD - if ( !type ) { - if ( !request_module(nm) ) { - CDEBUG(D_PSDEV, "Loaded module '%s'\n", nm); - type = obd_nm_to_type(nm); - } else { - CDEBUG(D_PSDEV, "Can't load module '%s'\n", nm); - } - } -#endif - - OBD_FREE(input->att_type, input->att_typelen + 1); - if ( !type ) { - printk(__FUNCTION__ ": unknown obd type dev %d\n", - dev); - EXIT; - return -EINVAL; - } - obddev->obd_type = type; - - /* get the attach data */ - err = getdata(input->att_datalen, &input->att_data); - if ( err ) { - EXIT; - return err; - } - - INIT_LIST_HEAD(&obddev->obd_gen_clients); - obddev->obd_multi_count = 0; - - CDEBUG(D_IOCTL, "Attach %d, datalen %d, type %s\n", - dev, input->att_datalen, obddev->obd_type->typ_name); - /* maybe we are done */ - if ( !OBT(obddev) || !OBP(obddev, attach) ) { - obddev->obd_flags |= OBD_ATTACHED; - type->typ_refcnt++; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - type->typ_refcnt); - if (input->att_data) - OBD_FREE(input->att_data, input->att_datalen); - MOD_INC_USE_COUNT; - EXIT; - return 0; - } - - /* do the attach */ - err = OBP(obddev, attach)(obddev, input->att_datalen, - input->att_data); - if (input->att_data) - OBD_FREE(input->att_data, input->att_datalen); - - if ( err ) { - obddev->obd_flags &= ~OBD_ATTACHED; - obddev->obd_type = NULL; - EXIT; - } else { - obddev->obd_flags |= OBD_ATTACHED; - type->typ_refcnt++; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - type->typ_refcnt); - MOD_INC_USE_COUNT; - EXIT; - } - return err; - } - - case OBD_IOC_DETACH: { - - ENTRY; - if (obddev->obd_flags & OBD_SET_UP) { - EXIT; - return -EBUSY; - } - if (! (obddev->obd_flags & OBD_ATTACHED) ) { - CDEBUG(D_IOCTL, "Device not attached\n"); - EXIT; - return -ENODEV; - } - if ( !list_empty(&obddev->obd_gen_clients) ) { - CDEBUG(D_IOCTL, "Device has connected clients\n"); - EXIT; - return -EBUSY; - } - - CDEBUG(D_PSDEV, "Detach %d, type %s\n", dev, - obddev->obd_type->typ_name); - obddev->obd_flags &= ~OBD_ATTACHED; - obddev->obd_type->typ_refcnt--; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - obddev->obd_type->typ_refcnt); - obddev->obd_type = NULL; - MOD_DEC_USE_COUNT; - EXIT; - return 0; - } - - case OBD_IOC_SETUP: { - struct ioc_setup { - int setup_datalen; - void *setup_data; - } *setup; - setup = tmp_buf; - - ENTRY; - /* have we attached a type to this device */ - if (!(obddev->obd_flags & OBD_ATTACHED)) { - CDEBUG(D_IOCTL, "Device not attached\n"); - EXIT; - return -ENODEV; - } - - /* has this been done already? */ - if ( obddev->obd_flags & OBD_SET_UP ) { - CDEBUG(D_IOCTL, "Device %d already setup (type %s)\n", - dev, obddev->obd_type->typ_name); - EXIT; - return -EBUSY; - } - - /* get main structure */ - err = copy_from_user(setup, (void *) arg, sizeof(*setup)); - if (err) { - EXIT; - return err; - } - - err = getdata(setup->setup_datalen, &setup->setup_data); - if (err) { - EXIT; - return err; - } - - /* do the setup */ - CDEBUG(D_PSDEV, "Setup %d, type %s\n", dev, - obddev->obd_type->typ_name); - if ( !OBT(obddev) || !OBP(obddev, setup) ) { - obddev->obd_type->typ_refcnt++; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", - dev, obddev->obd_type->typ_refcnt); - if (setup->setup_data) - OBD_FREE(setup->setup_data, - setup->setup_datalen); - obddev->obd_flags |= OBD_SET_UP; - EXIT; - return 0; - } - - err = OBP(obddev, setup)(obddev, setup->setup_datalen, - setup->setup_data); - - if ( err ) { - obddev->obd_flags &= ~OBD_SET_UP; - EXIT; - } else { - obddev->obd_type->typ_refcnt++; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", - dev, obddev->obd_type->typ_refcnt); - obddev->obd_flags |= OBD_SET_UP; - EXIT; - } - if (setup->setup_data) - OBD_FREE(setup->setup_data, setup->setup_datalen); - return err; } - case OBD_IOC_CLEANUP: { - ENTRY; - /* has this minor been registered? */ - if (!obddev->obd_type) { - CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev); - EXIT; - return -ENODEV; - } - - if ( !obddev->obd_type->typ_refcnt ) { - CDEBUG(D_IOCTL, "dev %d has refcount (%d)!\n", - dev, obddev->obd_type->typ_refcnt); - EXIT; - return -EBUSY; - } - - if ( (!(obddev->obd_flags & OBD_SET_UP)) || - (!(obddev->obd_flags & OBD_ATTACHED))) { - CDEBUG(D_IOCTL, "device not attached or set up\n"); - EXIT; - return -ENODEV; - } - - if ( !OBT(obddev) || !OBP(obddev, cleanup) ) - goto cleanup_out; - - /* cleanup has no argument */ - err = OBP(obddev, cleanup)(obddev); - if ( err ) { - EXIT; - return err; + data = (struct obd_ioctl_data *)buf; + + switch (cmd) { + case TCGETS: + return -EINVAL; + case OBD_IOC_DEVICE: { + CDEBUG(D_IOCTL, "\n"); + if (data->ioc_dev >= MAX_OBD_DEVICES || + data->ioc_dev < 0) { + printk("OBD ioctl: DEVICE insufficient devices\n"); + return -EINVAL; } + CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev); - cleanup_out: - obddev->obd_flags &= ~OBD_SET_UP; - obddev->obd_type->typ_refcnt--; - CDEBUG(D_PSDEV, "Dev %d refcount now %d\n", dev, - obddev->obd_type->typ_refcnt); + filp->private_data = &obd_dev[data->ioc_dev]; EXIT; return 0; } - case OBD_IOC_CONNECT: - { - if ( (!(obddev->obd_flags & OBD_SET_UP)) || - (!(obddev->obd_flags & OBD_ATTACHED))) { - CDEBUG(D_IOCTL, "Device not attached or set up\n"); - return -ENODEV; - } - if ( !OBT(obddev) || !OBP(obddev, connect) ) - return -EOPNOTSUPP; - - err = OBP(obddev, connect)(&conn); - if ( err ) - return err; - - return copy_to_user((int *)arg, &conn.oc_id, - sizeof(uint32_t)); - } - case OBD_IOC_DISCONNECT: - /* frees data structures */ - /* has this minor been registered? */ - if (!obddev->obd_type) - return -ENODEV; - - get_user(cli_id, (int *) arg); - conn.oc_id = cli_id; - - if ( !OBT(obddev) || !OBP(obddev, disconnect)) - return -EOPNOTSUPP; - - OBP(obddev, disconnect)(&conn); + case OBD_IOC_ATTACH: { + struct obd_type *type; + + ENTRY; + /* have we attached a type to this device */ + if ( obd->obd_type || (obd->obd_flags & OBD_ATTACHED) ){ + printk("OBD: Device %d already typed as %s.\n", + obd->obd_minor, MKSTR(obd->obd_type->typ_name)); + return -EBUSY; + } + + printk("-----> attach %s %s\n", MKSTR(data->ioc_inlbuf1), + MKSTR(data->ioc_inlbuf2)); + + /* find the type */ + type = obd_nm_to_type(data->ioc_inlbuf1); + if ( !type ) { + printk("OBD: unknown type dev %d\n", obd->obd_minor); + return -EINVAL; + } + + obd->obd_type = type; + obd->obd_multi_count = 0; + INIT_LIST_HEAD(&obd->obd_gen_clients); + + /* do the attach */ + if ( OBT(obd) && OBP(obd, attach) ) { + err = OBP(obd, attach)(obd, data); + } + + if ( err ) { + obd->obd_flags &= ~OBD_ATTACHED; + obd->obd_type = NULL; + EXIT; + } else { + obd->obd_flags |= OBD_ATTACHED; + type->typ_refcnt++; + printk("OBD: dev %d attached type %s\n", + obd->obd_minor, data->ioc_inlbuf1); + obd->obd_proc_entry = + proc_lustre_register_obd_device(obd); + MOD_INC_USE_COUNT; + EXIT; + } + + return err; + } + + case OBD_IOC_DETACH: { + ENTRY; + if (obd->obd_flags & OBD_SET_UP) { + printk("OBD device %d still set up\n", obd->obd_minor); + return -EBUSY; + } + if (! (obd->obd_flags & OBD_ATTACHED) ) { + printk("OBD device %d not attached\n", obd->obd_minor); + return -ENODEV; + } + if ( !list_empty(&obd->obd_gen_clients) ) { + printk("OBD device %d has connected clients\n", obd->obd_minor); + return -EBUSY; + } + + if (obd->obd_proc_entry) + proc_lustre_release_obd_device(obd); + + obd->obd_flags &= ~OBD_ATTACHED; + obd->obd_type->typ_refcnt--; + obd->obd_type = NULL; + MOD_DEC_USE_COUNT; + EXIT; + return 0; + } + + case OBD_IOC_SETUP: { + ENTRY; + /* have we attached a type to this device? */ + if (!(obd->obd_flags & OBD_ATTACHED)) { + printk("Device %d not attached\n", obd->obd_minor); + return -ENODEV; + } + + /* has this been done already? */ + if ( obd->obd_flags & OBD_SET_UP ) { + printk("Device %d already setup (type %s)\n", + obd->obd_minor, obd->obd_type->typ_name); + return -EBUSY; + } + + if ( OBT(obd) && OBP(obd, setup) ) + err = OBP(obd, setup)(obd, data); + + if (!err) { + obd->obd_type->typ_refcnt++; + obd->obd_flags |= OBD_SET_UP; + EXIT; + } + + return err; + } + case OBD_IOC_CLEANUP: { + ENTRY; + /* has this minor been registered? */ + if (!obd->obd_type) { + printk("OBD cleanup dev %d has no type.\n", + obd->obd_minor); + EXIT; + return -ENODEV; + } + + if ( (!(obd->obd_flags & OBD_SET_UP)) || + (!(obd->obd_flags & OBD_ATTACHED))) { + printk("OBD cleanup device %d not attached/set up\n", + obd->obd_minor); + EXIT; + return -ENODEV; + } + + if ( !OBT(obd) || !OBP(obd, cleanup) ) + goto cleanup_out; + + /* cleanup has no argument */ + err = OBP(obd, cleanup)(obd); + if ( err ) { + EXIT; + return err; + } + + cleanup_out: + obd->obd_flags &= ~OBD_SET_UP; + obd->obd_type->typ_refcnt--; + EXIT; + return 0; + } + + case OBD_IOC_CONNECT: + { + if ( (!(obd->obd_flags & OBD_SET_UP)) || + (!(obd->obd_flags & OBD_ATTACHED))) { + CDEBUG(D_IOCTL, "Device not attached or set up\n"); + return -ENODEV; + } + + if ( !OBT(obd) || !OBP(obd, connect) ) + return -EOPNOTSUPP; + + conn.oc_id = data->ioc_conn1; + conn.oc_dev = obd; + + err = OBP(obd, connect)(&conn); + CDEBUG(D_IOCTL, "assigned connection %d\n", conn.oc_id); + data->ioc_conn1 = conn.oc_id; + if ( err ) + return err; + + return copy_to_user((int *)arg, data, sizeof(*data)); + } + case OBD_IOC_DISCONNECT: { + + if (!obd->obd_type) + return -ENODEV; + + if ( !OBT(obd) || !OBP(obd, disconnect)) + return -EOPNOTSUPP; + + conn.oc_id = data->ioc_conn1; + conn.oc_dev = obd; + OBP(obd, disconnect)(&conn); + return 0; + } + + case OBD_IOC_DEC_USE_COUNT: { + MOD_DEC_USE_COUNT; return 0; - - case OBD_IOC_SYNC: { - struct oic_range_s *range = tmp_buf; - - if (!obddev->obd_type) - return -ENODEV; - - err = copy_from_user(range, (const void *)arg, sizeof(*range)); - - if ( err ) { - EXIT; - return err; - } - - if ( !OBT(obddev) || !OBP(obddev, sync) ) { - err = -EOPNOTSUPP; - EXIT; - return err; - } - - /* XXX sync needs to be tested/verified */ - err = OBP(obddev, sync)(&conn, &range->obdo, range->count, - range->offset); - - if ( err ) { - EXIT; - return err; - } - - return put_user(err, (int *) arg); - } - case OBD_IOC_CREATE: { - struct oic_attr_s *attr = tmp_buf; - - err = copy_from_user(attr, (const void *)arg, sizeof(*attr)); - if (err) { - EXIT; - return err; - } - - /* has this minor been registered? */ - if ( !(obddev->obd_flags & OBD_ATTACHED) || - !(obddev->obd_flags & OBD_SET_UP)) { - CDEBUG(D_IOCTL, "Device not attached or set up\n"); - return -ENODEV; - } - conn.oc_id = attr->conn_id; - - if ( !OBT(obddev) || !OBP(obddev, create) ) - return -EOPNOTSUPP; - - err = OBP(obddev, create)(&conn, &attr->obdo); - if (err) { - EXIT; - return err; - } - - err = copy_to_user((int *)arg, attr, sizeof(*attr)); - EXIT; - return err; - } - - case OBD_IOC_DESTROY: { - struct oic_attr_s *attr = tmp_buf; - - /* has this minor been registered? */ - if (!obddev->obd_type) - return -ENODEV; - - err = copy_from_user(attr, (int *)arg, sizeof(*attr)); - if ( err ) { - EXIT; - return err; - } - - if ( !OBT(obddev) || !OBP(obddev, destroy) ) - return -EOPNOTSUPP; - - conn.oc_id = attr->conn_id; - err = OBP(obddev, destroy)(&conn, &attr->obdo); - EXIT; - return err; - } - - case OBD_IOC_SETATTR: { - struct oic_attr_s *attr = tmp_buf; - - /* has this minor been registered? */ - if (!obddev->obd_type) - return -ENODEV; - - err = copy_from_user(attr, (int *)arg, sizeof(*attr)); - if (err) - return err; - - if ( !OBT(obddev) || !OBP(obddev, setattr) ) - return -EOPNOTSUPP; - - conn.oc_id = attr->conn_id; - err = OBP(obddev, setattr)(&conn, &attr->obdo); - EXIT; - return err; - } - - case OBD_IOC_GETATTR: { - struct oic_attr_s *attr = tmp_buf; - - err = copy_from_user(attr, (int *)arg, sizeof(*attr)); - if (err) - return err; - - conn.oc_id = attr->conn_id; - ODEBUG(&attr->obdo); - err = OBP(obddev, getattr)(&conn, &attr->obdo); - if ( err ) { - EXIT; - return err; - } - - err = copy_to_user((int *)arg, attr, sizeof(*attr)); - EXIT; - return err; - } - - case OBD_IOC_READ: { - int err; - struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */ - - err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s)); - if ( err ) { - EXIT; - return err; - } - - conn.oc_id = rw_s->conn_id; - - if ( !OBT(obddev) || !OBP(obddev, read) ) { - err = -EOPNOTSUPP; - EXIT; - return err; - } - - - err = OBP(obddev, read)(&conn, &rw_s->obdo, rw_s->buf, - &rw_s->count, rw_s->offset); - - ODEBUG(&rw_s->obdo); - CDEBUG(D_INFO, "READ: conn %d, count %Ld, offset %Ld, '%s'\n", - rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf); - if ( err ) { - EXIT; - return err; - } - - err = copy_to_user((int*)arg, &rw_s->count, sizeof(rw_s->count)); - EXIT; - return err; - } - - case OBD_IOC_WRITE: { - struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */ - - err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s)); - if ( err ) { - EXIT; - return err; - } - - conn.oc_id = rw_s->conn_id; - - if ( !OBT(obddev) || !OBP(obddev, write) ) { - err = -EOPNOTSUPP; - return err; - } - - CDEBUG(D_INFO, "WRITE: conn %d, count %Ld, offset %Ld, '%s'\n", - rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf); - err = OBP(obddev, write)(&conn, &rw_s->obdo, rw_s->buf, - &rw_s->count, rw_s->offset); - ODEBUG(&rw_s->obdo); - if ( err ) { - EXIT; - return err; - } - - err = copy_to_user((int *)arg, &rw_s->count, - sizeof(rw_s->count)); - EXIT; - return err; - } - case OBD_IOC_PREALLOCATE: { - struct oic_prealloc_s *prealloc = tmp_buf; - - /* has this minor been registered? */ - if (!obddev->obd_type) - return -ENODEV; - - err = copy_from_user(prealloc, (int *)arg, sizeof(*prealloc)); - if (err) - return -EFAULT; - - if ( !(obddev->obd_flags & OBD_ATTACHED) || - !(obddev->obd_flags & OBD_SET_UP)) { - CDEBUG(D_IOCTL, "Device not attached or set up\n"); - return -ENODEV; - } - - if ( !OBT(obddev) || !OBP(obddev, preallocate) ) - return -EOPNOTSUPP; - - conn.oc_id = prealloc->conn_id; - err = OBP(obddev, preallocate)(&conn, &prealloc->alloc, - prealloc->ids); - if ( err ) { - EXIT; - return err; - } - - err =copy_to_user((int *)arg, prealloc, sizeof(*prealloc)); - EXIT; - return err; - } - case OBD_IOC_STATFS: { - struct statfs *tmp; - unsigned int conn_id; - struct statfs buf; - - /* has this minor been registered? */ - if (!obddev->obd_type) - return -ENODEV; - - tmp = (void *)arg + sizeof(unsigned int); - get_user(conn_id, (int *) arg); - - if ( !OBT(obddev) || !OBP(obddev, statfs) ) - return -EOPNOTSUPP; - - conn.oc_id = conn_id; - err = OBP(obddev, statfs)(&conn, &buf); - if ( err ) { - EXIT; - return err; - } - err = copy_to_user(tmp, &buf, sizeof(buf)); - EXIT; - return err; - - } - case OBD_IOC_COPY: { - struct ioc_mv_s *mvdata = tmp_buf; - - if ( (!(obddev->obd_flags & OBD_SET_UP)) || - (!(obddev->obd_flags & OBD_ATTACHED))) { - CDEBUG(D_IOCTL, "Device not attached or set up\n"); - return -ENODEV; - } - - /* get main structure */ - err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata)); - if (err) { - EXIT; - return err; - } - - if ( !OBT(obddev) || !OBP(obddev, copy) ) - return -EOPNOTSUPP; - - /* do the partition */ - CDEBUG(D_INFO, "Copy %d, type %s dst %Ld src %Ld\n", dev, - obddev->obd_type->typ_name, mvdata->dst.o_id, - mvdata->src.o_id); - - conn.oc_id = mvdata->src_conn_id; - - err = OBP(obddev, copy)(&conn, &mvdata->dst, - &conn, &mvdata->src, - mvdata->src.o_size, 0); - return err; } - case OBD_IOC_MIGR: { - struct ioc_mv_s *mvdata = tmp_buf; - - if ( (!(obddev->obd_flags & OBD_SET_UP)) || - (!(obddev->obd_flags & OBD_ATTACHED))) { - CDEBUG(D_IOCTL, "Device not attached or set up\n"); - return -ENODEV; - } - - err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata)); - if (err) { - EXIT; - return err; - } - - CDEBUG(D_INFO, "Migrate copying %d bytes\n", sizeof(*mvdata)); - - if ( !OBT(obddev) || !OBP(obddev, migrate) ) - return -EOPNOTSUPP; - - /* do the partition */ - CDEBUG(D_INFO, "Migrate %d, type %s conn %d src %Ld dst %Ld\n", - dev, obddev->obd_type->typ_name, mvdata->src_conn_id, - mvdata->src.o_id, mvdata->dst.o_id); - - conn.oc_id = mvdata->src_conn_id; - err = OBP(obddev, migrate)(&conn, &mvdata->dst, &mvdata->src, - mvdata->src.o_size, 0); - - return err; - } - - default: { - struct obd_type *type; - struct oic_generic input; - char *nm; - void *karg; - - /* get data structures */ - err = copy_from_user(&input, (void *)arg, sizeof(input)); - if ( err ) { - EXIT; - return err; - } - - err = getdata(input.att_typelen + 1, &input.att_type); - if ( err ) { - EXIT; - return err; - } - - /* find the type */ - nm = input.att_type; - type = obd_nm_to_type(nm); + case OBD_IOC_CREATE: { + /* has this minor been registered? */ + if ( !(obd->obd_flags & OBD_ATTACHED) || + !(obd->obd_flags & OBD_SET_UP)) { + CDEBUG(D_IOCTL, "Device not attached or set up\n"); + return -ENODEV; + } + conn.oc_id = data->ioc_conn1; + conn.oc_dev = obd; + + if ( !OBT(obd) || !OBP(obd, create) ) + return -EOPNOTSUPP; + + err = OBP(obd, create)(&conn, &data->ioc_obdo1); + if (err) { + EXIT; + return err; + } + + err = copy_to_user((int *)arg, data, sizeof(*data)); + EXIT; + return err; + } +#if 0 + case OBD_IOC_SYNC: { + struct oic_range_s *range = tmp_buf; + + if (!obd->obd_type) + return -ENODEV; + + err = copy_from_user(range, (const void *)arg, sizeof(*range)); + + if ( err ) { + EXIT; + return err; + } + + if ( !OBT(obd) || !OBP(obd, sync) ) { + err = -EOPNOTSUPP; + EXIT; + return err; + } + + /* XXX sync needs to be tested/verified */ + err = OBP(obd, sync)(&conn, &range->obdo, range->count, + range->offset); + + if ( err ) { + EXIT; + return err; + } + + return put_user(err, (int *) arg); + } + + case OBD_IOC_DESTROY: { + struct oic_attr_s *attr = tmp_buf; + + /* has this minor been registered? */ + if (!obd->obd_type) + return -ENODEV; + + err = copy_from_user(attr, (int *)arg, sizeof(*attr)); + if ( err ) { + EXIT; + return err; + } + + if ( !OBT(obd) || !OBP(obd, destroy) ) + return -EOPNOTSUPP; + + conn.oc_id = attr->conn_id; + err = OBP(obd, destroy)(&conn, &attr->obdo); + EXIT; + return err; + } + + case OBD_IOC_SETATTR: { + struct oic_attr_s *attr = tmp_buf; + + /* has this minor been registered? */ + if (!obd->obd_type) + return -ENODEV; + + err = copy_from_user(attr, (int *)arg, sizeof(*attr)); + if (err) + return err; + + if ( !OBT(obd) || !OBP(obd, setattr) ) + return -EOPNOTSUPP; + + conn.oc_id = attr->conn_id; + err = OBP(obd, setattr)(&conn, &attr->obdo); + EXIT; + return err; + } + + case OBD_IOC_GETATTR: { + struct oic_attr_s *attr = tmp_buf; + + err = copy_from_user(attr, (int *)arg, sizeof(*attr)); + if (err) + return err; + + conn.oc_id = attr->conn_id; + ODEBUG(&attr->obdo); + err = OBP(obd, getattr)(&conn, &attr->obdo); + if ( err ) { + EXIT; + return err; + } + + err = copy_to_user((int *)arg, attr, sizeof(*attr)); + EXIT; + return err; + } + + case OBD_IOC_READ: { + int err; + struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */ + + err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s)); + if ( err ) { + EXIT; + return err; + } + + conn.oc_id = rw_s->conn_id; + + if ( !OBT(obd) || !OBP(obd, read) ) { + err = -EOPNOTSUPP; + EXIT; + return err; + } + + + err = OBP(obd, read)(&conn, &rw_s->obdo, rw_s->buf, + &rw_s->count, rw_s->offset); + + ODEBUG(&rw_s->obdo); + CDEBUG(D_INFO, "READ: conn %d, count %Ld, offset %Ld, '%s'\n", + rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf); + if ( err ) { + EXIT; + return err; + } + + err = copy_to_user((int*)arg, &rw_s->count, sizeof(rw_s->count)); + EXIT; + return err; + } + + case OBD_IOC_WRITE: { + struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */ + + err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s)); + if ( err ) { + EXIT; + return err; + } + + conn.oc_id = rw_s->conn_id; + + if ( !OBT(obd) || !OBP(obd, write) ) { + err = -EOPNOTSUPP; + return err; + } + + CDEBUG(D_INFO, "WRITE: conn %d, count %Ld, offset %Ld, '%s'\n", + rw_s->conn_id, rw_s->count, rw_s->offset, rw_s->buf); + + err = OBP(obd, write)(&conn, &rw_s->obdo, rw_s->buf, + &rw_s->count, rw_s->offset); + ODEBUG(&rw_s->obdo); + if ( err ) { + EXIT; + return err; + } + + err = copy_to_user((int *)arg, &rw_s->count, + sizeof(rw_s->count)); + EXIT; + return err; + } + case OBD_IOC_PREALLOCATE: { + struct oic_prealloc_s *prealloc = tmp_buf; + + /* has this minor been registered? */ + if (!obd->obd_type) + return -ENODEV; + + err = copy_from_user(prealloc, (int *)arg, sizeof(*prealloc)); + if (err) + return -EFAULT; + + if ( !(obd->obd_flags & OBD_ATTACHED) || + !(obd->obd_flags & OBD_SET_UP)) { + CDEBUG(D_IOCTL, "Device not attached or set up\n"); + return -ENODEV; + } + + if ( !OBT(obd) || !OBP(obd, preallocate) ) + return -EOPNOTSUPP; + + conn.oc_id = prealloc->conn_id; + err = OBP(obd, preallocate)(&conn, &prealloc->alloc, + prealloc->ids); + if ( err ) { + EXIT; + return err; + } + + err =copy_to_user((int *)arg, prealloc, sizeof(*prealloc)); + EXIT; + return err; + } + case OBD_IOC_STATFS: { + struct statfs *tmp; + unsigned int conn_id; + struct statfs buf; + + /* has this minor been registered? */ + if (!obd->obd_type) + return -ENODEV; + + tmp = (void *)arg + sizeof(unsigned int); + get_user(conn_id, (int *) arg); + + if ( !OBT(obd) || !OBP(obd, statfs) ) + return -EOPNOTSUPP; + + conn.oc_id = conn_id; + err = OBP(obd, statfs)(&conn, &buf); + if ( err ) { + EXIT; + return err; + } + err = copy_to_user(tmp, &buf, sizeof(buf)); + EXIT; + return err; + + } + case OBD_IOC_COPY: { + struct ioc_mv_s *mvdata = tmp_buf; + + if ( (!(obd->obd_flags & OBD_SET_UP)) || + (!(obd->obd_flags & OBD_ATTACHED))) { + CDEBUG(D_IOCTL, "Device not attached or set up\n"); + return -ENODEV; + } + + /* get main structure */ + err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata)); + if (err) { + EXIT; + return err; + } + + if ( !OBT(obd) || !OBP(obd, copy) ) + return -EOPNOTSUPP; + + /* do the partition */ + CDEBUG(D_INFO, "Copy %d, type %s dst %Ld src %Ld\n", dev, + obd->obd_type->typ_name, mvdata->dst.o_id, + mvdata->src.o_id); + + conn.oc_id = mvdata->src_conn_id; + + err = OBP(obd, copy)(&conn, &mvdata->dst, + &conn, &mvdata->src, + mvdata->src.o_size, 0); + return err; + } + + case OBD_IOC_MIGR: { + struct ioc_mv_s *mvdata = tmp_buf; + + if ( (!(obd->obd_flags & OBD_SET_UP)) || + (!(obd->obd_flags & OBD_ATTACHED))) { + CDEBUG(D_IOCTL, "Device not attached or set up\n"); + return -ENODEV; + } + + err = copy_from_user(mvdata, (void *) arg, sizeof(*mvdata)); + if (err) { + EXIT; + return err; + } + + CDEBUG(D_INFO, "Migrate copying %d bytes\n", sizeof(*mvdata)); + + if ( !OBT(obd) || !OBP(obd, migrate) ) + return -EOPNOTSUPP; + + /* do the partition */ + CDEBUG(D_INFO, "Migrate %d, type %s conn %d src %Ld dst %Ld\n", + dev, obd->obd_type->typ_name, mvdata->src_conn_id, + mvdata->src.o_id, mvdata->dst.o_id); + + conn.oc_id = mvdata->src_conn_id; + err = OBP(obd, migrate)(&conn, &mvdata->dst, &mvdata->src, + mvdata->src.o_size, 0); + + return err; + } + case OBD_IOC_PUNCH: { + struct oic_rw_s *rw_s = tmp_buf; /* read, write ioctl str */ + + err = copy_from_user(rw_s, (int *)arg, sizeof(*rw_s)); + if ( err ) { + EXIT; + return err; + } + + conn.oc_id = rw_s->conn_id; + + if ( !OBT(obd) || !OBP(obd, punch) ) { + err = -EOPNOTSUPP; + return err; + } + + CDEBUG(D_INFO, "PUNCH: conn %d, count %Ld, offset %Ld\n", + rw_s->conn_id, rw_s->count, rw_s->offset); + err = OBP(obd, punch)(&conn, &rw_s->obdo, rw_s->count, + rw_s->offset); + ODEBUG(&rw_s->obdo); + if ( err ) { + EXIT; + return err; + } + EXIT; + return err; + } + + default: { + struct obd_type *type; + struct oic_generic input; + char *nm; + void *karg; + + /* get data structures */ + err = copy_from_user(&input, (void *)arg, sizeof(input)); + if ( err ) { + EXIT; + return err; + } + + err = getdata(input.att_typelen + 1, &input.att_type); + if ( err ) { + EXIT; + return err; + } + + /* find the type */ + nm = input.att_type; + type = obd_nm_to_type(nm); #ifdef CONFIG_KMOD - if ( !type ) { - if ( !request_module(nm) ) { - CDEBUG(D_PSDEV, "Loaded module '%s'\n", nm); - type = obd_nm_to_type(nm); - } else { - CDEBUG(D_PSDEV, "Can't load module '%s'\n", nm); - } - } + if ( !type ) { + if ( !request_module(nm) ) { + CDEBUG(D_PSDEV, "Loaded module '%s'\n", nm); + type = obd_nm_to_type(nm); + } else { + CDEBUG(D_PSDEV, "Can't load module '%s'\n", nm); + } + } #endif - OBD_FREE(input.att_type, input.att_typelen + 1); - if ( !type ) { - printk(__FUNCTION__ ": unknown obd type dev %d\n", dev); - EXIT; - return -EINVAL; - } - - if ( !type->typ_ops || !type->typ_ops->o_iocontrol ) { - EXIT; - return -EOPNOTSUPP; - } - conn.oc_id = input.att_connid; - - CDEBUG(D_INFO, "Calling ioctl %x for type %s, len %d\n", - cmd, type->typ_name, input.att_datalen); - - /* get the generic data */ - karg = input.att_data; - err = getdata(input.att_datalen, &karg); - if ( err ) { - EXIT; - return err; - } - - err = type->typ_ops->o_iocontrol(cmd, &conn, input.att_datalen, - karg, input.att_data); - OBD_FREE(karg, input.att_datalen); + OBD_FREE(input.att_type, input.att_typelen + 1); + if ( !type ) { + printk(__FUNCTION__ ": unknown obd type dev %d\n", dev); + EXIT; + return -EINVAL; + } + + if ( !type->typ_ops || !type->typ_ops->o_iocontrol ) { + EXIT; + return -EOPNOTSUPP; + } + conn.oc_id = input.att_connid; + + CDEBUG(D_INFO, "Calling ioctl %x for type %s, len %d\n", + cmd, type->typ_name, input.att_datalen); + + /* get the generic data */ + karg = input.att_data; + err = getdata(input.att_datalen, &karg); + if ( err ) { + EXIT; + return err; + } + + err = type->typ_ops->o_iocontrol(cmd, &conn, input.att_datalen, + karg, input.att_data); + OBD_FREE(karg, input.att_datalen); + + EXIT; + return err; + } +#endif + default: + return -EINVAL; - EXIT; - return err; - } - } + } } /* obd_class_ioctl */ /* Driver interface done, utility functions follow */ int obd_register_type(struct obd_ops *ops, char *nm) { - struct obd_type *type; - - - if (obd_init_magic != 0x11223344) { - printk(__FUNCTION__ ": bad magic for type\n"); - EXIT; - return -EINVAL; - } - - if ( obd_nm_to_type(nm) ) { - CDEBUG(D_IOCTL, "Type %s already registered\n", nm); - EXIT; - return -EEXIST; - } - - OBD_ALLOC(type, struct obd_type * , sizeof(*type)); - if ( !type ) { - EXIT; - return -ENOMEM; - } - memset(type, 0, sizeof(*type)); - INIT_LIST_HEAD(&type->typ_chain); - MOD_INC_USE_COUNT; - list_add(&type->typ_chain, obd_types.next); - type->typ_ops = ops; - type->typ_name = nm; - EXIT; - return 0; + struct obd_type *type; + + + if (obd_init_magic != 0x11223344) { + printk(__FUNCTION__ ": bad magic for type\n"); + EXIT; + return -EINVAL; + } + + if ( obd_nm_to_type(nm) ) { + CDEBUG(D_IOCTL, "Type %s already registered\n", nm); + EXIT; + return -EEXIST; + } + + OBD_ALLOC(type, struct obd_type * , sizeof(*type)); + if ( !type ) { + EXIT; + return -ENOMEM; + } + memset(type, 0, sizeof(*type)); + INIT_LIST_HEAD(&type->typ_chain); + MOD_INC_USE_COUNT; + list_add(&type->typ_chain, obd_types.next); + type->typ_ops = ops; + type->typ_name = nm; + EXIT; + return 0; } - + int obd_unregister_type(char *nm) { - struct obd_type *type = obd_nm_to_type(nm); - - if ( !type ) { - MOD_DEC_USE_COUNT; - printk(KERN_INFO __FUNCTION__ ": unknown obd type\n"); - EXIT; - return -EINVAL; - } - - if ( type->typ_refcnt ) { - MOD_DEC_USE_COUNT; - printk(KERN_ALERT __FUNCTION__ ":type %s has refcount " - "(%d)\n", nm, type->typ_refcnt); - EXIT; - return -EBUSY; - } - - list_del(&type->typ_chain); - OBD_FREE(type, sizeof(*type)); - MOD_DEC_USE_COUNT; - return 0; + struct obd_type *type = obd_nm_to_type(nm); + + if ( !type ) { + MOD_DEC_USE_COUNT; + printk(KERN_INFO __FUNCTION__ ": unknown obd type\n"); + EXIT; + return -EINVAL; + } + + if ( type->typ_refcnt ) { + MOD_DEC_USE_COUNT; + printk(KERN_ALERT __FUNCTION__ ":type %s has refcount " + "(%d)\n", nm, type->typ_refcnt); + EXIT; + return -EBUSY; + } + + list_del(&type->typ_chain); + OBD_FREE(type, sizeof(*type)); + MOD_DEC_USE_COUNT; + return 0; } /* obd_unregister_type */ /* declare character device */ static struct file_operations obd_psdev_fops = { - NULL, /* llseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* presto_psdev_readdir */ - NULL, /* poll */ - obd_class_ioctl, /* ioctl */ - NULL, /* presto_psdev_mmap */ - obd_class_open, /* open */ - NULL, - obd_class_release, /* release */ - NULL, /* fsync */ - NULL, /* fasync */ - NULL /* lock */ + ioctl: obd_class_ioctl, /* ioctl */ + open: obd_class_open, /* open */ + release: obd_class_release, /* release */ }; /* modules setup */ +#define OBD_MINOR 241 +static struct miscdevice obd_psdev = { + OBD_MINOR, + "obd_psdev", + &obd_psdev_fops +}; int init_obd(void) { - int err; - int i; - - printk(KERN_INFO "OBD class driver v0.01, braam@stelias.com\n"); - - INIT_LIST_HEAD(&obd_types); - - if (register_chrdev(OBD_PSDEV_MAJOR,"obd_psdev", - &obd_psdev_fops)) { - printk(KERN_ERR __FUNCTION__ ": unable to get major %d\n", - OBD_PSDEV_MAJOR); - return -EIO; - } - - for (i = 0; i < MAX_OBD_DEVICES; i++) { - memset(&(obd_dev[i]), 0, sizeof(obd_dev[i])); - obd_dev[i].obd_minor = i; - INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients); - } - - err = obd_init_obdo_cache(); - if (err) - return err; - obd_sysctl_init(); - obd_init_magic = 0x11223344; - return 0; + int err; + int i; + + printk(KERN_INFO "OBD class driver v0.01, braam@stelias.com\n"); + + INIT_LIST_HEAD(&obd_types); + + if ( (err = misc_register(&obd_psdev)) ) { + printk(KERN_ERR __FUNCTION__ ": cannot register %d err %d\n", + OBD_MINOR, err); + return -EIO; + } + + for (i = 0; i < MAX_OBD_DEVICES; i++) { + memset(&(obd_dev[i]), 0, sizeof(obd_dev[i])); + obd_dev[i].obd_minor = i; + INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients); + } + + err = obd_init_obdo_cache(); + if (err) + return err; + obd_sysctl_init(); + obd_init_magic = 0x11223344; + return 0; } EXPORT_SYMBOL(obd_register_type); @@ -958,29 +873,29 @@ EXPORT_SYMBOL(gen_multi_cleanup); #ifdef MODULE int init_module(void) { - return init_obd(); + return init_obd(); } void cleanup_module(void) { - int i; + int i; ENTRY; - unregister_chrdev(OBD_PSDEV_MAJOR, "obd_psdev"); - for (i = 0; i < MAX_OBD_DEVICES; i++) { - struct obd_device *obddev = &obd_dev[i]; - if ( obddev->obd_type && - (obddev->obd_flags & OBD_SET_UP) && - OBT(obddev) && OBP(obddev, detach) ) { - /* XXX should this call generic detach otherwise? */ - OBP(obddev, detach)(obddev); - } - } - - obd_cleanup_obdo_cache(); - obd_sysctl_clean(); - CDEBUG(D_MALLOC, "CLASS mem used %ld\n", obd_memory); - obd_init_magic = 0; - EXIT; + misc_deregister(&obd_psdev); + for (i = 0; i < MAX_OBD_DEVICES; i++) { + struct obd_device *obd = &obd_dev[i]; + if ( obd->obd_type && + (obd->obd_flags & OBD_SET_UP) && + OBT(obd) && OBP(obd, detach) ) { + /* XXX should this call generic detach otherwise? */ + OBP(obd, detach)(obd); + } + } + + obd_cleanup_obdo_cache(); + obd_sysctl_clean(); + CDEBUG(D_MALLOC, "CLASS mem used %ld\n", obd_memory); + obd_init_magic = 0; + EXIT; } #endif