# HG changeset patch
# User Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
# Date 1279122229 -3600
# Node ID df18254561b27fe8cad6fc8a37fefa5e14cf6fb2
# Parent ad6448ee4bb6b318fa7e0231ddc0c42bf785ccbf
libxl: support mapping files rather than carrying paths around
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>
---
tools/libxl/libxl.c | 69 +++++++++++++++++++++++++++++----
tools/libxl/libxl.h | 25 +++++++++++-
tools/libxl/libxl_dom.c | 85 ++++++++++++++++++++++++++++++++++-------
tools/libxl/xl_cmdimpl.c | 12 ++---
tools/ocaml/libs/xl/xl_stubs.c | 4 -
5 files changed, 164 insertions(+), 31 deletions(-)
diff -r ad6448ee4bb6 -r df18254561b2 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c Wed Jul 14 16:40:33 2010 +0100
+++ b/tools/libxl/libxl.c Wed Jul 14 16:43:49 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 @@ int libxl_domain_build(struct libxl_ctx
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 @@ int libxl_domain_build(struct libxl_ctx
}
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 @@ int libxl_domain_restore(struct libxl_ct
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 @@ int libxl_domain_restore(struct libxl_ct
}
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 @@ static int libxl_create_stubdom(struct l
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 @@ int libxl_tmem_shared_auth(struct libxl_
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 ad6448ee4bb6 -r df18254561b2 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h Wed Jul 14 16:40:33 2010 +0100
+++ b/tools/libxl/libxl.h Wed Jul 14 16:43:49 2010 +0100
@@ -90,6 +90,24 @@ typedef struct {
} 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 @@ typedef struct {
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 @@ typedef struct {
struct {
uint32_t slack_memkb;
const char *cmdline;
- const char *ramdisk;
+ libxl_file_reference ramdisk;
const char *features;
} pv;
} u;
@@ -307,6 +325,9 @@ int libxl_domain_resume(struct libxl_ctx
int libxl_domain_resume(struct libxl_ctx *ctx, uint32_t domid);
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 ad6448ee4bb6 -r df18254561b2 tools/libxl/libxl_dom.c
--- a/tools/libxl/libxl_dom.c Wed Jul 14 16:40:33 2010 +0100
+++ b/tools/libxl/libxl_dom.c Wed Jul 14 16:43:49 2010 +0100
@@ -143,35 +143,94 @@ int build_pv(struct libxl_ctx *ctx, uint
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;
- }
- 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;
- }
+ return ERROR_FAIL;
+ }
+
+ 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,
libxl_domain_build_info *info, libxl_domain_build_state *state)
{
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 ad6448ee4bb6 -r df18254561b2 tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c Wed Jul 14 16:40:33 2010 +0100
+++ b/tools/libxl/xl_cmdimpl.c Wed Jul 14 16:43:49 2010 +0100
@@ -196,7 +196,7 @@ static void init_build_info(libxl_domain
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 @@ static void printf_info(int domid,
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 @@ static void printf_info(int domid,
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 @@ static void parse_config_data(const char
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 @@ static void parse_config_data(const char
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 ad6448ee4bb6 -r df18254561b2 tools/ocaml/libs/xl/xl_stubs.c
--- a/tools/ocaml/libs/xl/xl_stubs.c Wed Jul 14 16:40:33 2010 +0100
+++ b/tools/ocaml/libs/xl/xl_stubs.c Wed Jul 14 16:43:49 2010 +0100
@@ -120,7 +120,7 @@ static int domain_build_info_val (libxl_
c_val->target_memkb = Int64_val(Field(v, 3));
c_val->video_memkb = Int64_val(Field(v, 4));
c_val->shadow_memkb = Int64_val(Field(v, 5));
- c_val->kernel = String_val(Field(v, 6));
+ c_val->kernel.path = String_val(Field(v, 6));
c_val->hvm = Tag_val(Field(v, 7)) == 0;
infopriv = Field(Field(v, 7), 0);
if (c_val->hvm) {
@@ -136,7 +136,7 @@ static int domain_build_info_val (libxl_
} 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-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|