xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Ian Campbell <ian.campbell@citrix.com>
To: xen-devel@lists.xensource.com
Cc: Ian Campbell <ian.campbell@citrix.com>
Subject: [PATCH 7 of 9] libxl: support mapping files rather than carrying paths around
Date: Mon, 12 Jul 2010 15:01:43 +0100	[thread overview]
Message-ID: <2d4475143f70d6231163.1278943303@localhost.localdomain> (raw)
In-Reply-To: <patchbomb.1278943296@localhost.localdomain>

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@citrix.com>

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));
 	}

  parent reply	other threads:[~2010-07-12 14:01 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-12 14:01 [PATCH 0 of 9] libxl/xl: support for domain 0 bootloader (e.g. pygrub) Ian Campbell
2010-07-12 14:01 ` [PATCH 1 of 9] pygrub: introduce easier to parse output format Ian Campbell
2010-07-12 14:01 ` [PATCH 2 of 9] xenconsole: do not exit if a pty device is missing Ian Campbell
2010-07-12 14:01 ` [PATCH 3 of 9] libxl: add printf attribute to libxl_xs_write and fixup resulting warnings Ian Campbell
2010-07-12 14:01 ` [PATCH 4 of 9] libxl: add libxl_strdup convenience function Ian Campbell
2010-07-12 14:01 ` [PATCH 5 of 9] libxl: fix typo Ian Campbell
2010-07-12 14:01 ` [PATCH 6 of 9] libxl/xl: exec xenconsole in current process, defer decision to fork to caller Ian Campbell
2010-07-12 14:01 ` Ian Campbell [this message]
2010-07-12 14:01 ` [PATCH 8 of 9] libxl: add function to attach/detach a disk to/from the local VM Ian Campbell
2010-07-12 14:01 ` [PATCH 9 of 9] libxl/xl: support running bootloader (e.g. pygrub) in domain 0 Ian Campbell
2010-07-13 18:23 ` [PATCH 0 of 9] libxl/xl: support for domain 0 bootloader (e.g. pygrub) Ian Jackson
2010-07-14  1:24   ` Zhigang Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2d4475143f70d6231163.1278943303@localhost.localdomain \
    --to=ian.campbell@citrix.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).