aboutsummaryrefslogtreecommitdiffstats
path: root/tools/blktap
diff options
context:
space:
mode:
authorJake Wires <jwires@xensource.com>2007-02-22 21:32:17 -0800
committerJake Wires <jwires@xensource.com>2007-02-22 21:32:17 -0800
commit11e8d023ca155afdc579b4a7a53de44da19dea9f (patch)
treefd21c158d1a9be407ce52b1eceedf039f54eccf7 /tools/blktap
parent22c07c8f80658a1873425e1893445f41a98e468f (diff)
downloadxen-11e8d023ca155afdc579b4a7a53de44da19dea9f.tar.gz
xen-11e8d023ca155afdc579b4a7a53de44da19dea9f.tar.bz2
xen-11e8d023ca155afdc579b4a7a53de44da19dea9f.zip
[TAPDISK] minor changes to tapdisk and plugins
* open all parent images read-only * expose parent image names to tapdisk (needed for locking api) Signed-off-by: Jake Wires <jwires@xensource.com>
Diffstat (limited to 'tools/blktap')
-rw-r--r--tools/blktap/drivers/block-aio.c25
-rw-r--r--tools/blktap/drivers/block-qcow.c81
-rw-r--r--tools/blktap/drivers/block-ram.c22
-rw-r--r--tools/blktap/drivers/block-sync.c20
-rw-r--r--tools/blktap/drivers/block-vmdk.c23
-rw-r--r--tools/blktap/drivers/img2qcow.c2
-rw-r--r--tools/blktap/drivers/qcow2raw.c4
-rw-r--r--tools/blktap/drivers/tapdisk.c146
-rw-r--r--tools/blktap/drivers/tapdisk.h44
9 files changed, 224 insertions, 143 deletions
diff --git a/tools/blktap/drivers/block-aio.c b/tools/blktap/drivers/block-aio.c
index bbcc4c785a..733407b8c6 100644
--- a/tools/blktap/drivers/block-aio.c
+++ b/tools/blktap/drivers/block-aio.c
@@ -152,9 +152,9 @@ static inline void init_fds(struct disk_driver *dd)
}
/* Open the disk file and initialize aio state. */
-int tdaio_open (struct disk_driver *dd, const char *name)
+int tdaio_open (struct disk_driver *dd, const char *name, td_flag_t flags)
{
- int i, fd, ret = 0;
+ int i, fd, ret = 0, o_flags;
struct td_state *s = dd->td_state;
struct tdaio_state *prv = (struct tdaio_state *)dd->private;
@@ -187,12 +187,15 @@ int tdaio_open (struct disk_driver *dd, const char *name)
prv->iocb_free[i] = &prv->iocb_list[i];
/* Open the file */
- fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE);
+ o_flags = O_DIRECT | O_LARGEFILE |
+ ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR);
+ fd = open(name, o_flags);
if ( (fd == -1) && (errno == EINVAL) ) {
/* Maybe O_DIRECT isn't supported. */
- fd = open(name, O_RDWR | O_LARGEFILE);
+ o_flags &= ~O_DIRECT;
+ fd = open(name, o_flags);
if (fd != -1) DPRINTF("WARNING: Accessing image without"
"O_DIRECT! (%s)\n", name);
@@ -280,6 +283,9 @@ int tdaio_submit(struct disk_driver *dd)
int ret;
struct tdaio_state *prv = (struct tdaio_state *)dd->private;
+ if (!prv->iocb_queued)
+ return 0;
+
ret = io_submit(prv->aio_ctx, prv->iocb_queued, prv->iocb_queue);
/* XXX: TODO: Handle error conditions here. */
@@ -324,12 +330,13 @@ int tdaio_do_callbacks(struct disk_driver *dd, int sid)
return rsp;
}
-int tdaio_has_parent(struct disk_driver *dd)
+int tdaio_get_parent_id(struct disk_driver *dd, struct disk_id *id)
{
- return 0;
+ return TD_NO_PARENT;
}
-int tdaio_get_parent(struct disk_driver *dd, struct disk_driver *parent)
+int tdaio_validate_parent(struct disk_driver *dd,
+ struct disk_driver *parent, td_flag_t flags)
{
return -EINVAL;
}
@@ -341,8 +348,8 @@ struct tap_disk tapdisk_aio = {
.td_queue_read = tdaio_queue_read,
.td_queue_write = tdaio_queue_write,
.td_submit = tdaio_submit,
- .td_has_parent = tdaio_has_parent,
- .td_get_parent = tdaio_get_parent,
.td_close = tdaio_close,
.td_do_callbacks = tdaio_do_callbacks,
+ .td_get_parent_id = tdaio_get_parent_id,
+ .td_validate_parent = tdaio_validate_parent
};
diff --git a/tools/blktap/drivers/block-qcow.c b/tools/blktap/drivers/block-qcow.c
index 2859b08829..185c670111 100644
--- a/tools/blktap/drivers/block-qcow.c
+++ b/tools/blktap/drivers/block-qcow.c
@@ -209,23 +209,6 @@ static int init_aio_state(struct disk_driver *dd)
return -1;
}
-/*
- *Test if block is zero.
- * Return:
- * 1 for TRUE
- * 0 for FALSE
- */
-static inline int IS_ZERO(char *buf, int len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- /*if not zero, return false*/
- if (ZERO_TEST(*(buf + i))) return 0;
- }
- return 1;
-}
-
static uint32_t gen_cksum(char *ptr, int len)
{
unsigned char *md;
@@ -825,9 +808,9 @@ static inline void init_fds(struct disk_driver *dd)
}
/* Open the disk file and initialize qcow state. */
-int tdqcow_open (struct disk_driver *dd, const char *name)
+int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flags)
{
- int fd, len, i, shift, ret, size, l1_table_size;
+ int fd, len, i, shift, ret, size, l1_table_size, o_flags;
struct td_state *bs = dd->td_state;
struct tdqcow_state *s = (struct tdqcow_state *)dd->private;
char *buf;
@@ -838,7 +821,9 @@ int tdqcow_open (struct disk_driver *dd, const char *name)
DPRINTF("QCOW: Opening %s\n",name);
- fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE);
+ o_flags = O_DIRECT | O_LARGEFILE |
+ ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR);
+ fd = open(name, o_flags);
if (fd < 0) {
DPRINTF("Unable to open %s (%d)\n",name,0 - errno);
return -1;
@@ -1016,7 +1001,8 @@ int tdqcow_queue_read(struct disk_driver *dd, uint64_t sector,
* as busy and try again later */
return cb(dd, -EBUSY, sector + n,
nb_sectors - n, id, private);
- } else rsp += ret;
+ } else
+ rsp += ret;
} else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
aio_unlock(s, sector);
if (decompress_cluster(s, cluster_offset) < 0) {
@@ -1403,21 +1389,15 @@ int qcow_compress_cluster(struct tdqcow_state *s, int64_t sector_num,
return 0;
}
-int tdqcow_has_parent(struct disk_driver *dd)
-{
- struct tdqcow_state *s = (struct tdqcow_state *)dd->private;
- return (s->backing_file_offset ? 1 : 0);
-}
-
-int tdqcow_get_parent(struct disk_driver *cdd, struct disk_driver *pdd)
+int tdqcow_get_parent_id(struct disk_driver *dd, struct disk_id *id)
{
off_t off;
char *buf, *filename;
- int len, secs, ret = -1;
- struct tdqcow_state *child = (struct tdqcow_state *)cdd->private;
+ int len, secs, err = -EINVAL;
+ struct tdqcow_state *child = (struct tdqcow_state *)dd->private;
if (!child->backing_file_offset)
- return -1;
+ return TD_NO_PARENT;
/* read the backing file name */
len = child->backing_file_size;
@@ -1432,14 +1412,39 @@ int tdqcow_get_parent(struct disk_driver *cdd, struct disk_driver *pdd)
if (read(child->fd, buf, secs << 9) != secs << 9)
goto out;
- filename = buf + (child->backing_file_offset - off);
- filename[len] = '\0';
+ filename = buf + (child->backing_file_offset - off);
+ filename[len] = '\0';
- /*Open backing file*/
- ret = tdqcow_open(pdd, filename);
+ id->name = strdup(filename);
+ id->drivertype = DISK_TYPE_QCOW;
+ err = 0;
out:
free(buf);
- return ret;
+ return err;
+}
+
+int tdqcow_validate_parent(struct disk_driver *child,
+ struct disk_driver *parent, td_flag_t flags)
+{
+ struct stat stats;
+ uint64_t psize, csize;
+ struct tdqcow_state *c = (struct tdqcow_state *)child->private;
+ struct tdqcow_state *p = (struct tdqcow_state *)parent->private;
+
+ if (stat(p->name, &stats))
+ return -EINVAL;
+ if (get_filesize(p->name, &psize, &stats))
+ return -EINVAL;
+
+ if (stat(c->name, &stats))
+ return -EINVAL;
+ if (get_filesize(c->name, &csize, &stats))
+ return -EINVAL;
+
+ if (csize != psize)
+ return -EINVAL;
+
+ return 0;
}
struct tap_disk tapdisk_qcow = {
@@ -1449,8 +1454,8 @@ struct tap_disk tapdisk_qcow = {
.td_queue_read = tdqcow_queue_read,
.td_queue_write = tdqcow_queue_write,
.td_submit = tdqcow_submit,
- .td_has_parent = tdqcow_has_parent,
- .td_get_parent = tdqcow_get_parent,
.td_close = tdqcow_close,
.td_do_callbacks = tdqcow_do_callbacks,
+ .td_get_parent_id = tdqcow_get_parent_id,
+ .td_validate_parent = tdqcow_validate_parent
};
diff --git a/tools/blktap/drivers/block-ram.c b/tools/blktap/drivers/block-ram.c
index c23dd6b27e..3b4ef7ceb5 100644
--- a/tools/blktap/drivers/block-ram.c
+++ b/tools/blktap/drivers/block-ram.c
@@ -135,11 +135,11 @@ static inline void init_fds(struct disk_driver *dd)
}
/* Open the disk file and initialize ram state. */
-int tdram_open (struct disk_driver *dd, const char *name)
+int tdram_open (struct disk_driver *dd, const char *name, td_flag_t flags)
{
char *p;
uint64_t size;
- int i, fd, ret = 0, count = 0;
+ int i, fd, ret = 0, count = 0, o_flags;
struct td_state *s = dd->td_state;
struct tdram_state *prv = (struct tdram_state *)dd->private;
@@ -167,12 +167,15 @@ int tdram_open (struct disk_driver *dd, const char *name)
}
/* Open the file */
- fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE);
+ o_flags = O_DIRECT | O_LARGEFILE |
+ ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR);
+ fd = open(name, o_flags);
if ((fd == -1) && (errno == EINVAL)) {
/* Maybe O_DIRECT isn't supported. */
- fd = open(name, O_RDWR | O_LARGEFILE);
+ o_flags &= ~O_DIRECT;
+ fd = open(name, o_flags);
if (fd != -1) DPRINTF("WARNING: Accessing image without"
"O_DIRECT! (%s)\n", name);
@@ -275,12 +278,13 @@ int tdram_do_callbacks(struct disk_driver *dd, int sid)
return 1;
}
-int tdram_has_parent(struct disk_driver *dd)
+int tdram_get_parent_id(struct disk_driver *dd, struct disk_id *id)
{
- return 0;
+ return TD_NO_PARENT;
}
-int tdram_get_parent(struct disk_driver *dd, struct disk_driver *parent)
+int tdram_validate_parent(struct disk_driver *dd,
+ struct disk_driver *parent, td_flag_t flags)
{
return -EINVAL;
}
@@ -292,8 +296,8 @@ struct tap_disk tapdisk_ram = {
.td_queue_read = tdram_queue_read,
.td_queue_write = tdram_queue_write,
.td_submit = tdram_submit,
- .td_has_parent = tdram_has_parent,
- .td_get_parent = tdram_get_parent,
.td_close = tdram_close,
.td_do_callbacks = tdram_do_callbacks,
+ .td_get_parent_id = tdram_get_parent_id,
+ .td_validate_parent = tdram_validate_parent
};
diff --git a/tools/blktap/drivers/block-sync.c b/tools/blktap/drivers/block-sync.c
index 367eb70ab9..74f77d6f61 100644
--- a/tools/blktap/drivers/block-sync.c
+++ b/tools/blktap/drivers/block-sync.c
@@ -118,9 +118,9 @@ static inline void init_fds(struct disk_driver *dd)
}
/* Open the disk file and initialize aio state. */
-int tdsync_open (struct disk_driver *dd, const char *name)
+int tdsync_open (struct disk_driver *dd, const char *name, td_flag_t flags)
{
- int i, fd, ret = 0;
+ int i, fd, ret = 0, o_flags;
struct td_state *s = dd->td_state;
struct tdsync_state *prv = (struct tdsync_state *)dd->private;
@@ -130,11 +130,14 @@ int tdsync_open (struct disk_driver *dd, const char *name)
return (0 - errno);
/* Open the file */
- fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE);
+ o_flags = O_DIRECT | O_LARGEFILE |
+ ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR);
+ fd = open(name, o_flags);
if ( (fd == -1) && (errno == EINVAL) ) {
/* Maybe O_DIRECT isn't supported. */
+ o_flags &= ~O_DIRECT;
fd = open(name, O_RDWR | O_LARGEFILE);
if (fd != -1) DPRINTF("WARNING: Accessing image without"
"O_DIRECT! (%s)\n", name);
@@ -223,12 +226,13 @@ int tdsync_do_callbacks(struct disk_driver *dd, int sid)
return 1;
}
-int tdsync_has_parent(struct disk_driver *dd)
+int tdsync_get_parent_id(struct disk_driver *dd, struct disk_id *id)
{
- return 0;
+ return TD_NO_PARENT;
}
-int tdsync_get_parent(struct disk_driver *dd, struct disk_driver *parent)
+int tdsync_validate_parent(struct disk_driver *dd,
+ struct disk_driver *parent, td_flag_t flags)
{
return -EINVAL;
}
@@ -240,8 +244,8 @@ struct tap_disk tapdisk_sync = {
.td_queue_read = tdsync_queue_read,
.td_queue_write = tdsync_queue_write,
.td_submit = tdsync_submit,
- .td_has_parent = tdsync_has_parent,
- .td_get_parent = tdsync_get_parent,
.td_close = tdsync_close,
.td_do_callbacks = tdsync_do_callbacks,
+ .td_get_parent_id = tdsync_get_parent_id,
+ .td_validate_parent = tdsync_validate_parent
};
diff --git a/tools/blktap/drivers/block-vmdk.c b/tools/blktap/drivers/block-vmdk.c
index 5a6a5ca775..4ab88373ea 100644
--- a/tools/blktap/drivers/block-vmdk.c
+++ b/tools/blktap/drivers/block-vmdk.c
@@ -119,10 +119,11 @@ static inline void init_fds(struct disk_driver *dd)
}
/* Open the disk file and initialize aio state. */
-static int tdvmdk_open (struct disk_driver *dd, const char *name)
+static int tdvmdk_open (struct disk_driver *dd,
+ const char *name, td_flag_t flags)
{
int ret, fd;
- int l1_size, i;
+ int l1_size, i, o_flags;
uint32_t magic;
struct td_state *s = dd->td_state;
struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private;
@@ -133,12 +134,15 @@ static int tdvmdk_open (struct disk_driver *dd, const char *name)
return -1;
/* Open the file */
- fd = open(name, O_RDWR | O_LARGEFILE);
+ o_flags = O_DIRECT | O_LARGEFILE |
+ ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR);
+ fd = open(name, o_flags);
if ( (fd == -1) && (errno == EINVAL) ) {
/* Maybe O_DIRECT isn't supported. */
- fd = open(name, O_RDWR | O_LARGEFILE);
+ o_flags &= ~O_DIRECT;
+ fd = open(name, o_flags);
if (fd != -1) DPRINTF("WARNING: Accessing image without"
"O_DIRECT! (%s)\n", name);
@@ -394,12 +398,13 @@ static int tdvmdk_do_callbacks(struct disk_driver *dd, int sid)
return 1;
}
-static int tdvmdk_has_parent(struct disk_driver *dd)
+static int tdvmdk_get_parent_id(struct disk_driver *dd, struct disk_id *id)
{
- return 0;
+ return TD_NO_PARENT;
}
-static int tdvmdk_get_parent(struct disk_driver *dd, struct disk_driver *parent)
+static int tdvmdk_validate_parent(struct disk_driver *dd,
+ struct disk_driver *parent, td_flag_t flags)
{
return -EINVAL;
}
@@ -411,8 +416,8 @@ struct tap_disk tapdisk_vmdk = {
.td_queue_read = tdvmdk_queue_read,
.td_queue_write = tdvmdk_queue_write,
.td_submit = tdvmdk_submit,
- .td_has_parent = tdvmdk_has_parent,
- .td_get_parent = tdvmdk_get_parent,
.td_close = tdvmdk_close,
.td_do_callbacks = tdvmdk_do_callbacks,
+ .td_get_parent_id = tdvmdk_get_parent_id,
+ .td_validate_parent = tdvmdk_validate_parent
};
diff --git a/tools/blktap/drivers/img2qcow.c b/tools/blktap/drivers/img2qcow.c
index 7baf28fb02..926cf2742e 100644
--- a/tools/blktap/drivers/img2qcow.c
+++ b/tools/blktap/drivers/img2qcow.c
@@ -201,7 +201,7 @@ int main(int argc, char *argv[])
dd.private = malloc(dd.drv->private_data_size);
/*Open qcow file*/
- if (dd.drv->td_open(&dd, argv[1])!=0) {
+ if (dd.drv->td_open(&dd, argv[1], 0)!=0) {
DFPRINTF("Unable to open Qcow file [%s]\n",argv[1]);
exit(-1);
}
diff --git a/tools/blktap/drivers/qcow2raw.c b/tools/blktap/drivers/qcow2raw.c
index 8adf573309..55ae4ad108 100644
--- a/tools/blktap/drivers/qcow2raw.c
+++ b/tools/blktap/drivers/qcow2raw.c
@@ -169,7 +169,7 @@ int main(int argc, char *argv[])
ddqcow.drv = &tapdisk_qcow;
ddqcow.private = malloc(ddqcow.drv->private_data_size);
- if (ddqcow.drv->td_open(&ddqcow, argv[2])!=0) {
+ if (ddqcow.drv->td_open(&ddqcow, argv[2], TD_RDONLY)!=0) {
DFPRINTF("Unable to open Qcow file [%s]\n",argv[2]);
exit(-1);
} else DFPRINTF("QCOW file opened, size %llu\n",
@@ -270,7 +270,7 @@ int main(int argc, char *argv[])
ddaio.drv = &tapdisk_aio;
ddaio.private = malloc(ddaio.drv->private_data_size);
- if (ddaio.drv->td_open(&ddaio, argv[1])!=0) {
+ if (ddaio.drv->td_open(&ddaio, argv[1], 0)!=0) {
DFPRINTF("Unable to open Qcow file [%s]\n", argv[1]);
exit(-1);
}
diff --git a/tools/blktap/drivers/tapdisk.c b/tools/blktap/drivers/tapdisk.c
index 6215770d97..43a037a053 100644
--- a/tools/blktap/drivers/tapdisk.c
+++ b/tools/blktap/drivers/tapdisk.c
@@ -81,6 +81,15 @@ void daemonize(void)
return;
}
+static void free_driver(struct disk_driver *d)
+{
+ if (d->name)
+ free(d->name);
+ if (d->private)
+ free(d->private);
+ free(d);
+}
+
static void unmap_disk(struct td_state *s)
{
tapdev_info_t *info = s->ring_info;
@@ -91,8 +100,7 @@ static void unmap_disk(struct td_state *s)
while (dd) {
tmp = dd->next;
dd->drv->td_close(dd);
- free(dd->private);
- free(dd);
+ free_driver(dd);
dd = tmp;
}
@@ -112,7 +120,6 @@ static void unmap_disk(struct td_state *s)
free(s);
return;
-
}
void sig_handler(int sig)
@@ -205,26 +212,6 @@ static struct td_state *state_init(void)
return s;
}
-static struct disk_driver *disk_init(struct td_state *s, struct tap_disk *drv)
-{
- struct disk_driver *dd;
-
- dd = calloc(1, sizeof(struct disk_driver));
- if (!dd)
- return NULL;
-
- dd->private = malloc(drv->private_data_size);
- if (!dd->private) {
- free(dd);
- return NULL;
- }
-
- dd->drv = drv;
- dd->td_state = s;
-
- return dd;
-}
-
static int map_new_dev(struct td_state *s, int minor)
{
int tap_fd;
@@ -280,49 +267,94 @@ static int map_new_dev(struct td_state *s, int minor)
return -1;
}
-static int open_disk(struct td_state *s, struct disk_driver *dd, char *path)
+static struct disk_driver *disk_init(struct td_state *s,
+ struct tap_disk *drv, char *name)
+{
+ struct disk_driver *dd;
+
+ dd = calloc(1, sizeof(struct disk_driver));
+ if (!dd)
+ return NULL;
+
+ dd->private = malloc(drv->private_data_size);
+ if (!dd->private) {
+ free(dd);
+ return NULL;
+ }
+
+ dd->drv = drv;
+ dd->td_state = s;
+ dd->name = name;
+
+ return dd;
+}
+
+static int open_disk(struct td_state *s, struct tap_disk *drv, char *path)
{
int err;
- struct disk_driver *d = dd;
+ char *dup;
+ struct disk_id id;
+ struct disk_driver *d;
+
+ dup = strdup(path);
+ if (!dup)
+ return -ENOMEM;
- err = dd->drv->td_open(dd, path);
+ memset(&id, 0, sizeof(struct disk_id));
+ s->disks = d = disk_init(s, drv, dup);
+ if (!d)
+ return -ENOMEM;
+
+ err = drv->td_open(d, path, 0);
if (err)
- return err;
+ goto fail;
/* load backing files as necessary */
- while (d->drv->td_has_parent(d)) {
+ while ((err = d->drv->td_get_parent_id(d, &id)) == 0) {
struct disk_driver *new;
- new = calloc(1, sizeof(struct disk_driver));
- if (!new)
+ if (id.drivertype > MAX_DISK_TYPES ||
+ !get_driver(id.drivertype) || !id.name)
goto fail;
- new->drv = d->drv;
- new->td_state = s;
- new->private = malloc(new->drv->private_data_size);
- if (!new->private) {
- free(new);
+
+ dup = strdup(id.name);
+ if (!dup)
goto fail;
- }
-
- err = d->drv->td_get_parent(d, new);
+
+ new = disk_init(s, get_driver(id.drivertype), dup);
+ if (!new)
+ goto fail;
+
+ err = new->drv->td_open(new, new->name, TD_RDONLY);
if (err)
goto fail;
+ err = d->drv->td_validate_parent(d, new, 0);
+ if (err) {
+ d->next = new;
+ goto fail;
+ }
+
d = d->next = new;
+ free(id.name);
}
- return 0;
+ if (err >= 0)
+ return 0;
fail:
DPRINTF("failed opening disk\n");
- while (dd) {
- d = dd->next;
- dd->drv->td_close(dd);
- free(dd->private);
- free(dd);
- dd = d;
+ if (id.name)
+ free(id.name);
+ d = s->disks;
+ while (d) {
+ struct disk_driver *tmp = d->next;
+ d->drv->td_close(d);
+ free_driver(d);
+ d = tmp;
}
- return err;
+ s->disks = NULL;
+ return -1;
}
static int read_msg(char *buf)
@@ -334,7 +366,6 @@ static int read_msg(char *buf)
msg_newdev_t *msg_dev;
msg_pid_t *msg_pid;
struct tap_disk *drv;
- struct disk_driver *dd;
int ret = -1;
struct td_state *s = NULL;
fd_list_entry_t *entry;
@@ -369,14 +400,8 @@ static int read_msg(char *buf)
if (s == NULL)
goto params_done;
- s->disks = dd = disk_init(s, drv);
- if (!dd) {
- free(s);
- goto params_done;
- }
-
/*Open file*/
- ret = open_disk(s, dd, path);
+ ret = open_disk(s, drv, path);
if (ret)
goto params_done;
@@ -785,6 +810,19 @@ int main(int argc, char *argv[])
}
}
+ /* completed io from above may have
+ * queued new requests on chained disks */
+ if (progress_made) {
+ td_for_each_disk(ptr->s, dd) {
+ dd->early +=
+ dd->drv->td_submit(dd);
+ if (dd->early > 0) {
+ io_done(dd, 10);
+ dd->early = 0;
+ }
+ }
+ }
+
if (FD_ISSET(ptr->tap_fd, &readfds) ||
(info->busy.req && progress_made))
get_io_request(ptr->s);
diff --git a/tools/blktap/drivers/tapdisk.h b/tools/blktap/drivers/tapdisk.h
index 7b03fa0762..b76d46cce5 100644
--- a/tools/blktap/drivers/tapdisk.h
+++ b/tools/blktap/drivers/tapdisk.h
@@ -42,10 +42,15 @@
*
* - The fd used for poll is an otherwise unused pipe, which allows poll to
* be safely called without ever returning anything.
- *
+ *
* NOTE: tapdisk uses the number of sectors submitted per request as a
* ref count. Plugins must use the callback function to communicate the
* completion--or error--of every sector submitted to them.
+ *
+ * td_get_parent_id returns:
+ * 0 if parent id successfully retrieved
+ * TD_NO_PARENT if no parent exists
+ * -errno on error
*/
#ifndef TAPDISK_H_
@@ -71,12 +76,23 @@
#define MAX_IOFD 2
#define BLK_NOT_ALLOCATED 99
+#define TD_NO_PARENT 1
+
+typedef uint32_t td_flag_t;
+
+#define TD_RDONLY 1
struct td_state;
struct tap_disk;
+struct disk_id {
+ char *name;
+ int drivertype;
+};
+
struct disk_driver {
int early;
+ char *name;
void *private;
int io_fd[MAX_IOFD];
struct tap_disk *drv;
@@ -105,18 +121,20 @@ typedef int (*td_callback_t)(struct disk_driver *dd, int res, uint64_t sector,
struct tap_disk {
const char *disk_type;
int private_data_size;
- int (*td_open) (struct disk_driver *dd, const char *name);
- int (*td_queue_read) (struct disk_driver *dd, uint64_t sector,
- int nb_sectors, char *buf, td_callback_t cb,
- int id, void *prv);
- int (*td_queue_write) (struct disk_driver *dd, uint64_t sector,
- int nb_sectors, char *buf, td_callback_t cb,
- int id, void *prv);
- int (*td_submit) (struct disk_driver *dd);
- int (*td_has_parent) (struct disk_driver *dd);
- int (*td_get_parent) (struct disk_driver *dd, struct disk_driver *p);
- int (*td_close) (struct disk_driver *dd);
- int (*td_do_callbacks)(struct disk_driver *dd, int sid);
+ int (*td_open) (struct disk_driver *dd,
+ const char *name, td_flag_t flags);
+ int (*td_queue_read) (struct disk_driver *dd, uint64_t sector,
+ int nb_sectors, char *buf, td_callback_t cb,
+ int id, void *prv);
+ int (*td_queue_write) (struct disk_driver *dd, uint64_t sector,
+ int nb_sectors, char *buf, td_callback_t cb,
+ int id, void *prv);
+ int (*td_submit) (struct disk_driver *dd);
+ int (*td_close) (struct disk_driver *dd);
+ int (*td_do_callbacks) (struct disk_driver *dd, int sid);
+ int (*td_get_parent_id) (struct disk_driver *dd, struct disk_id *id);
+ int (*td_validate_parent)(struct disk_driver *dd,
+ struct disk_driver *p, td_flag_t flags);
};
typedef struct disk_info {