#include <linux/obd_support.h>
#include <linux/obd_class.h>
+static int obd_init_magic;
int obd_print_entry = 1;
int obd_debug_level = 4095;
struct obd_device obd_dev[MAX_OBD_DEVICES];
{
struct list_head *tmp;
struct obd_type *type;
+ CDEBUG(D_IOCTL, "SEARCH %s\n", nm);
tmp = &obd_types;
while ( (tmp = tmp->next) != &obd_types ) {
type = list_entry(tmp, struct obd_type, typ_chain);
+ CDEBUG(D_IOCTL, "TYP %s\n", type->typ_name);
if (strlen(type->typ_name) == strlen(nm) &&
strcmp(type->typ_name, nm) == 0 ) {
return type;
if (!len)
return 0;
+ CDEBUG(D_IOCTL, "getdata: len %d, add %p\n", len, *data);
+
OBD_ALLOC(tmp, void *, len);
if ( !tmp )
return -ENOMEM;
{
int err, i_ino, dev;
struct obd_device *obddev;
- struct oic_rw_s rw_s; /* read, write */
+ struct obd_conn conn;
long int cli_id; /* connect, disconnect */
- struct oic_prealloc_s prealloc; /* preallocate */
-
if (!inode)
return -EINVAL;
if (dev > MAX_OBD_DEVICES)
return -ENODEV;
obddev = &obd_dev[dev];
+ conn.oc_dev = obddev;
switch (cmd) {
case OBD_IOC_ATTACH: {
return err;
}
- CDEBUG(D_IOCTL, "Attach %d, type %s\n",
- dev, obddev->obd_type->typ_name);
+ 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);
if (!obddev->obd_type->typ_ops || !OBP(obddev,attach)) {
obddev->obd_flags |= OBD_ATTACHED;
type->typ_refcnt++;
/* do the attach */
err = OBP(obddev,attach)(obddev,
- input.att_datalen, &input.att_data);
+ input.att_datalen, input.att_data);
OBD_FREE(input.att_data, input.att_datalen);
if ( err ) {
}
return err;
}
+
+ case OBD_IOC_DETACH: {
+
+ if (obddev->obd_flags & OBD_SET_UP)
+ return -EINVAL;
+ if (! (obddev->obd_flags & OBD_ATTACHED) )
+ return -EINVAL;
+ if ( !list_empty(&obddev->obd_gen_clients) )
+ return -EINVAL;
+
+ obddev->obd_flags &= ~OBD_ATTACHED;
+ obddev->obd_type->typ_refcnt--;
+ obddev->obd_type = NULL;
+ MOD_DEC_USE_COUNT;
+ return 0;
+ }
+
+
case OBD_IOC_FORMAT: {
struct ioc_format {
int format_datalen;
OBD_FREE(input.part_data, input.part_datalen);
return err;
}
- case OBD_IOC_SETUP_OBDDEV: {
+
+ case OBD_IOC_COPY: {
+ struct ioc_mv_s mvdata;
+ struct ioc_part {
+ int part_datalen;
+ void *part_data;
+ } input;
+ obdattr *srcoa, *tgtoa;
+
+ if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
+ (!(obddev->obd_flags & OBD_ATTACHED))) {
+ CDEBUG(D_IOCTL, "Device not attached or set up\n");
+ return -EINVAL;
+ }
+
+ /* get main structure */
+ err = copy_from_user(&input, (void *) arg, sizeof(input));
+ if (err)
+ return err;
+
+
+ err = copy_from_user(&mvdata, input.part_data, sizeof(mvdata));
+ if (err)
+ return err;
+
+ if (!obddev->obd_type->typ_ops ||
+ !obddev->obd_type->typ_ops->o_copy )
+ return -EOPNOTSUPP;
+
+ /* do the partition */
+ CDEBUG(D_IOCTL, "Copy %d, type %s src %ld tgt %ld\n", dev,
+ obddev->obd_type->typ_name, mvdata.src, mvdata.tgt);
+
+ conn.oc_id = mvdata.conn_id;
+ srcoa = obd_oa_fromid(&conn, mvdata.src);
+ if ( !srcoa )
+ return -ENOENT;
+ tgtoa = obd_oa_fromid(&conn, mvdata.tgt);
+ if ( ! tgtoa ) {
+ obd_free_oa(srcoa);
+ return -ENOMEM;
+ }
+
+ err = obddev->obd_type->typ_ops->o_copy(&conn,srcoa, tgtoa);
+
+ obd_free_oa(srcoa);
+ obd_free_oa(tgtoa);
+ return err;
+ }
+ case OBD_IOC_MIGR: {
+ struct ioc_mv_s mvdata;
+ struct ioc_part {
+ int part_datalen;
+ void *part_data;
+ } input;
+ obdattr *srcoa, *tgtoa;
+
+ if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
+ (!(obddev->obd_flags & OBD_ATTACHED))) {
+ CDEBUG(D_IOCTL, "Device not attached or set up\n");
+ return -EINVAL;
+ }
+
+ /* get main structure */
+ err = copy_from_user(&input, (void *) arg, sizeof(input));
+ if (err)
+ return err;
+
+
+ CDEBUG(D_IOCTL, "Migrate copying %d\n", sizeof(mvdata));
+ err = copy_from_user(&mvdata, input.part_data, sizeof(mvdata));
+ if (err)
+ return err;
+
+ if (!obddev->obd_type->typ_ops ||
+ !obddev->obd_type->typ_ops->o_copy )
+ return -EOPNOTSUPP;
+
+ /* do the partition */
+ CDEBUG(D_IOCTL, "Migrate %d, type %s conn %d src %ld tgt %ld\n", dev,
+ obddev->obd_type->typ_name, mvdata.conn_id, mvdata.src, mvdata.tgt);
+
+
+ if ( ! (srcoa = obd_empty_oa()) )
+ return -ENOMEM;
+ if ( ! (tgtoa = obd_empty_oa()) ) {
+ obd_free_oa(srcoa);
+ return -ENOMEM;
+ }
+
+ srcoa->i_ino = mvdata.src;
+ tgtoa->i_ino = mvdata.tgt;
+
+ conn.oc_id = mvdata.conn_id;
+
+ err = obddev->obd_type->typ_ops->o_migrate(&conn, srcoa, tgtoa);
+
+ obd_free_oa(srcoa);
+ obd_free_oa(tgtoa);
+ return err;
+ }
+
+ case OBD_IOC_SETUP: {
struct ioc_setup {
int setup_datalen;
void *setup_data;
if (err)
return err;
+
/* do the setup */
CDEBUG(D_IOCTL, "Setup %d, type %s\n", dev,
obddev->obd_type->typ_name);
if ( err )
obddev->obd_flags &= ~OBD_SET_UP;
- else
+ else {
+ obddev->obd_type->typ_refcnt++;
obddev->obd_flags |= OBD_SET_UP;
+ }
return err;
}
case OBD_IOC_CLEANUP: {
if ( !obddev->obd_type->typ_refcnt )
printk("OBD_CLEANUP: refcount wrap!\n");
+ if ( !obddev->obd_flags & OBD_SET_UP )
+ return -EINVAL;
+
if ( !obddev->obd_type->typ_ops->o_cleanup )
goto cleanup_out;
return rc;
cleanup_out:
- obddev->obd_flags = 0;
+ obddev->obd_flags &= ~OBD_SET_UP;
obddev->obd_type->typ_refcnt--;
- obddev->obd_type = NULL;
- MOD_DEC_USE_COUNT;
return 0;
}
case OBD_IOC_CONNECT:
{
- struct obd_conn_info conninfo;
if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
(!(obddev->obd_flags & OBD_ATTACHED))) {
return -EINVAL;
}
- if (obddev->obd_type->typ_ops->o_connect(obddev, &conninfo))
+
+ if (obddev->obd_type->typ_ops->o_connect(&conn))
return -EINVAL;
- return copy_to_user((int *)arg, &conninfo,
- sizeof(struct obd_conn_info));
+ return copy_to_user((int *)arg, &conn.oc_id,
+ sizeof(int));
}
case OBD_IOC_DISCONNECT:
/* frees data structures */
return -ENODEV;
get_user(cli_id, (int *) arg);
+ conn.oc_id = cli_id;
- OBP(obddev, disconnect)(cli_id);
+ OBP(obddev, disconnect)(&conn);
return 0;
case OBD_IOC_SYNC: {
if ( !(obddev->obd_flags & OBD_ATTACHED) ||
!(obddev->obd_flags & OBD_SET_UP))
return -ENODEV;
+ conn.oc_id = foo.conn_id;
-
- if (!obddev->u.ext2.ext2_sb) {
- CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
- return put_user(-EINVAL, (int *) arg);
- }
-
- i_ino = OBP(obddev, create)(foo.conn_id, foo.prealloc, &err);
+ i_ino = OBP(obddev, create)(&conn, foo.prealloc, &err);
if (err) {
CDEBUG(D_IOCTL, "create: obd_inode_new failure\n");
/* 0 is the only error value */
unsigned int conn_id;
unsigned int ino;
} destroy;
+ obdattr *oa;
+ int rc;
+
+ if ( ! (oa = obd_empty_oa()) )
+ return -ENOMEM;
/* has this minor been registered? */
if (!obddev->obd_type)
!obddev->obd_type->typ_ops->o_destroy)
return -EINVAL;
- return obddev->obd_type->typ_ops->o_destroy(destroy.conn_id, destroy.ino);
+ oa->i_ino = destroy.ino;
+ conn.oc_id = destroy.conn_id;
+ rc = obddev->obd_type->typ_ops->o_destroy(&conn, oa);
+ OBD_FREE(oa, sizeof(*oa));
+ return rc;
}
case OBD_IOC_SETATTR:
{
- int err;
struct oic_attr_s foo;
- struct inode holder;
+ obdattr *oa;
+ int rc;
+
+ if ( ! (oa = obd_empty_oa()) )
+ return -ENOMEM;
/* has this minor been registered? */
if (!obddev->obd_type)
return -ENODEV;
-
- err= copy_from_user(&foo, (int *)arg, sizeof(foo));
- if (err)
- return err;
+ rc = copy_from_user(&foo, (int *)arg, sizeof(foo));
+ if (rc)
+ return rc;
if ( !obddev->obd_type ||
!obddev->obd_type->typ_ops->o_setattr)
return -EINVAL;
- inode_setattr(&holder, &foo.iattr);
- return obddev->obd_type->typ_ops->o_setattr(foo.conn_id, foo.ino, &holder);
+ oa->i_ino = foo.ino;
+ inode_setattr(oa, &foo.iattr);
+ conn.oc_id = foo.conn_id;
+ rc = obddev->obd_type->typ_ops->o_setattr(&conn, oa);
+ OBD_FREE(oa, sizeof(*oa));
+ return rc;
}
case OBD_IOC_GETATTR:
{
- int err;
- struct tmp {
+ int rc;
+ struct oic_getattr {
unsigned int conn_id;
unsigned long ino;
} foo;
struct iattr iattr;
- struct inode holder;
- copy_from_user(&foo, (int *)arg, sizeof(struct tmp));
+ obdattr *oa;
- if ( !obddev->obd_type ||
- !obddev->obd_type->typ_ops->o_getattr)
- return -EINVAL;
+ rc = copy_from_user(&foo, (int *)arg, sizeof(foo));
+ if (rc)
+ return rc;
- if (obddev->obd_type->typ_ops->o_getattr(foo.conn_id,
- foo.ino, &holder))
- return -EINVAL;
+ conn.oc_id = foo.conn_id;
+ oa = obd_oa_fromid(&conn, foo.ino);
+ if ( !oa )
+ return -ENOENT;
- inode_to_iattr(&holder, &iattr);
- err = copy_to_user((int *)arg, &iattr, sizeof(iattr));
- return err;
+ inode_to_iattr(oa, &iattr);
+ rc = copy_to_user((int *)arg, &iattr, sizeof(iattr));
+ return rc;
}
- case OBD_IOC_READ2:
+ case OBD_IOC_READ:
{
- int err;
+ obdattr *oa = NULL;
+ int rc;
+ struct oic_rw_s rw_s; /* read, write ioctl str */
- /* has this minor been registered? */
- if (!obddev->obd_type)
- return -ENODEV;
+ rc = copy_from_user(&rw_s, (int *)arg, sizeof(rw_s));
+ if ( rc )
+ goto READ_OUT;
- err = copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
- if ( err )
- return err;
+
+ conn.oc_id = rw_s.conn_id;
+ if ( ! (oa = obd_oa_fromid(&conn, rw_s.id)) )
+ return -ENOENT;
+ rc = -EINVAL;
if ( !obddev->obd_type->typ_ops ||
!obddev->obd_type->typ_ops->o_read )
- return -EINVAL;
+ goto READ_OUT;
- 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;
+ rc = obddev->obd_type->typ_ops->o_read
+ (&conn, oa, rw_s.buf, &rw_s.count, rw_s.offset);
+ if ( rc )
+ goto READ_OUT;
- err = copy_to_user((int*)arg, &rw_s.count,
- sizeof(unsigned long));
- return err;
- }
+ rc = copy_to_user((int*)arg, &rw_s.count, sizeof(rw_s.count));
+ READ_OUT:
+ if ( oa )
+ OBD_FREE(oa, sizeof(*oa));
+ return rc;
+ }
- case OBD_IOC_READ:
- {
- int err;
- /* has this minor been registered? */
- if (!obddev->obd_type)
- return -ENODEV;
+ case OBD_IOC_WRITE: {
+ obdattr *oa = NULL;
+ int rc;
+ struct oic_rw_s rw_s; /* read, write ioctl str */
+ rc = copy_from_user(&rw_s, (int *)arg, sizeof(rw_s));
+ if ( rc )
+ goto WRITE_OUT;
- err = copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
- if ( err )
- return err;
+ conn.oc_id = rw_s.conn_id;
+ oa = obd_oa_fromid(&conn, rw_s.id);
+ if ( !oa )
+ return -ENOENT;
+ rc = -EINVAL;
if ( !obddev->obd_type->typ_ops ||
- !obddev->obd_type->typ_ops->o_read )
- return -EINVAL;
-
- rw_s.count = obddev->obd_type->typ_ops->o_read(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;
- }
+ !obddev->obd_type->typ_ops->o_write )
+ goto WRITE_OUT;
- case OBD_IOC_WRITE:
- {
- int err;
- /* has this minor been registered? */
- if (!obddev->obd_type)
- return -ENODEV;
+ rc = obddev->obd_type->typ_ops->o_write
+ (&conn, oa, rw_s.buf, &rw_s.count, rw_s.offset);
+ if ( rc )
+ goto WRITE_OUT;
+ rc = copy_to_user((int*)arg, &rw_s.count, sizeof(rw_s.count));
- copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
- CDEBUG(D_IOCTL, "\n");
- if ( !obddev->obd_type->typ_ops->o_write )
- return -EINVAL;
- rw_s.count =
- obddev->obd_type->typ_ops->o_write(rw_s.conn_id,
- rw_s.inode,
- rw_s.buf,
- rw_s.count,
- rw_s.offset,
- &err);
-
- printk("Result rw_s.count %ld\n", rw_s.count);
- return (int)rw_s.count;
- copy_to_user((int *)arg, &rw_s.count,
- sizeof(unsigned long));
- return err;
+ WRITE_OUT:
+ OBD_FREE(oa, sizeof(*oa));
+ return rc;
}
- case OBD_IOC_PREALLOCATE:
+ case OBD_IOC_PREALLOCATE: {
+ struct oic_prealloc_s prealloc;
+ int rc;
+
/* has this minor been registered? */
if (!obddev->obd_type)
return -ENODEV;
- copy_from_user(&prealloc, (int *)arg,
- sizeof(struct oic_prealloc_s));
+ rc = copy_from_user(&prealloc, (int *)arg, sizeof(prealloc));
+ if (rc)
+ return -ENOMEM;
- if (!obddev->u.ext2.ext2_sb || !obddev->u.ext2.ext2_sb->s_dev) {
+ if ( !(obddev->obd_flags & OBD_ATTACHED) ||
+ !(obddev->obd_flags & OBD_SET_UP)) {
CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
return -EINVAL;
}
if (!obddev->obd_type ||
!obddev->obd_type->typ_ops->o_preallocate)
- return -EINVAL;
+ return -EOPNOTSUPP;
+ conn.oc_id = prealloc.cli_id;
+ rc = obddev->obd_type->typ_ops->o_preallocate
+ (&conn, &prealloc.alloc, prealloc.inodes);
+ if ( rc )
+ return rc;
- prealloc.alloc =
- obddev->obd_type->typ_ops->o_preallocate(prealloc.cli_id, prealloc.alloc,
- prealloc.inodes, &err);
- if ( err )
- return err;
- return copy_to_user((int *)arg, &prealloc,
- sizeof(struct oic_prealloc_s));
+ return copy_to_user((int *)arg, &prealloc, sizeof(prealloc));
+ }
case OBD_IOC_STATFS:
{
struct statfs *tmp;
!obddev->obd_type->typ_ops->o_statfs)
return -EINVAL;
- rc = obddev->obd_type->typ_ops->o_statfs(conn_id, &buf);
+ conn.oc_id = conn_id;
+ rc = obddev->obd_type->typ_ops->o_statfs(&conn, &buf);
if ( rc )
return rc;
rc = copy_to_user(tmp, &buf, sizeof(buf));
{
struct obd_type *type;
+
+ if (obd_init_magic != 0x11223344) {
+ EXIT;
+ return -EINVAL;
+ }
+
if ( obd_nm_to_type(nm) ) {
CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
+ EXIT;
return -1;
}
-
+
OBD_ALLOC(type, struct obd_type * , sizeof(*type));
- if ( !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 = obd_nm_to_type(nm);
- if ( !type )
+ if ( !type ) {
+ MOD_DEC_USE_COUNT;
+ printk("OBD: NO TYPE\n");
+ EXIT;
return -1;
+ }
- if ( type->typ_refcnt )
+ if ( type->typ_refcnt ) {
+ MOD_DEC_USE_COUNT;
+ printk("OBD: refcount wrap\n");
+ EXIT;
return -1;
+ }
list_del(&type->typ_chain);
OBD_FREE(type, sizeof(*type));
+ MOD_DEC_USE_COUNT;
return 0;
}
int i;
printk(KERN_INFO "OBD class driver v0.002, braam@stelias.com\n");
-
+
INIT_LIST_HEAD(&obd_types);
-
+
if (register_chrdev(OBD_PSDEV_MAJOR,"obd_psdev",
&obd_psdev_fops)) {
printk(KERN_ERR "obd_psdev: unable to get major %d\n",
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);
}
obd_sysctl_init();
-
+ obd_init_magic = 0x11223344;
return 0;
}
EXPORT_SYMBOL(gen_client);
EXPORT_SYMBOL(gen_cleanup);
EXPORT_SYMBOL(gen_disconnect);
+EXPORT_SYMBOL(gen_copy_data);
-EXPORT_SYMBOL(gen_multi_attach);
+/* EXPORT_SYMBOL(gen_multi_attach); */
EXPORT_SYMBOL(gen_multi_setup);
EXPORT_SYMBOL(gen_multi_cleanup);
for (i = 0; i < MAX_OBD_DEVICES; i++) {
struct obd_device *obddev = &obd_dev[i];
if ( obddev->obd_type &&
- obddev->obd_type->typ_ops->o_cleanup_device )
- OBP(obddev, cleanup_device)(obddev);
+ (obddev->obd_flags & OBD_SET_UP) &&
+ obddev->obd_type->typ_ops->o_detach ) {
+ OBP(obddev, detach)(obddev);
+ }
}
+
obd_sysctl_clean();
+ obd_init_magic = 0;
}
#endif
extern struct obd_device obd_dev[MAX_OBD_DEVICES];
/* map connection to client */
-struct obd_client *gen_client(int cli_id)
+struct obd_client *gen_client(struct obd_conn *conn)
{
- struct obd_device * obddev;
+ struct obd_device * obddev = conn->oc_dev;
struct list_head * lh, * next;
struct obd_client * cli;
- int a;
- for (a = 0; a < MAX_OBD_DEVICES; a++) {
- obddev = &obd_dev[a];
-
- lh = next = &obddev->obd_gen_clients;
- while ((lh = lh->next) != &obddev->obd_gen_clients) {
- cli = list_entry(lh, struct obd_client, cli_chain);
-
- if (cli->cli_id == cli_id)
- return cli;
- }
+ lh = next = &obddev->obd_gen_clients;
+ while ((lh = lh->next) != &obddev->obd_gen_clients) {
+ cli = list_entry(lh, struct obd_client, cli_chain);
+
+ if (cli->cli_id == conn->oc_id)
+ return cli;
}
return NULL;
/* a connection defines a context in which preallocation can be managed. */
-int gen_connect (struct obd_device *obddev,
- struct obd_conn_info * conninfo)
+int gen_connect (struct obd_conn *conn)
{
struct obd_client * cli;
OBD_ALLOC(cli, struct obd_client *, sizeof(struct obd_client));
if ( !cli ) {
printk("obd_connect (minor %d): no memory!\n",
- obddev->obd_minor);
+ conn->oc_dev->obd_minor);
return -ENOMEM;
}
INIT_LIST_HEAD(&cli->cli_prealloc_inodes);
/* this should probably spinlocked? */
- cli->cli_id = ++obddev->obd_gen_last_id;
+ cli->cli_id = ++conn->oc_dev->obd_gen_last_id;
cli->cli_prealloc_quota = 0;
- cli->cli_obd = obddev;
- list_add(&(cli->cli_chain), obddev->obd_gen_clients.prev);
+ cli->cli_obd = conn->oc_dev;
+ list_add(&(cli->cli_chain), conn->oc_dev->obd_gen_clients.prev);
CDEBUG(D_IOCTL, "connect: new ID %u\n", cli->cli_id);
- conninfo->conn_id = cli->cli_id;
+ conn->oc_id = cli->cli_id;
return 0;
} /* gen_obd_connect */
-int gen_disconnect(unsigned int conn_id)
+int gen_disconnect(struct obd_conn *conn)
{
struct obd_client * cli;
-
ENTRY;
- if (!(cli = gen_client(conn_id))) {
+ if (!(cli = gen_client(conn))) {
CDEBUG(D_IOCTL, "disconnect: attempting to free "
- "nonexistent client %u\n", conn_id);
+ "nonexistent client %u\n", conn->oc_id);
return -EINVAL;
}
+
list_del(&(cli->cli_chain));
OBD_FREE(cli, sizeof(struct obd_client));
- CDEBUG(D_IOCTL, "disconnect: ID %u\n", conn_id);
+ CDEBUG(D_IOCTL, "disconnect: ID %u\n", conn->oc_id);
EXIT;
return 0;
int gen_multi_setup(struct obd_device *obddev, int len, void *data)
{
int i;
- struct obd_device *rdev = obddev->obd_multi_dev[0];
for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
int rc;
- struct obd_device *child = rdev + i;
- rc = OBP(child, connect)(child, &rdev->obd_multi_conns[i]);
+ struct obd_conn *ch_conn = &obddev->obd_multi_conn[i];
+ rc = OBP(ch_conn->oc_dev, connect)(ch_conn);
if ( rc != 0 ) {
/* XXX disconnect others */
return 0;
}
-int gen_multi_cleanup(struct obd_device * obddev)
-{
- int i;
- struct obd_device **rdev = obddev->obd_multi_dev;
-
- for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
- int rc;
- struct obd_device *child = *(rdev + i);
- rc = OBP(child, cleanup)(child);
- *(rdev + i) = NULL;
-
- if ( rc != 0 ) {
- /* XXX disconnect others */
- return -EINVAL;
- }
- }
- gen_cleanup(obddev);
- return 0;
-} /* sim_cleanup_obddev */
-
+#if 0
int gen_multi_attach(struct obd_device *obddev, int len, void *data)
{
int i;
}
return 0;
}
-
+#endif
/*
* close all connections to lower devices
* needed for forced unloads of OBD client drivers
*/
-int gen_multi_cleanup_device(struct obd_device *obddev)
+int gen_multi_cleanup(struct obd_device *obddev)
{
int i;
- struct obd_device **rdev;
- rdev = obddev->obd_multi_dev;
for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
+ struct obd_conn *ch_conn = &obddev->obd_multi_conn[i];
int rc;
- struct obd_device *child = *(rdev + i);
- rc = OBP(child, disconnect)
- (obddev->obd_multi_conns[i].conn_id);
+ rc = OBP(ch_conn->oc_dev, disconnect)(ch_conn);
if ( rc != 0 ) {
- printk("OBD multi cleanup dev: disconnect failure %d\n", child->obd_minor);
+ printk("OBD multi cleanup dev: disconnect failure %d\n", ch_conn->oc_dev->obd_minor);
}
- *(rdev + i) = NULL;
}
return 0;
} /* gen_multi_cleanup_device */
cli = list_entry(tmp, struct obd_client, cli_chain);
CDEBUG(D_IOCTL, "Disconnecting obd_connection %d, at %p\n",
cli->cli_id, cli);
- OBP(obddev, disconnect)(cli->cli_id);
}
-
- return OBP(obddev, cleanup_device)(obddev);
+ return 0;
} /* sim_cleanup_device */
+
+void ___wait_on_page(struct page *page)
+{
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+
+ add_wait_queue(&page->wait, &wait);
+ do {
+ run_task_queue(&tq_disk);
+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+ if (!PageLocked(page))
+ break;
+ schedule();
+ } while (PageLocked(page));
+ tsk->state = TASK_RUNNING;
+ remove_wait_queue(&page->wait, &wait);
+}
+
+void lck_page(struct page *page)
+{
+ while (TryLockPage(page))
+ ___wait_on_page(page);
+}
+
+int gen_copy_data(struct obd_conn *conn, obdattr *src, obdattr *tgt)
+{
+ struct page *page;
+ unsigned long offset = 0;
+ int rc;
+
+ page = __get_pages(GFP_USER, 0);
+ if ( !page )
+ return -ENOMEM;
+
+
+ lck_page(page);
+
+ while (offset < src->i_size) {
+
+ page->offset = offset;
+ rc = OBP(conn->oc_dev, brw)(READ, conn, src, page, 0);
+
+ if ( rc != PAGE_SIZE )
+ break;
+
+ rc = OBP(conn->oc_dev,brw)(WRITE, conn, tgt, page, 1);
+ if ( rc != PAGE_SIZE)
+ break;
+
+ offset += rc;
+ }
+ tgt->i_size = src->i_size;
+ tgt->i_blocks = src->i_blocks;
+ UnlockPage(page);
+ __free_page(page);
+
+ return 0;
+}
# p2ph generated invalid macros for ioctl stuff, so I override some of it here
eval 'sub OBD_IOC_CREATE () { &_IOC(2, ord(\'f\'), 3, 4);}' unless
defined(&OBD_IOC_CREATE);
-eval 'sub OBD_IOC_SETUP_OBDDEV () { &_IOC(1, ord(\'f\'), 4, 4);}' unless
- defined(&OBD_IOC_SETUP_OBDDEV);
+eval 'sub OBD_IOC_SETUP () { &_IOC(1, ord(\'f\'), 4, 4);}' unless
+ defined(&OBD_IOC_SETUP);
eval 'sub OBD_IOC_CLEANUP () { &_IOC(0, ord(\'f\'), 5, 0);}' unless
defined(&OBD_IOC_CLEANUP);
eval 'sub OBD_IOC_DESTROY () { &_IOC(1, ord(\'f\'), 6, 4);}' unless
defined(&OBD_IOC_PARTITION);
eval 'sub OBD_IOC_ATTACH () { &_IOC(3, ord(\'f\'), 20, 4);}' unless
defined(&OBD_IOC_ATTACH);
+eval 'sub OBD_IOC_DETACH () { &_IOC(3, ord(\'f\'), 21, 4);}' unless
+ defined(&OBD_IOC_DETACH);
+eval 'sub OBD_IOC_COPY () { &_IOC(3, ord(\'f\'), 22, 4);}' unless
+ defined(&OBD_IOC_COPY);
+eval 'sub OBD_IOC_MIGR () { &_IOC(3, ord(\'f\'), 23, 4);}' unless
+ defined(&OBD_IOC_MIGR);
eval 'sub ATTR_MODE () {1;}' unless defined(&ATTR_MODE);
eval 'sub ATTR_UID () {2;}' unless defined(&ATTR_UID);
('device' => {func => "Device", doc => "device <dev>: open another OBD device"},
'filesystem' => {func => "Filesystem", doc => "filesystem <dev>: partition for direct OBD device"},
'create' => {func => "Create", doc => "create: creates a new inode"},
- 'attach' => {func => "Attach", doc => "format type [adapter bus tid lun]"},
+ 'attach' => {func => "Attach", doc => "attach type [adapter bus tid lun]"},
+ 'detach' => {func => "Detach", doc => "detach this device"},
+ 'snapattach' => {func => "SnapAttach", doc => "snapattach snapno snapcount time1 index1 .... timek indexk"},
+ 'snaptable' => {func => "SnapShotTable", doc => "snaptable: build a snapshot table (interactive)"},
+ 'copy' => {func => "Copy", doc => "copy srcid tgtid"},
+ 'migrate' => {func => "Migrate", doc => "migrate srcid tgtid"},
'format' => {func => "Format", doc => "format type adapter bus tid lun size"},
'partition' => {func => "Partition", doc => "partition type adapter bus tid lun partition size"},
'setup' => {func => "Setup", doc => "setup: link the ext2 partition (default /dev/loop0) to this obddev"},
Device($::device);
Filesystem($::filesystem);
+
+sub readl {
+ if ( $file ) {
+ my $str = <STDIN>;
+ chop($str);
+ return $str;
+ } else {
+ return $term->readline(@_);
+ }
+}
+
+
+
if ( $file ) {
while ( <STDIN> ) {
print $_;
$::device = $device;
# Open the device, as we need an FD for the ioctl
sysopen(DEV_OBD, $device, 0) || die "Cannot open $device";
-
+ print "Device now $device\n";
}
}
}
+sub Detach {
+ my $err = 0;
+ my $data = "";
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_DETACH, $data);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+
+sub SnapAttach {
+ my $err = 0;
+ my $type = "snap_obd";
+ my $snapdev = shift;
+ my $snapno = shift;
+ my $file = shift;
+ my $snapcount;
+ my $table = {};
+ my $data;
+ my $datalen = 0;
+
+ if ( ! -f $file ) {
+ print "No such file $file\n";
+ }
+
+ $table = ReadSnapShotTable($file);
+
+ $snapcount = keys %{$table};
+ print "Snapcount $snapcount\n";
+ $data = pack("iii", $snapdev, $snapno, $snapcount);
+ $datalen = 3 * 4;
+ foreach my $time (sort keys %{$table}) {
+ $data .= pack("Ii", $time, $table->{$time});
+ $datalen += 8;
+ }
+
+ my $len = length($type);
+ my $cl = length($data);
+ my $add = pack("p", $data);
+ print "type $type (len $len), datalen $datalen ($cl)\n";
+ printf "Addr of data %x\n", $add;
+ my $packed = pack("ipip", length($type), $type, $datalen, $data);
+
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_ATTACH, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+
+sub SnapShotTable {
+
+ my $file = &readl("enter file name: ");
+ if ( ! -f $file ) {
+ `touch $file`;
+ }
+ my $table = ReadSnapShotTable($file);
+
+ again:
+ PrintSnapShotTable($table);
+ my $action = &readl("Add, Delete or Quit [adq]: ");
+ goto done if ($action =~ "^q.*" );
+ goto add if ($action =~ "^a.*");
+ goto del if ($action =~ "^d.*");
+ goto again;
+
+ add:
+ my $idx = &readl("enter new index: ");
+ my $time = &readl("enter time (hit RET for \"now\"): ");
+ my $oldtime = SnapFindTimeFromIdx($idx, $table);
+ delete $table->{$oldtime} if defined $oldtime;
+ $time = time unless $time;
+ $table->{$time} = $idx;
+ goto again;
+
+ del:
+ $didx = &readl("Enter index to delete: ");
+ my $deltime = SnapFindTimeFromIdx($didx, $table);
+ delete $table->{$deltime} if defined $deltime;
+ goto again;
+
+ done:
+ my $ok = &readl("OK with new table? [Yn]: ");
+ unless ( $ok eq "no" ) {
+ WriteSnapShotTable($file, $table);
+ }
+}
+
+sub SnapFindTimeFromIdx {
+ my $idx = shift;
+ my $table = shift;
+
+ foreach my $time ( keys %{$table} ) {
+ if ( $table->{$time} == $idx ) {
+ return $time;
+ }
+ }
+ undef;
+}
+
+sub PrintSnapShotTable {
+ my $table = shift;
+ my $time;
+
+ foreach $time ( sort keys %{$table} ) {
+ my $stime = localtime($time);
+ printf "Time: %s -- Index %d\n", $stime, $table->{$time};
+ }
+}
+
+sub ReadSnapShotTable {
+
+ my $file = shift;
+ my $table = {};
+
+ open FH, "<$file";
+ while ( <FH> ) {
+ my ($time, $index) = split ;
+ $table->{$time} = $index;
+ }
+ close FH;
+ return $table;
+}
+
+sub WriteSnapShotTable {
+ my $file = shift;
+ my $table = shift;
+
+ open FH, ">$file";
+ foreach my $time ( sort keys %{$table} ) {
+ print FH "$time $table->{$time}\n";
+ }
+ close FH;
+}
+
+sub Copy {
+ my $err = 0;
+ my $srcid = shift;
+ my $tgtid = shift;
+ my $data = pack("III", $::client_id, $srcid, $tgtid);
+ my $datalen = 12;
+
+ my $packed = pack("ip", $datalen, $data);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_COPY, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+sub Migrate {
+ my $err = 0;
+ my $srcid = shift;
+ my $tgtid = shift;
+ my $data = pack("III", $::client_id, $srcid, $tgtid);
+ my $datalen = 12;
+
+ my $packed = pack("ip", $datalen, $data);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_MIGR, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+
sub Format {
my $err = 0;
my $size = shift;
}
my $packed = pack("ip", $datalen, $data);
- my $rc = ioctl(DEV_OBD, &OBD_IOC_SETUP_OBDDEV, $packed);
+ my $rc = ioctl(DEV_OBD, &OBD_IOC_SETUP, $packed);
if (!defined $rc) {
print STDERR "ioctl failed: $!\n";