From f94ced5f79da783e38717813a58716906d0269f2 Mon Sep 17 00:00:00 2001 From: braam Date: Wed, 24 Nov 1999 19:46:12 +0000 Subject: [PATCH] Changes to accomodate the snapshot driver. For working snapshot code, see the snap directory and the snap/setup.sh script. The code is not complete, unlink hasn't been done yet. --- lustre/obdclass/class_obd.c | 425 ++++++++++++++++++++++++++++++-------------- lustre/obdclass/cleanup.sh | 1 + lustre/obdclass/genops.c | 146 ++++++++------- lustre/obdclass/obdcontrol | 218 ++++++++++++++++++++++- lustre/obdclass/setup.sh | 10 +- 5 files changed, 594 insertions(+), 206 deletions(-) diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index 95bdef8..ceb72c3 100644 --- a/lustre/obdclass/class_obd.c +++ b/lustre/obdclass/class_obd.c @@ -56,6 +56,7 @@ #include #include +static int obd_init_magic; int obd_print_entry = 1; int obd_debug_level = 4095; struct obd_device obd_dev[MAX_OBD_DEVICES]; @@ -110,10 +111,12 @@ static struct obd_type *obd_nm_to_type(char *nm) { 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; @@ -130,6 +133,8 @@ static int getdata(int len, void **data) if (!len) return 0; + CDEBUG(D_IOCTL, "getdata: len %d, add %p\n", len, *data); + OBD_ALLOC(tmp, void *, len); if ( !tmp ) return -ENOMEM; @@ -150,11 +155,9 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, { 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; @@ -162,6 +165,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, if (dev > MAX_OBD_DEVICES) return -ENODEV; obddev = &obd_dev[dev]; + conn.oc_dev = obddev; switch (cmd) { case OBD_IOC_ATTACH: { @@ -197,8 +201,11 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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++; @@ -208,7 +215,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, /* 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 ) { @@ -221,6 +228,24 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, } 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; @@ -289,7 +314,109 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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; @@ -317,6 +444,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, if (err) return err; + /* do the setup */ CDEBUG(D_IOCTL, "Setup %d, type %s\n", dev, obddev->obd_type->typ_name); @@ -331,8 +459,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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: { @@ -345,6 +475,9 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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; @@ -354,15 +487,12 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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))) { @@ -370,11 +500,12 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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 */ @@ -383,8 +514,9 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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: { @@ -418,14 +550,9 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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 */ @@ -440,6 +567,11 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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) @@ -451,167 +583,158 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, !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; @@ -629,7 +752,8 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, !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)); @@ -648,20 +772,30 @@ int obd_register_type(struct obd_ops *ops, char *nm) { 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; } @@ -669,14 +803,23 @@ int obd_unregister_type(char *nm) { 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; } @@ -707,9 +850,9 @@ int init_obd(void) 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", @@ -719,11 +862,12 @@ int init_obd(void) 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; } @@ -738,8 +882,9 @@ EXPORT_SYMBOL(gen_connect); 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); @@ -759,10 +904,14 @@ void cleanup_module(void) 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 diff --git a/lustre/obdclass/cleanup.sh b/lustre/obdclass/cleanup.sh index 462440c..8d39a73 100644 --- a/lustre/obdclass/cleanup.sh +++ b/lustre/obdclass/cleanup.sh @@ -5,6 +5,7 @@ rmmod obdfs ./obdcontrol -f << EOF cleanup +detach quit EOF diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index fcc0d06..06992c1 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -24,23 +24,18 @@ 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; @@ -49,47 +44,46 @@ struct obd_client *gen_client(int cli_id) /* 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; @@ -104,12 +98,11 @@ int gen_disconnect(unsigned int conn_id) 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 */ @@ -119,27 +112,8 @@ int gen_multi_setup(struct obd_device *obddev, int len, void *data) 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; @@ -156,7 +130,7 @@ int gen_multi_attach(struct obd_device *obddev, int len, void *data) } return 0; } - +#endif /* @@ -164,22 +138,18 @@ int gen_multi_attach(struct obd_device *obddev, int len, void *data) * 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 */ @@ -202,8 +172,64 @@ int gen_cleanup(struct obd_device * obddev) 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; +} diff --git a/lustre/obdclass/obdcontrol b/lustre/obdclass/obdcontrol index e4497cc..a399b7e 100755 --- a/lustre/obdclass/obdcontrol +++ b/lustre/obdclass/obdcontrol @@ -21,8 +21,8 @@ BEGIN { require "asm/ioctl.ph" }; # 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 @@ -55,6 +55,12 @@ eval 'sub OBD_IOC_PARTITION () { &_IOC(3, ord(\'f\'), 19, 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); @@ -87,7 +93,12 @@ my %commands = ('device' => {func => "Device", doc => "device : open another OBD device"}, 'filesystem' => {func => "Filesystem", doc => "filesystem : 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"}, @@ -121,6 +132,19 @@ my $term, $attribs; Device($::device); Filesystem($::filesystem); + +sub readl { + if ( $file ) { + my $str = ; + chop($str); + return $str; + } else { + return $term->readline(@_); + } +} + + + if ( $file ) { while ( ) { print $_; @@ -216,7 +240,7 @@ sub Device { $::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"; } @@ -249,6 +273,190 @@ sub Attach { } } +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 ( ) { + 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; @@ -302,7 +510,7 @@ sub Setup { } 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"; diff --git a/lustre/obdclass/setup.sh b/lustre/obdclass/setup.sh index 24abc26..fcd1dec 100755 --- a/lustre/obdclass/setup.sh +++ b/lustre/obdclass/setup.sh @@ -1,13 +1,17 @@ #! /bin/bash - insmod loop losetup /dev/loop0 /tmp/fs -insmod obdclass.o +insmod ../class/obdclass.o insmod ../ext2obd/obdext2.o insmod ../obdfs/obdfs.o + +echo "NEW OBDFS setup..." >> /var/log/messages + ./obdcontrol -f << EOF attach ext2_obd setup quit EOF -mount -t obdfs /dev/obd0 /mnt/obd +echo "NEW OBDFS mount..." >> /var/log/messages +mount -t obdfs -odevice=/dev/obd0 /dev/obd0 /mnt/obd +echo "NEW OBDFS usage..." >> /var/log/messages -- 1.8.3.1