This will allow us to map and then unlink the file and therefore
delete the process on process exit or explicit unmap.
Using the mmaped versions of these files required rewriting build_pv
to use the xc_dom builder functionality directly rather than through
the xc_linux_build "compatibility layer". (The status of the
xc_linux_build interface as a compatibility layer seems a bit dubious
since all existing callers use it but if anything is going to replace
it then libxl seems like the likely candidate).
I'm not thrilled with the definition of the maps lifecycle. This could
be solved by adding a helper function to explicitly free the toplevel
structure.
Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
diff -r bcea013ddd5a -r 2d4475143f70 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c Mon Jul 12 14:56:37 2010 +0100
+++ b/tools/libxl/libxl.c Mon Jul 12 14:56:37 2010 +0100
@@ -22,6 +22,7 @@
#include <sys/types.h>
#include <fcntl.h>
#include <sys/select.h>
+#include <sys/mman.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h> /* for write, unlink and close */
@@ -291,12 +292,12 @@
vments[i++] = "image/ostype";
vments[i++] = "linux";
vments[i++] = "image/kernel";
- vments[i++] = (char*) info->kernel;
+ vments[i++] = (char*) info->kernel.path;
vments[i++] = "start_time";
vments[i++] = libxl_sprintf(ctx, "%lu.%02d",
start_time.tv_sec,(int)start_time.tv_usec/10000);
- if (info->u.pv.ramdisk) {
+ if (info->u.pv.ramdisk.path) {
vments[i++] = "image/ramdisk";
- vments[i++] = (char*) info->u.pv.ramdisk;
+ vments[i++] = (char*) info->u.pv.ramdisk.path;
}
if (info->u.pv.cmdline) {
vments[i++] = "image/cmdline";
@@ -305,6 +306,10 @@
}
ret = build_post(ctx, domid, info, state, vments, localents);
out:
+ libxl_file_reference_unmap(ctx, &info->kernel);
+ if (!info->hvm)
+ libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
+
return ret;
}
@@ -338,12 +343,12 @@
vments[i++] = "image/ostype";
vments[i++] = "linux";
vments[i++] = "image/kernel";
- vments[i++] = (char*) info->kernel;
+ vments[i++] = (char*) info->kernel.path;
vments[i++] = "start_time";
vments[i++] = libxl_sprintf(ctx, "%lu.%02d",
start_time.tv_sec,(int)start_time.tv_usec/10000);
- if (info->u.pv.ramdisk) {
+ if (info->u.pv.ramdisk.path) {
vments[i++] = "image/ramdisk";
- vments[i++] = (char*) info->u.pv.ramdisk;
+ vments[i++] = (char*) info->u.pv.ramdisk.path;
}
if (info->u.pv.cmdline) {
vments[i++] = "image/cmdline";
@@ -361,6 +366,10 @@
}
out:
+ libxl_file_reference_unmap(ctx, &info->kernel);
+ if (!info->hvm)
+ libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
+
esave = errno;
flags = fcntl(fd, F_GETFL);
@@ -1057,9 +1066,9 @@
b_info.max_vcpus = 1;
b_info.max_memkb = 32 * 1024;
b_info.target_memkb = b_info.max_memkb;
- b_info.kernel = libxl_abs_path(ctx, "ioemu-stubdom.gz",
libxl_xenfirmwaredir_path());
+ b_info.kernel.path = libxl_abs_path(ctx, "ioemu-stubdom.gz",
libxl_xenfirmwaredir_path());
b_info.u.pv.cmdline = libxl_sprintf(ctx, " -d %d", info->domid);
- b_info.u.pv.ramdisk = "";
+ b_info.u.pv.ramdisk.path = "";
b_info.u.pv.features = "";
b_info.hvm = 0;
@@ -3181,3 +3190,47 @@
return rc;
}
+int libxl_file_reference_map(struct libxl_ctx *ctx, libxl_file_reference *f)
+{
+ struct stat st_buf;
+ int ret, fd;
+ void *data;
+
+ if (f->mapped)
+ return 0;
+
+ fd = open(f->path, O_RDONLY);
+ if (f < 0)
+ return ERROR_FAIL;
+
+ ret = fstat(fd, &st_buf);
+ if (ret < 0)
+ goto out;
+
+ ret = -1;
+ data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (data == NULL)
+ goto out;
+
+ f->mapped = 1;
+ f->data = data;
+ f->size = st_buf.st_size;
+
+ ret = 0;
+out:
+ close(fd);
+
+ return ret == 0 ? 0 : ERROR_FAIL;
+}
+
+int libxl_file_reference_unmap(struct libxl_ctx *ctx, libxl_file_reference *f)
+{
+ int ret;
+
+ if (!f->mapped)
+ return 0;
+
+ ret = munmap(f->data, f->size);
+
+ return ret == 0 ? 0 : ERROR_FAIL;
+}
diff -r bcea013ddd5a -r 2d4475143f70 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h Mon Jul 12 14:56:37 2010 +0100
+++ b/tools/libxl/libxl.h Mon Jul 12 14:56:37 2010 +0100
@@ -90,6 +90,24 @@
} libxl_domain_create_info;
typedef struct {
+ /*
+ * Path is always set if the file refernece is valid. However if
+ * mapped is true then the actual file may already be unlinked.
+ */
+ char *path;
+ int mapped;
+ void *data;
+ size_t size;
+} libxl_file_reference;
+
+/*
+ * Instances of libxl_file_reference contained in this struct which
+ * have been mapped (with libxl_file_reference_map) will be unmapped
+ * by libxl_domain_build/restore. If either of these are never called
+ * then the user is responsible for calling
+ * libxl_file_reference_unmap.
+ */
+typedef struct {
int max_vcpus;
int cur_vcpus;
int tsc_mode;
@@ -98,7 +116,7 @@
uint32_t video_memkb;
uint32_t shadow_memkb;
bool disable_migrate;
- const char *kernel;
+ libxl_file_reference kernel;
int hvm;
union {
struct {
@@ -115,7 +133,7 @@
struct {
uint32_t slack_memkb;
const char *cmdline;
- const char *ramdisk;
+ libxl_file_reference ramdisk;
const char *features;
} pv;
} u;
@@ -308,6 +326,9 @@
int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req);
int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force);
+int libxl_file_reference_map(struct libxl_ctx *ctx, libxl_file_reference *f);
+int libxl_file_reference_unmap(struct libxl_ctx *ctx, libxl_file_reference *f);
+
char *libxl_uuid2string(struct libxl_ctx *ctx, uint8_t uuid[16]);
/* 0 means ERROR_ENOMEM, which we have logged */
diff -r bcea013ddd5a -r 2d4475143f70 tools/libxl/libxl_dom.c
--- a/tools/libxl/libxl_dom.c Mon Jul 12 14:56:37 2010 +0100
+++ b/tools/libxl/libxl_dom.c Mon Jul 12 14:56:37 2010 +0100
@@ -143,22 +143,76 @@
int ret;
int flags = 0;
+ xc_dom_loginit(ctx->xch);
+
dom = xc_dom_allocate(ctx->xch, info->u.pv.cmdline, info->u.pv.features);
if (!dom) {
XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_allocate failed");
- return -1;
+ return ERROR_FAIL;
}
- ret = xc_dom_linux_build(ctx->xch, dom, domid, info->target_memkb / 1024,
- info->kernel, info->u.pv.ramdisk, flags,
- state->store_port, &state->store_mfn,
- state->console_port, &state->console_mfn);
- if (ret != 0) {
- xc_dom_release(dom);
- XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "xc_dom_linux_build failed");
- return -2;
+
+ if (info->kernel.mapped) {
+ if ( (ret = xc_dom_kernel_mem(dom, info->kernel.data,
info->kernel.size)) != 0) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_kernel_mem failed");
+ goto out;
+ }
+ } else {
+ if ( (ret = xc_dom_kernel_file(dom, info->kernel.path)) != 0) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_kernel_file failed");
+ goto out;
+ }
}
+
+ if ( info->u.pv.ramdisk.path && strlen(info->u.pv.ramdisk.path) ) {
+ if (info->u.pv.ramdisk.mapped) {
+ if ( (ret = xc_dom_ramdisk_mem(dom, info->u.pv.ramdisk.data,
info->u.pv.ramdisk.size)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_ramdisk_mem failed");
+ goto out;
+ }
+ } else {
+ if ( (ret = xc_dom_ramdisk_file(dom, info->u.pv.ramdisk.path)) !=
0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_ramdisk_file failed");
+ goto out;
+ }
+ }
+ }
+
+ dom->flags = flags;
+ dom->console_evtchn = state->console_port;
+ dom->xenstore_evtchn = state->store_port;
+
+ if ( (ret = xc_dom_boot_xen_init(dom, ctx->xch, domid)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_boot_xen_init failed");
+ goto out;
+ }
+ if ( (ret = xc_dom_parse_image(dom)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_parse_image failed");
+ goto out;
+ }
+ if ( (ret = xc_dom_mem_init(dom, info->target_memkb / 1024)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_mem_init failed");
+ goto out;
+ }
+ if ( (ret = xc_dom_boot_mem_init(dom)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_boot_mem_init failed");
+ goto out;
+ }
+ if ( (ret = xc_dom_build_image(dom)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_build_image failed");
+ goto out;
+ }
+ if ( (ret = xc_dom_boot_image(dom)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_boot_image failed");
+ goto out;
+ }
+
+ state->console_mfn = xc_dom_p2m_host(dom, dom->console_pfn);
+ state->store_mfn = xc_dom_p2m_host(dom, dom->xenstore_pfn);
+
+ ret = 0;
+out:
xc_dom_release(dom);
- return 0;
+ return ret == 0 ? 0 : ERROR_FAIL;
}
int build_hvm(struct libxl_ctx *ctx, uint32_t domid,
@@ -166,12 +220,17 @@
{
int ret;
+ if (info->kernel.mapped) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "build_hvm kernel cannot be mmapped");
+ return ERROR_INVAL;
+ }
+
ret = xc_hvm_build_target_mem(
ctx->xch,
domid,
(info->max_memkb - info->video_memkb) / 1024,
(info->target_memkb - info->video_memkb) / 1024,
- libxl_abs_path(ctx, (char *)info->kernel,
+ libxl_abs_path(ctx, (char *)info->kernel.path,
libxl_xenfirmwaredir_path()));
if (ret) {
XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "hvm building failed");
diff -r bcea013ddd5a -r 2d4475143f70 tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c Mon Jul 12 14:56:37 2010 +0100
+++ b/tools/libxl/xl_cmdimpl.c Mon Jul 12 14:56:37 2010 +0100
@@ -196,7 +196,7 @@
if (c_info->hvm) {
b_info->shadow_memkb = 0; /* Set later */
b_info->video_memkb = 8 * 1024;
- b_info->kernel = "hvmloader";
+ b_info->kernel.path = "hvmloader";
b_info->hvm = 1;
b_info->u.hvm.pae = 1;
b_info->u.hvm.apic = 1;
@@ -366,7 +366,7 @@
printf("\t(image\n");
if (c_info->hvm) {
printf("\t\t(hvm\n");
- printf("\t\t\t(loader %s)\n", b_info->kernel);
+ printf("\t\t\t(loader %s)\n", b_info->kernel.path);
printf("\t\t\t(video_memkb %d)\n", b_info->video_memkb);
printf("\t\t\t(shadow_memkb %d)\n", b_info->shadow_memkb);
printf("\t\t\t(pae %d)\n", b_info->u.hvm.pae);
@@ -397,9 +397,9 @@
printf("\t\t)\n");
} else {
printf("\t\t(linux %d)\n", b_info->hvm);
- printf("\t\t\t(kernel %s)\n", b_info->kernel);
+ printf("\t\t\t(kernel %s)\n", b_info->kernel.path);
printf("\t\t\t(cmdline %s)\n", b_info->u.pv.cmdline);
- printf("\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk);
+ printf("\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk.path);
printf("\t\t)\n");
}
printf("\t)\n");
@@ -563,7 +563,7 @@
b_info->video_memkb = l * 1024;
if (!xlu_cfg_get_string (config, "kernel", &buf))
- b_info->kernel = strdup(buf);
+ b_info->kernel.path = strdup(buf);
if (c_info->hvm == 1) {
if (!xlu_cfg_get_long (config, "pae", &l))
@@ -603,7 +603,7 @@
b_info->u.pv.cmdline = cmdline;
if (!xlu_cfg_get_string (config, "ramdisk", &buf))
- b_info->u.pv.ramdisk = strdup(buf);
+ b_info->u.pv.ramdisk.path = strdup(buf);
}
if (!xlu_cfg_get_list (config, "disk", &vbds, 0)) {
diff -r bcea013ddd5a -r 2d4475143f70 tools/ocaml/libs/xl/xl_stubs.c
--- a/tools/ocaml/libs/xl/xl_stubs.c Mon Jul 12 14:56:37 2010 +0100
+++ b/tools/ocaml/libs/xl/xl_stubs.c Mon Jul 12 14:56:37 2010 +0100
@@ -103,7 +103,7 @@
c_val->target_memkb = Int64_val(Field(v, 6));
c_val->video_memkb = Int64_val(Field(v, 7));
c_val->shadow_memkb = Int64_val(Field(v, 8));
- c_val->kernel = String_val(Field(v, 9));
+ c_val->kernel.path = String_val(Field(v, 9));
c_val->hvm = Tag_val(Field(v, 10)) == 0;
infopriv = Field(Field(v, 10), 0);
if (c_val->hvm) {
@@ -119,7 +119,7 @@
} else {
c_val->u.pv.slack_memkb = Int64_val(Field(infopriv, 0));
c_val->u.pv.cmdline = String_val(Field(infopriv, 1));
- c_val->u.pv.ramdisk = String_val(Field(infopriv, 2));
+ c_val->u.pv.ramdisk.path = String_val(Field(infopriv, 2));
c_val->u.pv.features = String_val(Field(infopriv, 3));
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|