struct obd_device obd_dev[MAX_OBD_DEVICES];
struct list_head obd_types;
+/* called when opening /dev/obdNNN */
static int obd_class_open(struct inode * inode, struct file * file)
{
int dev;
dev = MINOR(inode->i_rdev);
if (dev >= MAX_OBD_DEVICES)
return -ENODEV;
- obd_dev[dev].refcnt++;
- CDEBUG(D_PSDEV, "Refcount now %d\n", obd_dev[dev].refcnt++);
+ obd_dev[dev].obd_refcnt++;
+ CDEBUG(D_PSDEV, "Refcount now %d\n", obd_dev[dev].obd_refcnt++);
MOD_INC_USE_COUNT;
EXIT;
return 0;
}
+/* called when closing /dev/obdNNN */
static int obd_class_release(struct inode * inode, struct file * file)
{
int dev;
if (dev >= MAX_OBD_DEVICES)
return -ENODEV;
fsync_dev(inode->i_rdev);
- if (obd_dev[dev].refcnt <= 0)
+ if (obd_dev[dev].obd_refcnt <= 0)
printk(KERN_ALERT "presto_psdev_release: refcount(%d) <= 0\n",
- obd_dev[dev].refcnt);
- obd_dev[dev].refcnt--;
+ obd_dev[dev].obd_refcnt);
+ obd_dev[dev].obd_refcnt--;
- CDEBUG(D_PSDEV, "Refcount now %d\n", obd_dev[dev].refcnt++);
+ CDEBUG(D_PSDEV, "Refcount now %d\n", obd_dev[dev].obd_refcnt++);
MOD_DEC_USE_COUNT;
return 0;
}
+/* support function */
static struct obd_type *obd_nm_to_type(char *nm)
{
struct list_head *tmp;
return NULL;
}
+/* to control /dev/obdNNN */
static int obd_class_ioctl (struct inode * inode, struct file * filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
int err, i_ino, dev;
struct obd_device *obddev;
obddev = &obd_dev[dev];
/* has this minor been registered? */
- if (cmd != OBD_IOC_SETUP_SUPER && !obd_dev[dev].obd_type)
+ if (cmd != OBD_IOC_SETUP_OBDDEV && !obd_dev[dev].obd_type)
return -ENODEV;
switch (cmd) {
- case OBD_IOC_SETUP_SUPER: {
+ case OBD_IOC_SETUP_OBDDEV: {
struct obd_type *type;
struct setup {
}
/* get data structures */
- if ( (err= copy_from_user(&input, (void *) arg, sizeof(struct setup))) )
+ err= copy_from_user(&input, (void *) arg, sizeof(input));
+ if (err)
return err;
type = obd_nm_to_type(input.setup_type);
if ( !type ) {
- CDEBUG(D_IOCTL, "Trying to register non existent type %s\n",
+ printk("Trying to register non existent type %s\n",
input.setup_type);
return -1;
}
obddev->obd_type = type;
- CDEBUG(D_IOCTL, "Registering %d, type %s\n",
- dev, input.setup_type);
+ CDEBUG(D_IOCTL, "Setup %d, type %s\n", dev, input.setup_type);
if ( obddev->obd_type->typ_ops->o_setup(obddev,
&input.setup_data)){
obddev->obd_type = NULL;
return -1;
} else {
- type->typ_refcount++;
+ type->typ_refcnt++;
+ MOD_INC_USE_COUNT;
return 0;
}
-
-
}
- case OBD_IOC_CLEANUP_SUPER:
+ case OBD_IOC_CLEANUP_OBDDEV: {
+ int rc;
- /* cleanup has no argument */
- if ( obddev->obd_type->typ_refcount )
- obddev->obd_type->typ_refcount--;
- else
+ if ( !obddev->obd_type->typ_refcnt )
printk("OBD_CLEANUP: refcount wrap!\n");
- if ( obddev->obd_type->typ_ops->o_cleanup )
- return obddev->obd_type->typ_ops->o_cleanup(obddev);
- else
- return 0;
+ if ( !obddev->obd_type->typ_ops->o_cleanup )
+ goto out;
+ /* cleanup has no argument */
+ rc = obddev->obd_type->typ_ops->o_cleanup(obddev);
+ if ( rc )
+ return rc;
+
+ out:
+ obddev->obd_type->typ_refcnt--;
+ obddev->obd_type = NULL;
+ MOD_DEC_USE_COUNT;
+ return 0;
+ }
case OBD_IOC_CONNECT:
{
struct obd_conn_info conninfo;
/* sync doesn't need a connection ID, because it knows
* what device it was called on, and can thus get the
* superblock that it needs. */
- if (!obddev->sb || !obddev->sb->s_dev) {
+ if (!obddev->u.sim.sim_sb || !obddev->u.sim.sim_sb->s_dev) {
CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
err = -EINVAL;
} else {
- if ((err = fsync_dev(obddev->sb->s_dev)))
+ if ((err = fsync_dev(obddev->u.sim.sim_sb->s_dev)))
CDEBUG(D_IOCTL, "sync: fsync_dev failure\n");
else
CDEBUG(D_IOCTL, "sync: success\n");
case OBD_IOC_CREATE:
/* similarly, create doesn't need a connection ID for
* the same reasons. */
- if (!obddev->sb) {
+ if (!obddev->u.sim.sim_sb) {
CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
return put_user(-EINVAL, (int *) arg);
}
return err;
}
+ case OBD_IOC_READ2:
+ {
+ int err;
+
+ err = copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
+ if ( err )
+ return err;
+
+ if ( !obddev->obd_type->typ_ops ||
+ !obddev->obd_type->typ_ops->o_read )
+ return -EINVAL;
+
+ rw_s.count = obddev->obd_type->typ_ops->o_read2(rw_s.conn_id,
+ rw_s.inode,
+ rw_s.buf,
+ rw_s.count,
+ rw_s.offset,
+ &err);
+ if ( err )
+ return err;
+
+ err = copy_to_user((int*)arg, &rw_s.count,
+ sizeof(unsigned long));
+ return err;
+ }
+
+
case OBD_IOC_READ:
{
int err;
copy_from_user(&prealloc, (int *)arg,
sizeof(struct oic_prealloc_s));
- if (!obddev->sb || !obddev->sb->s_dev) {
+ if (!obddev->u.sim.sim_sb || !obddev->u.sim.sim_sb->s_dev) {
CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
return -EINVAL;
}
{
struct statfs *tmp;
unsigned int conn_id;
-
+ struct statfs buf;
+ int rc;
+
tmp = (void *)arg + sizeof(unsigned int);
get_user(conn_id, (int *) arg);
if ( !obddev->obd_type ||
!obddev->obd_type->typ_ops->o_statfs)
return -EINVAL;
- return obddev->obd_type->typ_ops->o_statfs(conn_id, tmp);
+ rc = obddev->obd_type->typ_ops->o_statfs(conn_id, &buf);
+ if ( rc )
+ return rc;
+ rc = copy_to_user(tmp, &buf, sizeof(buf));
+ return rc;
+
}
default:
printk("invalid ioctl: cmd = %u, arg = %lu\n", cmd, arg);
if ( !type )
return -1;
- if ( type->typ_refcount )
+ if ( type->typ_refcnt )
return -1;
list_del(&type->typ_chain);
}
for (i = 0; i < MAX_OBD_DEVICES; i++) {
- obd_dev[i].obd_type = 0;
- obd_dev[i].refcnt = 0;
- obd_dev[i].sb = NULL;
- obd_dev[i].last_id = 0;
- INIT_LIST_HEAD(&obd_dev[i].clients);
+ memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
+ INIT_LIST_HEAD(&obd_dev[i].u.sim.sim_clients);
}
obd_sysctl_init();