xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Wei Liu <wei.liu2@citrix.com>
To: xen-devel@lists.xen.org
Cc: Wei Liu <wei.liu2@citrix.com>,
	ian.jackson@eu.citrix.com, ian.campbell@citrix.com
Subject: [PATCH v2 04/18] libxl: properly lock user data store
Date: Wed, 30 Jul 2014 19:23:45 +0100	[thread overview]
Message-ID: <1406744639-28782-5-git-send-email-wei.liu2@citrix.com> (raw)
In-Reply-To: <1406744639-28782-1-git-send-email-wei.liu2@citrix.com>

Originally libxl user data store didn't have lock at all. There could be
such race condition as mentioned by Ian Jackson:

  Task 1                                 Task 2
  Creating the domain                    Trying to shut down

    actually create domain
                                           observe domid
                                           start domain destruction
                                           delete all userdata
                                           destroy domain
    store the userdata
      *** forbidden state created: userdata exists but domain doesn't
      *** userdata has been leaked
    [ would now bomb out ]

This patch adds in proper locking to libxl user data store. The lock is
associated with a specific domain (i.e. a per-domain lock).

As for locking hierachy, we first take CTX lock (which is implemented
with pthread recursive mutex so even if the application has taken it
we're fine), then take the file lock. These locks are released in
reversed order.

A new libxl error code ERROR_LOCK_FAIL is introduced to describe failure
to acquire locks.

Also factor out libxl__userdata_{retrieve,store}, so that other
functions that already hold the lock can call them to manipulate
user data.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/libxl/libxl_dom.c      |   81 +++++++++++++++++++++++++++++++++++-------
 tools/libxl/libxl_internal.h |    9 +++++
 tools/libxl/libxl_types.idl  |    1 +
 3 files changed, 79 insertions(+), 12 deletions(-)

diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index a41e8fd..3b9eade 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1798,6 +1798,12 @@ void libxl__userdata_destroyall(libxl__gc *gc, uint32_t domid)
     const char *pattern;
     glob_t gl;
     int r, i;
+    libxl__carefd *lock;
+
+    CTX_LOCK;
+    lock = libxl__lock_domain_data(gc, domid);
+    if (!lock)
+        goto out;
 
     pattern = libxl__userdata_path(gc, domid, "*", "?");
     if (!pattern)
@@ -1817,14 +1823,15 @@ void libxl__userdata_destroyall(libxl__gc *gc, uint32_t domid)
     }
     globfree(&gl);
 out:
+    if (lock) libxl__unlock_domain_data(lock);
+    CTX_UNLOCK;
     return;
 }
 
-int libxl_userdata_store(libxl_ctx *ctx, uint32_t domid,
-                              const char *userdata_userid,
-                              const uint8_t *data, int datalen)
+int libxl__userdata_store(libxl__gc *gc, uint32_t domid,
+                          const char *userdata_userid,
+                          const uint8_t *data, int datalen)
 {
-    GC_INIT(ctx);
     const char *filename;
     const char *newfilename;
     int e, rc;
@@ -1853,7 +1860,7 @@ int libxl_userdata_store(libxl_ctx *ctx, uint32_t domid,
     if (fd < 0)
         goto err;
 
-    if (libxl_write_exactly(ctx, fd, data, datalen, "userdata", newfilename))
+    if (libxl_write_exactly(CTX, fd, data, datalen, "userdata", newfilename))
         goto err;
 
     if (close(fd) < 0) {
@@ -1875,18 +1882,42 @@ err:
     }
 
     if (rc)
-        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot write/rename %s for %s",
+        LIBXL__LOG_ERRNO(CTX, LIBXL__LOG_ERROR, "cannot write/rename %s for %s",
                  newfilename, filename);
 out:
-    GC_FREE;
     return rc;
 }
 
-int libxl_userdata_retrieve(libxl_ctx *ctx, uint32_t domid,
-                                 const char *userdata_userid,
-                                 uint8_t **data_r, int *datalen_r)
+int libxl_userdata_store(libxl_ctx *ctx, uint32_t domid,
+                              const char *userdata_userid,
+                              const uint8_t *data, int datalen)
 {
     GC_INIT(ctx);
+    int rc;
+    libxl__carefd *lock;
+
+    CTX_LOCK;
+    lock = libxl__lock_domain_data(gc, domid);
+    if (!lock) {
+        rc = ERROR_LOCK_FAIL;
+        goto out;
+    }
+
+    rc = libxl__userdata_store(gc, domid, userdata_userid,
+                               data, datalen);
+
+    libxl__unlock_domain_data(lock);
+
+out:
+    CTX_UNLOCK;
+    GC_FREE;
+    return rc;
+}
+
+int libxl__userdata_retrieve(libxl__gc *gc, uint32_t domid,
+                             const char *userdata_userid,
+                             uint8_t **data_r, int *datalen_r)
+{
     const char *filename;
     int e, rc;
     int datalen = 0;
@@ -1898,13 +1929,13 @@ int libxl_userdata_retrieve(libxl_ctx *ctx, uint32_t domid,
         goto out;
     }
 
-    e = libxl_read_file_contents(ctx, filename, data_r ? &data : 0, &datalen);
+    e = libxl_read_file_contents(CTX, filename, data_r ? &data : 0, &datalen);
     if (e && errno != ENOENT) {
         rc = ERROR_FAIL;
         goto out;
     }
     if (!e && !datalen) {
-        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "userdata file %s is empty", filename);
+        LIBXL__LOG(CTX, LIBXL__LOG_ERROR, "userdata file %s is empty", filename);
         if (data_r) assert(!*data_r);
         rc = ERROR_FAIL;
         goto out;
@@ -1913,7 +1944,33 @@ int libxl_userdata_retrieve(libxl_ctx *ctx, uint32_t domid,
     if (data_r) *data_r = data;
     if (datalen_r) *datalen_r = datalen;
     rc = 0;
+
+out:
+    return rc;
+}
+
+int libxl_userdata_retrieve(libxl_ctx *ctx, uint32_t domid,
+                                 const char *userdata_userid,
+                                 uint8_t **data_r, int *datalen_r)
+{
+    GC_INIT(ctx);
+    int rc;
+    libxl__carefd *lock;
+
+    CTX_LOCK;
+    lock = libxl__lock_domain_data(gc, domid);
+    if (!lock) {
+        rc = ERROR_LOCK_FAIL;
+        goto out;
+    }
+
+    rc = libxl__userdata_retrieve(gc, domid, userdata_userid,
+                                  data_r, datalen_r);
+
+
+    libxl__unlock_domain_data(lock);
 out:
+    CTX_UNLOCK;
     GC_FREE;
     return rc;
 }
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 60316ff..03ed7ec 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -996,6 +996,15 @@ _hidden const char *libxl__userdata_path(libxl__gc *gc, uint32_t domid,
                                          const char *userdata_userid,
                                          const char *wh);
 _hidden void libxl__userdata_destroyall(libxl__gc *gc, uint32_t domid);
+/* Caller must hold data store lock before calling
+ * libxl__userdata_{retrieve,store}
+ */
+_hidden int libxl__userdata_retrieve(libxl__gc *gc, uint32_t domid,
+                                     const char *userdata_userid,
+                                     uint8_t **data_r, int *datalen_r);
+_hidden int libxl__userdata_store(libxl__gc *gc, uint32_t domid,
+                                  const char *userdata_userid,
+                                  const uint8_t *data, int datalen);
 
 _hidden int libxl__domain_resume(libxl__gc *gc, uint32_t domid,
                                  int suspend_cancel);
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index a412f9c..17b4453 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -58,6 +58,7 @@ libxl_error = Enumeration("error", [
     (-12, "OSEVENT_REG_FAIL"),
     (-13, "BUFFERFULL"),
     (-14, "UNKNOWN_CHILD"),
+    (-15, "LOCK_FAIL"),
     ], value_namespace = "")
 
 libxl_domain_type = Enumeration("domain_type", [
-- 
1.7.10.4

  parent reply	other threads:[~2014-07-30 18:23 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-30 18:23 [PATCH v2 00/18] libxl: synchronise domain configuration Wei Liu
2014-07-30 18:23 ` [PATCH v2 01/18] libxl: libxl error code is signed integer Wei Liu
2014-08-26 21:15   ` Ian Campbell
2014-09-03 14:12     ` Ian Campbell
2014-07-30 18:23 ` [PATCH v2 02/18] libxl: make userdata_path libxl internal function Wei Liu
2014-08-26 21:16   ` Ian Campbell
2014-07-30 18:23 ` [PATCH v2 03/18] libxl: functions to lock / unlock domain data in libxl user data store Wei Liu
2014-08-26 21:21   ` Ian Campbell
2014-09-03 14:27     ` Wei Liu
2014-09-03 12:40   ` Ian Campbell
2014-09-03 15:09     ` Wei Liu
2014-07-30 18:23 ` Wei Liu [this message]
2014-08-26 21:24   ` [PATCH v2 04/18] libxl: properly lock " Ian Campbell
2014-07-30 18:23 ` [PATCH v2 05/18] libxl: libxl-json format and internal functions to get / set it Wei Liu
2014-07-30 18:23 ` [PATCH v2 06/18] libxl: store a copy of configuration when creating domain Wei Liu
2014-08-27  1:34   ` Ian Campbell
2014-07-30 18:23 ` [PATCH v2 07/18] libxl: separate device add/rm complete callbacks Wei Liu
2014-08-27  1:41   ` Ian Campbell
2014-08-28 10:34     ` Wei Liu
2014-09-03 11:53       ` Ian Campbell
2014-09-03 11:55         ` Ian Campbell
2014-07-30 18:23 ` [PATCH v2 08/18] libxl: introduce libxl__device_from_pcidev Wei Liu
2014-08-27  1:45   ` Ian Campbell
2014-07-30 18:23 ` [PATCH v2 09/18] libxl: disallow attaching the same device more than once Wei Liu
2014-08-27  1:48   ` Ian Campbell
2014-08-28 10:55     ` Wei Liu
2014-09-03 11:52       ` Ian Campbell
2014-07-30 18:23 ` [PATCH v2 10/18] tools/misc: introduce helper to initialise Dom0 Wei Liu
2014-07-31  8:34   ` Ian Campbell
2014-08-27  1:52   ` Ian Campbell
2014-08-28 10:58     ` Wei Liu
2014-07-30 18:23 ` [PATCH v2 11/18] libxl: synchronise configuration when we hotplug a device Wei Liu
2014-08-27  2:00   ` Ian Campbell
2014-08-28 11:18     ` Wei Liu
2014-09-03 11:57       ` Ian Campbell
2014-07-30 18:23 ` [PATCH v2 12/18] libxl: synchronise configuration when we remove/destroy " Wei Liu
2014-08-27  2:01   ` Ian Campbell
2014-07-30 18:23 ` [PATCH v2 13/18] libxl: make libxl_cd_insert "eject" + "insert" Wei Liu
2014-08-27  2:04   ` Ian Campbell
2014-08-28 11:25     ` Wei Liu
2014-08-28 18:14       ` Ian Campbell
2014-08-28 18:38         ` Wei Liu
2014-07-30 18:23 ` [PATCH v2 14/18] libxl: introduce libxl_get_memory_static_max Wei Liu
2014-08-27  2:09   ` Ian Campbell
2014-08-28 11:31     ` Wei Liu
2014-08-28 18:16       ` Ian Campbell
2014-08-28 18:39         ` Wei Liu
2014-07-30 18:23 ` [PATCH v2 15/18] libxl: introduce libxl_retrieve_domain_configuration Wei Liu
2014-08-27  2:13   ` Ian Campbell
2014-08-28 11:39     ` Wei Liu
2014-08-28 18:17       ` Ian Campbell
2014-08-28 18:51         ` Wei Liu
2014-07-30 18:23 ` [PATCH v2 16/18] libxl: introduce libxl_userdata_unlink Wei Liu
2014-08-27  2:16   ` Ian Campbell
2014-08-28 11:50     ` Wei Liu
2014-08-28 18:20       ` Ian Campbell
2014-08-28 19:04         ` Wei Liu
2014-08-28 19:31           ` Ian Campbell
2014-08-28 20:27             ` Wei Liu
2014-08-28 20:44               ` Ian Campbell
2014-08-29 10:37                 ` Wei Liu
2014-09-03 12:12                   ` Ian Campbell
2014-09-03 14:10                     ` Wei Liu
2014-09-03 14:16                       ` Ian Campbell
2014-09-03 14:17                         ` Wei Liu
2014-07-30 18:23 ` [PATCH v2 17/18] xl: use libxl_retrieve_domain_configuration and JSON format Wei Liu
2014-09-03 12:57   ` Ian Campbell
2014-07-30 18:23 ` [PATCH v2 18/18] xl: long output of "list" command now contains Dom0 information Wei Liu
2014-09-03 12:50   ` Ian Campbell
2014-08-12 16:17 ` [PATCH v2 00/18] libxl: synchronise domain configuration Wei Liu

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=1406744639-28782-5-git-send-email-wei.liu2@citrix.com \
    --to=wei.liu2@citrix.com \
    --cc=ian.campbell@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=xen-devel@lists.xen.org \
    /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).