xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Ian Jackson <ian.jackson@eu.citrix.com>
To: xen-devel@lists.xensource.com
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>,
	Ian Jackson <ian.jackson@eu.citrix.com>
Subject: [PATCH 08/11] libxl: Per-domain data storage for the convenience of the library user
Date: Thu, 25 Mar 2010 19:04:11 +0000	[thread overview]
Message-ID: <1269543854-7780-9-git-send-email-ian.jackson@eu.citrix.com> (raw)
In-Reply-To: <1269543854-7780-1-git-send-email-ian.jackson@eu.citrix.com>

We provide a mechanism whereby a user of the libxl library is able to
store some information alongside the domain.  The information stored
is a block of bytes.  Its lifetime is that of the domain - ie the
userdata is garbage collected alongside the domain if the domain is
destroyed.  (This is why the feature needs to be in libxl and cannot
be implemented in the user itself or in libxlutil.)

If a libxl caller does not need to use this feature it can ignore it.

The data is tagged with the (self-declared) name of the libxl user, so
that different users cannot accidentally trip over each others'
userdata.  The data is not interpreted at all by libxl.

To assist developers and people debugging, there is a registry of the
known userdata userids, and the corresponding data format as declared
by that libxl user, in libxl.h next to these declarations:

 int libxl_userdata_store(struct libxl_ctx *ctx, uint32_t domid,
                               const char *userdata_userid,
                               const uint8_t *data, int datalen);
 int libxl_userdata_retrieve(struct libxl_ctx *ctx, uint32_t domid,
                                  const char *userdata_userid,
                                  uint8_t **data_r, int *datalen_r);

The next patch will introduce the data for the userid "xl".

Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 tools/libxl/libxl.c          |    2 +
 tools/libxl/libxl.h          |   31 +++++++++++
 tools/libxl/libxl_dom.c      |  115 ++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_internal.h |    1 +
 4 files changed, 149 insertions(+), 0 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 711f0a0..4d069cd 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -708,6 +708,8 @@ int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force)
         if (!xs_rm(ctx->xsh, XBT_NULL, xapi_path))
             XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", xapi_path);
 
+    libxl__userdata_destroyall(ctx, domid);
+
     rc = xc_domain_destroy(ctx->xch, domid);
     if (rc < 0) {
         XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 2d76087..d57dd10 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -359,6 +359,37 @@ int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
                           unsigned int bus, unsigned int dev,
                           unsigned int func, unsigned int vdevfn);
 
+/*
+ * Functions for allowing users of libxl to store private data
+ * relating to a domain.  The data is an opaque sequence of bytes and
+ * is not interpreted or used by libxl.
+ *
+ * Data is indexed by the userdata userid, which is a short printable
+ * ASCII string.  The following list is a registry of userdata userids
+ * (the registry may be updated by posting a patch to xen-devel):
+ * 
+ *  userid      Data contents
+ *   "xl"        domain config file in xl format, Unix line endings
+ *
+ * libxl does not enforce the registration of userdata userids or the
+ * semantics of the data.  For specifications of the data formats
+ * see the code or documentation for the libxl caller in question.
+ */
+int libxl_userdata_store(struct libxl_ctx *ctx, uint32_t domid,
+                              const char *userdata_userid,
+                              const uint8_t *data, int datalen);
+  /* If datalen==0, data is not used and the user data for
+   * that domain and userdata_userid is deleted. */
+int libxl_userdata_retrieve(struct libxl_ctx *ctx, uint32_t domid,
+                                 const char *userdata_userid,
+                                 uint8_t **data_r, int *datalen_r);
+  /* On successful return, *data_r is from malloc.
+   * If there is no data for that domain and userdata_userid,
+   * *data_r and *datalen_r will be set to 0.
+   * data_r and datalen_r may be 0.
+   * On error return, *data_r and *datalen_r are undefined.
+   */
+
 typedef enum {
     POWER_BUTTON,
     SLEEP_BUTTON
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 7196aa8..237febb 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -16,6 +16,8 @@
 #include "libxl_osdeps.h"
 
 #include <stdio.h>
+#include <assert.h>
+#include <glob.h>
 #include <inttypes.h>
 #include <string.h>
 #include <sys/time.h> /* for struct timeval */
@@ -349,3 +351,116 @@ int save_device_model(struct libxl_ctx *ctx, uint32_t domid, int fd)
     unlink(filename);
     return 0;
 }
+
+static const char *userdata_path(struct libxl_ctx *ctx, uint32_t domid,
+                                      const char *userdata_userid,
+                                      const char *wh) {
+    char *path;
+    path = libxl_sprintf(ctx, "/var/lib/xen/"
+                         "userdata-%s.%"PRIu32".%s",
+                         wh, domid, userdata_userid);
+    if (!path)
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to allocate for"
+                     " userdata path");
+    return path;
+}
+
+static int userdata_delete(struct libxl_ctx *ctx, const char *path) {
+    int r;
+    r = unlink(path);
+    if (r) {
+        XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "remove failed for %s", path);
+        return errno;
+    }
+    return 0;
+}
+
+void libxl__userdata_destroyall(struct libxl_ctx *ctx, uint32_t domid) {
+    const char *pattern;
+    glob_t gl;
+    int r, i;
+    
+    pattern = userdata_path(ctx, domid, "*", "?");
+    if (!pattern) return;
+
+    gl.gl_pathc = 0;
+    gl.gl_pathv = 0;
+    gl.gl_offs = 0;
+    r = glob(pattern, GLOB_ERR|GLOB_NOSORT|GLOB_MARK, 0, &gl);
+    if (r) XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "glob failed for %s", pattern);
+
+    for (i=0; i<gl.gl_pathc; i++) {
+        userdata_delete(ctx, gl.gl_pathv[i]);
+    }
+    globfree(&gl);
+}
+
+int libxl_userdata_store(struct libxl_ctx *ctx, uint32_t domid,
+                              const char *userdata_userid,
+                              const uint8_t *data, int datalen) {
+    const char *filename;
+    const char *newfilename;
+    int e;
+    int fd = -1;
+    FILE *f = 0;
+    size_t rs;
+
+    filename = userdata_path(ctx, domid, userdata_userid, "d");
+    if (!filename) return ENOMEM;
+
+    if (!datalen)
+        return userdata_delete(ctx, filename);
+
+    newfilename = userdata_path(ctx, domid, userdata_userid, "n");
+    if (!newfilename) return ENOMEM;
+
+    fd= open(newfilename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+    if (fd<0) goto xe;
+    
+    f= fdopen(fd, "wb");
+    if (!f) goto xe;
+    fd = -1;
+
+    rs = fwrite(data, 1, datalen, f);
+    if (rs != datalen) { assert(ferror(f)); goto xe; }
+
+    if (fclose(f)) goto xe;
+    f = 0;
+
+    if (rename(newfilename,filename)) goto xe;
+
+    return 0;
+
+ xe:
+    e = errno;
+    if (f) fclose(f);
+    if (fd>=0) close(fd);
+
+    XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot write %s for %s",
+                 newfilename, filename);
+    return e;
+}
+
+int libxl_userdata_retrieve(struct libxl_ctx *ctx, uint32_t domid,
+                                 const char *userdata_userid,
+                                 uint8_t **data_r, int *datalen_r) {
+    const char *filename;
+    int e;
+    int datalen = 0;
+    void *data = 0;
+
+    filename = userdata_path(ctx, domid, userdata_userid, "d");
+    if (!filename) return ENOMEM;
+
+    e = libxl_read_file_contents(ctx, filename, data_r ? &data : 0, &datalen);
+
+    if (!e && !datalen) {
+        XL_LOG(ctx, XL_LOG_ERROR, "userdata file %s is empty", filename);
+        if (data_r) assert(!*data_r);
+        return EPROTO;
+    }
+
+    if (data_r) *data_r = data;
+    if (datalen_r) *datalen_r = datalen;
+    return 0;
+}
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index d1e355c..b35cf0f 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -130,6 +130,7 @@ int restore_common(struct libxl_ctx *ctx, uint32_t domid,
                    libxl_domain_build_info *info, libxl_domain_build_state *state, int fd);
 int core_suspend(struct libxl_ctx *ctx, uint32_t domid, int fd, int hvm, int live, int debug);
 int save_device_model(struct libxl_ctx *ctx, uint32_t domid, int fd);
+void libxl__userdata_destroyall(struct libxl_ctx *ctx, uint32_t domid);
 
 /* from xl_device */
 char *device_disk_backend_type_of_phystype(libxl_disk_phystype phystype);
-- 
1.5.6.5

  parent reply	other threads:[~2010-03-25 19:04 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-25 19:04 [PATCH 00/11] Migration support for "xl" Ian Jackson
2010-03-25 19:04 ` [PATCH 01/11] libxl: Make logging functions preserve errno Ian Jackson
2010-03-25 19:04 ` [PATCH 02/11] libxl: Report error if logfile rotation fails Ian Jackson
2010-03-25 19:04 ` [PATCH 03/11] libxl: New utility functions in for reading and writing files Ian Jackson
2010-03-25 19:04 ` [PATCH 04/11] libxl: libxl_domain_restore: Put fd back to blocking mode Ian Jackson
2010-03-25 19:04 ` [PATCH 05/11] libxl: Provide libxl_domain_rename Ian Jackson
2010-03-26 10:01   ` Vincent Hanquez
2010-03-26 10:23     ` Ian Jackson
2010-03-26 10:34       ` Vincent Hanquez
2010-03-26 10:40         ` Ian Jackson
2010-04-01 11:00         ` Stefano Stabellini
2010-03-25 19:04 ` [PATCH 06/11] libxl: Expose functions for helping with subprocesses Ian Jackson
2010-03-25 19:04 ` [PATCH 07/11] libxl: Expose libxl_report_exitstatus Ian Jackson
2010-03-25 19:04 ` Ian Jackson [this message]
2010-03-26 10:06   ` [PATCH 08/11] libxl: Per-domain data storage for the convenience of the library user Vincent Hanquez
2010-03-26 10:20     ` Ian Jackson
2010-03-26 10:29       ` Vincent Hanquez
2010-03-26 10:34         ` Ian Jackson
2010-03-26 10:41           ` Vincent Hanquez
2010-03-26 10:45             ` Ian Jackson
2010-03-26 11:27               ` Vincent Hanquez
2010-03-26 11:56                 ` Ian Jackson
2010-04-01 11:04       ` Stefano Stabellini
2010-03-25 19:04 ` [PATCH 09/11] xl: New savefile format. Save domain config when saving a domain Ian Jackson
2010-04-01 11:08   ` Stefano Stabellini
2010-03-25 19:04 ` [PATCH 10/11] xl: Domain creation logging fixes Ian Jackson
2010-03-25 19:04 ` [PATCH 11/11] xl: Migration support Ian Jackson
2010-04-01 11:10   ` Stefano Stabellini
2010-04-01 11:10 ` [PATCH 00/11] Migration support for "xl" Stefano Stabellini

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=1269543854-7780-9-git-send-email-ian.jackson@eu.citrix.com \
    --to=ian.jackson@eu.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).