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 v3 02/15] libxl: functions to lock / unlock libxl userdata store
Date: Thu, 4 Sep 2014 23:43:08 +0100	[thread overview]
Message-ID: <1409870601-7538-3-git-send-email-wei.liu2@citrix.com> (raw)
In-Reply-To: <1409870601-7538-1-git-send-email-wei.liu2@citrix.com>

This lock is used to protect all userdata files related to a particular
domain, which include but are not limited to domain configuration.  A
new "domain-userdata-lock" entry is introduced in libxl registry.

This lock works among different processes and different threads within
the same process.

Locking protocol inspired by Ian Jackson's chiark-utils with-lock-ex. A
file lock is taken with flock(2). If that succeeds that thread fstat the
fd and stat the lock file path. If the device and inode match then the
lock has been successfully acquired. This lock remains acquired until
the lock file gets deleted or released by flock(2). If device and inode
don't match then another thread acquired the lock and deleted the file
in the meantime; lock procedure should restart.

Portability note: this lock utilises flock(2) so a proper implementation
of flock(2) is required -- that is, it should not be implemented with
fcntl(2).

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

---
change in v3:
rename functions to libxl__{un,}lock_domain_userdata
rename registry entry to "domain-userdata-lock"
---
 tools/libxl/libxl.h          |    3 ++
 tools/libxl/libxl_internal.c |   69 ++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_internal.h |    5 +++
 3 files changed, 77 insertions(+)

diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 460207b..1ca25ae 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1220,6 +1220,9 @@ void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
  *  "xl"          domain config file in xl format, Unix line endings
  *  "libvirt-xml" domain config file in libvirt XML format.  See
  *                http://libvirt.org/formatdomain.html
+ *  "domain-userdata-lock"  lock file to protect domain userdata in libxl.
+ *                          It's a per-domain lock. Applications should
+ *                          not touch this file.
  *
  * libxl does not enforce the registration of userdata userids or the
  * semantics of the data.  For specifications of the data formats
diff --git a/tools/libxl/libxl_internal.c b/tools/libxl/libxl_internal.c
index b880c89..edf864b 100644
--- a/tools/libxl/libxl_internal.c
+++ b/tools/libxl/libxl_internal.c
@@ -381,6 +381,75 @@ out:
     return rc;
 }
 
+/* Portability note: this lock utilises flock(2) so a proper implementation of
+ * flock(2) is required.
+ */
+libxl__carefd *libxl__lock_domain_userdata(libxl__gc *gc, uint32_t domid)
+{
+    libxl__carefd *carefd = NULL;
+    const char *lockfile;
+    int fd;
+    struct stat stab, fstab;
+
+    lockfile = libxl__userdata_path(gc, domid, "domain-userdata-lock", "l");
+    if (!lockfile) goto out;
+
+    while (true) {
+        libxl__carefd_begin();
+        fd = open(lockfile, O_RDWR|O_CREAT, 0666);
+        if (fd < 0)
+            LOGE(ERROR, "cannot open lockfile %s, errno=%d", lockfile, errno);
+        carefd = libxl__carefd_opened(CTX, fd);
+        if (fd < 0) goto out;
+
+        /* Lock the file in exclusive mode, wait indefinitely to
+         * acquire the lock
+         */
+        while (flock(fd, LOCK_EX)) {
+            switch (errno) {
+            case EINTR:
+                /* Signal received, retry */
+                continue;
+            default:
+                /* All other errno: EBADF, EINVAL, ENOLCK, EWOULDBLOCK */
+                LOGE(ERROR,
+                     "unexpected error while trying to lock %s, fd=%d, errno=%d",
+                     lockfile, fd, errno);
+                goto out;
+            }
+        }
+
+        if (fstat(fd, &fstab)) {
+            LOGE(ERROR, "cannot fstat %s, fd=%d, errno=%d",
+                 lockfile, fd, errno);
+            goto out;
+        }
+        if (stat(lockfile, &stab)) {
+            if (errno != ENOENT) {
+                LOGE(ERROR, "cannot stat %s, errno=%d", lockfile, errno);
+                goto out;
+            }
+        } else {
+            if (stab.st_dev == fstab.st_dev && stab.st_ino == fstab.st_ino)
+                break;
+        }
+
+        libxl__carefd_close(carefd);
+    }
+
+    return carefd;
+
+out:
+    if (carefd) libxl__carefd_close(carefd);
+    return NULL;
+}
+
+void libxl__unlock_domain_userdata(libxl__carefd *lock_carefd)
+{
+    /* Simply closing the file descriptor releases the lock */
+    libxl__carefd_close(lock_carefd);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 7244473..0cedd30 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -43,6 +43,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
+#include <sys/file.h>
 
 #include <xenstore.h>
 #include <xenctrl.h>
@@ -3223,6 +3224,10 @@ static inline int libxl__key_value_list_is_empty(libxl_key_value_list *pkvl)
 
 int libxl__cpuid_policy_is_empty(libxl_cpuid_policy_list *pl);
 
+/* Portability note: a proper flock(2) implementation is required */
+libxl__carefd *libxl__lock_domain_userdata(libxl__gc *gc, uint32_t domid);
+void libxl__unlock_domain_userdata(libxl__carefd *lock_carefd);
+
 #endif
 
 /*
-- 
1.7.10.4

  parent reply	other threads:[~2014-09-04 22:43 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-04 22:43 [PATCH v3 00/15] libxl: synchronise domain configuration Wei Liu
2014-09-04 22:43 ` [PATCH v3 01/15] libxl: make userdata_path libxl internal function Wei Liu
2014-09-04 22:43 ` Wei Liu [this message]
2014-09-04 22:43 ` [PATCH v3 03/15] libxl: properly lock userdata store Wei Liu
2014-09-09 10:52   ` Ian Campbell
2014-09-04 22:43 ` [PATCH v3 04/15] libxl: libxl-json format and internal functions to get / set it Wei Liu
2014-09-04 22:43 ` [PATCH v3 05/15] libxl: store a copy of configuration when creating domain Wei Liu
2014-09-04 22:43 ` [PATCH v3 06/15] libxl: introduce libxl__device_from_pcidev Wei Liu
2014-09-04 22:43 ` [PATCH v3 07/15] libxl: disallow attaching the same device more than once Wei Liu
2014-09-09 10:56   ` Ian Campbell
2014-09-04 22:43 ` [PATCH v3 08/15] libxl: introduce helper to initialise Dom0 Wei Liu
2014-09-05 13:22   ` Wei Liu
2014-09-09 11:03     ` Wei Liu
2014-09-09 11:16   ` Ian Campbell
2014-09-09 12:16     ` Ian Campbell
2014-09-04 22:43 ` [PATCH v3 09/15] libxl: synchronise configuration when we hotplug a device Wei Liu
2014-09-09 11:11   ` Ian Campbell
2014-09-09 11:23     ` Ian Campbell
2014-09-09 13:37     ` Wei Liu
2014-09-09 13:41       ` Ian Campbell
2014-09-04 22:43 ` [PATCH v3 10/15] libxl: make libxl_cd_insert "eject" + "insert" Wei Liu
2014-09-09 11:30   ` Ian Campbell
2014-09-09 13:38     ` Wei Liu
2014-09-15 14:38     ` Wei Liu
2014-09-04 22:43 ` [PATCH v3 11/15] libxl: refactor libxl_get_memory_target Wei Liu
2014-09-09 11:36   ` Ian Campbell
2014-09-09 11:39     ` Ian Campbell
2014-09-09 13:39       ` Wei Liu
2014-09-04 22:43 ` [PATCH v3 12/15] libxl: introduce libxl_retrieve_domain_configuration Wei Liu
2014-09-09 11:41   ` Ian Campbell
2014-09-04 22:43 ` [PATCH v3 13/15] libxl: introduce libxl_userdata_unlink Wei Liu
2014-09-09 11:42   ` Ian Campbell
2014-09-04 22:43 ` [PATCH v3 14/15] xl: use libxl_retrieve_domain_configuration and JSON format Wei Liu
2014-09-09 11:44   ` Ian Campbell
2014-09-04 22:43 ` [PATCH v3 15/15] xl: long output of "list" command now contains Dom0 information 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=1409870601-7538-3-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).