mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Merge with xen-ia64-unstable.hg.
This commit is contained in:
commit
aa700ae4e2
20 files changed
+338
-169
No files matched your search
@@ -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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
err = dd->drv->td_open(dd, path);
|
||||
dup = strdup(path);
|
||||
if (!dup)
|
||||
return -ENOMEM;
|
||||
|
||||
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 (id.drivertype > MAX_DISK_TYPES ||
|
||||
!get_driver(id.drivertype) || !id.name)
|
||||
goto fail;
|
||||
|
||||
dup = strdup(id.name);
|
||||
if (!dup)
|
||||
goto fail;
|
||||
|
||||
new = disk_init(s, get_driver(id.drivertype), dup);
|
||||
if (!new)
|
||||
goto fail;
|
||||
new->drv = d->drv;
|
||||
new->td_state = s;
|
||||
new->private = malloc(new->drv->private_data_size);
|
||||
if (!new->private) {
|
||||
free(new);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = d->drv->td_get_parent(d, new);
|
||||
|
||||
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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -982,6 +982,12 @@ static void svm_hvm_inject_exception(
|
||||
v->arch.hvm_svm.vmcb->cr2 = v->arch.hvm_svm.cpu_cr2 = cr2;
|
||||
}
|
||||
|
||||
static int svm_event_injection_faulted(struct vcpu *v)
|
||||
{
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
return vmcb->exitintinfo.fields.v;
|
||||
}
|
||||
|
||||
int start_svm(void)
|
||||
{
|
||||
u32 eax, ecx, edx;
|
||||
@@ -1058,6 +1064,8 @@ int start_svm(void)
|
||||
hvm_funcs.init_ap_context = svm_init_ap_context;
|
||||
hvm_funcs.init_hypercall_page = svm_init_hypercall_page;
|
||||
|
||||
hvm_funcs.event_injection_faulted = svm_event_injection_faulted;
|
||||
|
||||
hvm_enable();
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -990,6 +990,16 @@ static void vmx_update_vtpr(struct vcpu *v, unsigned long value)
|
||||
/* VMX doesn't have a V_TPR field */
|
||||
}
|
||||
|
||||
static int vmx_event_injection_faulted(struct vcpu *v)
|
||||
{
|
||||
unsigned int idtv_info_field;
|
||||
|
||||
ASSERT(v == current);
|
||||
|
||||
idtv_info_field = __vmread(IDT_VECTORING_INFO_FIELD);
|
||||
return (idtv_info_field & INTR_INFO_VALID_MASK);
|
||||
}
|
||||
|
||||
/* Setup HVM interfaces */
|
||||
static void vmx_setup_hvm_funcs(void)
|
||||
{
|
||||
@@ -1025,6 +1035,8 @@ static void vmx_setup_hvm_funcs(void)
|
||||
hvm_funcs.init_ap_context = vmx_init_ap_context;
|
||||
|
||||
hvm_funcs.init_hypercall_page = vmx_init_hypercall_page;
|
||||
|
||||
hvm_funcs.event_injection_faulted = vmx_event_injection_faulted;
|
||||
}
|
||||
|
||||
int start_vmx(void)
|
||||
|
||||
@@ -275,6 +275,10 @@ hvm_emulate_write(enum x86_segment seg,
|
||||
unsigned long addr;
|
||||
int rc;
|
||||
|
||||
/* How many emulations could we save if we unshadowed on stack writes? */
|
||||
if ( seg == x86_seg_ss )
|
||||
perfc_incrc(shadow_fault_emulate_stack);
|
||||
|
||||
rc = hvm_translate_linear_addr(
|
||||
seg, offset, bytes, hvm_access_write, sh_ctxt, &addr);
|
||||
if ( rc )
|
||||
|
||||
@@ -2901,8 +2901,28 @@ static int sh_page_fault(struct vcpu *v,
|
||||
goto not_a_shadow_fault;
|
||||
|
||||
if ( is_hvm_domain(d) )
|
||||
{
|
||||
/*
|
||||
* If we are in the middle of injecting an exception or interrupt then
|
||||
* we should not emulate: it is not the instruction at %eip that caused
|
||||
* the fault. Furthermore it is almost certainly the case the handler
|
||||
* stack is currently considered to be a page table, so we should
|
||||
* unshadow the faulting page before exiting.
|
||||
*/
|
||||
if ( unlikely(hvm_event_injection_faulted(v)) )
|
||||
{
|
||||
gdprintk(XENLOG_DEBUG, "write to pagetable during event "
|
||||
"injection: cr2=%#lx, mfn=%#lx\n",
|
||||
va, mfn_x(gmfn));
|
||||
sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */);
|
||||
goto done;
|
||||
}
|
||||
|
||||
hvm_store_cpu_guest_regs(v, regs, NULL);
|
||||
SHADOW_PRINTK("emulate: eip=%#lx\n", (unsigned long)regs->eip);
|
||||
}
|
||||
|
||||
SHADOW_PRINTK("emulate: eip=%#lx esp=%#lx\n",
|
||||
(unsigned long)regs->eip, (unsigned long)regs->esp);
|
||||
|
||||
emul_ops = shadow_init_emulation(&emul_ctxt, regs);
|
||||
|
||||
|
||||
@@ -476,7 +476,7 @@ void __init __start_xen(multiboot_info_t *mbi)
|
||||
s = initial_images_end;
|
||||
init_boot_pages(s, e);
|
||||
|
||||
#if defined (CONFIG_X86_64)
|
||||
#if defined(CONFIG_X86_64)
|
||||
/*
|
||||
* x86/64 maps all registered RAM. Points to note:
|
||||
* 1. The initial pagetable already maps low 1GB, so skip that.
|
||||
@@ -508,7 +508,6 @@ void __init __start_xen(multiboot_info_t *mbi)
|
||||
unsigned long kdump_start, kdump_size, k;
|
||||
|
||||
/* Mark images pages as free for now. */
|
||||
|
||||
init_boot_pages(initial_images_start, initial_images_end);
|
||||
|
||||
kdump_start = kexec_crash_area.start;
|
||||
@@ -526,17 +525,19 @@ void __init __start_xen(multiboot_info_t *mbi)
|
||||
kdump_size >>= PAGE_SHIFT;
|
||||
|
||||
/* Allocate pages for Kdump memory area. */
|
||||
|
||||
k = alloc_boot_pages_at(kdump_size, kdump_start);
|
||||
if ( k != kdump_start )
|
||||
if ( !reserve_boot_pages(kdump_start, kdump_size) )
|
||||
panic("Unable to reserve Kdump memory\n");
|
||||
|
||||
/* Allocate pages for relocated initial images. */
|
||||
|
||||
k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0;
|
||||
k += (initial_images_end - initial_images_start) >> PAGE_SHIFT;
|
||||
|
||||
#if defined(CONFIG_X86_32)
|
||||
/* Must allocate within bootstrap 1:1 limits. */
|
||||
k = alloc_boot_low_pages(k, 1); /* 0x0 - HYPERVISOR_VIRT_START */
|
||||
#else
|
||||
k = alloc_boot_pages(k, 1);
|
||||
#endif
|
||||
if ( k == 0 )
|
||||
panic("Unable to allocate initial images memory\n");
|
||||
|
||||
|
||||
@@ -44,7 +44,8 @@ struct page_info *alloc_xen_pagetable(void)
|
||||
if ( !early_boot )
|
||||
return alloc_domheap_page(NULL);
|
||||
|
||||
pfn = alloc_boot_pages(1, 1);
|
||||
/* Early pagetables must come from low 1GB of memory. */
|
||||
pfn = alloc_boot_low_pages(1, 1); /* 0x0 - 0x40000000 */
|
||||
return ((pfn == 0) ? NULL : mfn_to_page(pfn));
|
||||
}
|
||||
|
||||
|
||||
+46
-16
@@ -95,9 +95,10 @@ static unsigned long scrub_pages;
|
||||
static unsigned long *alloc_bitmap;
|
||||
#define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8)
|
||||
|
||||
#define allocated_in_map(_pn) \
|
||||
( !! (alloc_bitmap[(_pn)/PAGES_PER_MAPWORD] & \
|
||||
(1UL<<((_pn)&(PAGES_PER_MAPWORD-1)))) )
|
||||
#define allocated_in_map(_pn) \
|
||||
({ unsigned long ___pn = (_pn); \
|
||||
!!(alloc_bitmap[___pn/PAGES_PER_MAPWORD] & \
|
||||
(1UL<<(___pn&(PAGES_PER_MAPWORD-1)))); })
|
||||
|
||||
/*
|
||||
* Hint regarding bitwise arithmetic in map_{alloc,free}:
|
||||
@@ -240,36 +241,65 @@ void init_boot_pages(paddr_t ps, paddr_t pe)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at)
|
||||
int reserve_boot_pages(unsigned long first_pfn, unsigned long nr_pfns)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for ( i = 0; i < nr_pfns; i++ )
|
||||
if ( allocated_in_map(pfn_at + i) )
|
||||
if ( allocated_in_map(first_pfn + i) )
|
||||
break;
|
||||
|
||||
if ( i == nr_pfns )
|
||||
if ( i != nr_pfns )
|
||||
return 0;
|
||||
|
||||
map_alloc(first_pfn, nr_pfns);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long alloc_boot_low_pages(
|
||||
unsigned long nr_pfns, unsigned long pfn_align)
|
||||
{
|
||||
unsigned long pg, i;
|
||||
|
||||
/* Search forwards to obtain lowest available range. */
|
||||
for ( pg = first_valid_mfn & ~(pfn_align-1);
|
||||
(pg + nr_pfns) < max_page;
|
||||
pg = (pg + i + pfn_align - 1) & ~(pfn_align - 1) )
|
||||
{
|
||||
map_alloc(pfn_at, nr_pfns);
|
||||
return pfn_at;
|
||||
for ( i = 0; i < nr_pfns; i++ )
|
||||
if ( allocated_in_map(pg+i) )
|
||||
break;
|
||||
if ( i == nr_pfns )
|
||||
{
|
||||
map_alloc(pg, nr_pfns);
|
||||
return pg;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
|
||||
unsigned long alloc_boot_pages(
|
||||
unsigned long nr_pfns, unsigned long pfn_align)
|
||||
{
|
||||
unsigned long pg;
|
||||
unsigned long pg, i;
|
||||
|
||||
pg = first_valid_mfn & ~(pfn_align-1);
|
||||
while ( (pg + nr_pfns) < max_page )
|
||||
/* Search backwards to obtain highest available range. */
|
||||
for ( pg = (max_page - nr_pfns) & ~(pfn_align - 1);
|
||||
pg >= first_valid_mfn;
|
||||
pg = (pg + i - nr_pfns) & ~(pfn_align - 1) )
|
||||
{
|
||||
if ( alloc_boot_pages_at(nr_pfns, pg) != 0 )
|
||||
break;
|
||||
pg += pfn_align;
|
||||
for ( i = 0; i < nr_pfns; i++ )
|
||||
if ( allocated_in_map(pg+i) )
|
||||
break;
|
||||
if ( i == nr_pfns )
|
||||
{
|
||||
map_alloc(pg, nr_pfns);
|
||||
return pg;
|
||||
}
|
||||
}
|
||||
|
||||
return pg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -134,6 +134,8 @@ struct hvm_function_table {
|
||||
int vcpuid, int trampoline_vector);
|
||||
|
||||
void (*init_hypercall_page)(struct domain *d, void *hypercall_page);
|
||||
|
||||
int (*event_injection_faulted)(struct vcpu *v);
|
||||
};
|
||||
|
||||
extern struct hvm_function_table hvm_funcs;
|
||||
@@ -262,4 +264,9 @@ hvm_inject_exception(unsigned int trapnr, int errcode, unsigned long cr2)
|
||||
|
||||
int hvm_bringup_ap(int vcpuid, int trampoline_vector);
|
||||
|
||||
static inline int hvm_event_injection_faulted(struct vcpu *v)
|
||||
{
|
||||
return hvm_funcs.event_injection_faulted(v);
|
||||
}
|
||||
|
||||
#endif /* __ASM_X86_HVM_HVM_H__ */
|
||||
@@ -56,6 +56,7 @@ PERFCOUNTER_CPU(shadow_fault_bail_user_supervisor,
|
||||
PERFCOUNTER_CPU(shadow_fault_emulate_read, "shadow_fault emulates a read")
|
||||
PERFCOUNTER_CPU(shadow_fault_emulate_write, "shadow_fault emulates a write")
|
||||
PERFCOUNTER_CPU(shadow_fault_emulate_failed, "shadow_fault emulator fails")
|
||||
PERFCOUNTER_CPU(shadow_fault_emulate_stack, "shadow_fault emulate stack write")
|
||||
PERFCOUNTER_CPU(shadow_fault_mmio, "shadow_fault handled as mmio")
|
||||
PERFCOUNTER_CPU(shadow_fault_fixed, "shadow_fault fixed fault")
|
||||
PERFCOUNTER_CPU(shadow_ptwr_emulate, "shadow causes ptwr to emulate")
|
||||
|
||||
@@ -39,8 +39,11 @@ struct page_info;
|
||||
/* Boot-time allocator. Turns into generic allocator after bootstrap. */
|
||||
paddr_t init_boot_allocator(paddr_t bitmap_start);
|
||||
void init_boot_pages(paddr_t ps, paddr_t pe);
|
||||
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align);
|
||||
unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at);
|
||||
unsigned long alloc_boot_pages(
|
||||
unsigned long nr_pfns, unsigned long pfn_align);
|
||||
unsigned long alloc_boot_low_pages(
|
||||
unsigned long nr_pfns, unsigned long pfn_align);
|
||||
int reserve_boot_pages(unsigned long first_pfn, unsigned long nr_pfns);
|
||||
void end_boot_allocator(void);
|
||||
|
||||
/* Generic allocator. These functions are *not* interrupt-safe. */
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifdef PERF_COUNTERS
|
||||
|
||||
#include <xen/lib.h>
|
||||
#include <xen/smp.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
/*
|
||||
|
||||