Xen-Devel Archive on lore.kernel.org
 help / color / Atom feed
From: Paul Durrant <pdurrant@amazon.com>
To: <xen-devel@lists.xenproject.org>
Cc: Anthony PERARD <anthony.perard@citrix.com>,
	Paul Durrant <pdurrant@amazon.com>,
	Ian Jackson <ian.jackson@eu.citrix.com>, Wei Liu <wl@xen.org>
Subject: [Xen-devel] [PATCH v3 3/6] libxl: add infrastructure to track and query 'retired' domids
Date: Thu, 16 Jan 2020 09:35:59 +0000
Message-ID: <20200116093602.4203-4-pdurrant@amazon.com> (raw)
In-Reply-To: <20200116093602.4203-1-pdurrant@amazon.com>

A domid is considered retired if the domain it represents was destroyed
less than a specified number of seconds ago. The number can be set using
the environment variable LIBXL_DOMID_MAX_RETIREMENT. If the variable does
not exist then a default value of 60s is used.

Whenever a domain is destroyed, a time-stamped record will be written into
a history file (/var/run/xen/domid-history). To avoid the history file
growing too large, any records with time-stamps that indicate that the
domid has exceeded maximum retirement will also be purged.

A new utility function, libxl__is_retired_domid(), has been added. This
function reads the same history file checking whether a specified domid
has a record that does not exceed maximum retirement. Since this utility
function does not write to the file, no records are actually purged by it.

NOTE: Since the history file is hosted by a tmpfs file system, it is
      automatically purged on boot thus allowing safe use of
      CLOCK_MONOTONIC as a time source.

Signed-off-by: Paul Durrant <pdurrant@amazon.com>
---
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wl@xen.org>
Cc: Anthony PERARD <anthony.perard@citrix.com>

v2:
 - New in v2
---
 tools/libxl/libxl_domain.c   | 132 +++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_internal.h |  10 +++
 2 files changed, 142 insertions(+)

diff --git a/tools/libxl/libxl_domain.c b/tools/libxl/libxl_domain.c
index 5714501778..7f255f184c 100644
--- a/tools/libxl/libxl_domain.c
+++ b/tools/libxl/libxl_domain.c
@@ -1268,6 +1268,137 @@ static void dm_destroy_cb(libxl__egc *egc,
     libxl__devices_destroy(egc, &dis->drs);
 }
 
+static unsigned int libxl__get_max_retirement(void)
+{
+    const char *env_max_retirement = getenv("LIBXL_DOMID_MAX_RETIREMENT");
+
+    return env_max_retirement ? strtol(env_max_retirement, NULL, 0) :
+        LIBXL_DOMID_MAX_RETIREMENT;
+}
+
+static int libxl__open_domid_history(libxl__gc *gc)
+{
+    const char *name;
+    int fd;
+    int ret;
+
+    name = GCSPRINTF("%s/domid-history", libxl__run_dir_path());
+
+    fd = open(name, O_RDWR|O_CREAT, 0644);
+    if (fd < 0) {
+        LOGE(ERROR, "unexpected error while trying open %s, errno=%d",
+             name, errno);
+        goto fail;
+    }
+
+    for (;;) {
+        ret = flock(fd, LOCK_EX);
+        if (!ret)
+            break;
+        if (errno != EINTR) {
+            /* All other errno: EBADF, EINVAL, ENOLCK, EWOULDBLOCK */
+            LOGE(ERROR,
+                 "unexpected error while trying to lock %s, fd=%d, errno=%d",
+                 name, fd, errno);
+            goto fail;
+        }
+    }
+
+    return fd;
+
+fail:
+    if (fd >= 0)
+        close(fd);
+
+    return -1;
+}
+
+/* Write a domid retirement record */
+static void libxl__retire_domid(libxl__gc *gc, uint32_t domid)
+{
+    long max_retirement = libxl__get_max_retirement();
+    int fd;
+    FILE *f;
+    long roff, woff;
+    char line[64];
+    struct timespec ts;
+
+    fd = libxl__open_domid_history(gc);
+    if (fd < 0)
+        return;
+
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+
+    /* Purge old retirement records */
+
+    f = fdopen(fd, "r+");
+    woff = ftell(f);
+
+    while (fgets(line, sizeof(line), f)) {
+        unsigned long sec;
+        unsigned int ignored;
+
+        roff = ftell(f);
+
+        if (sscanf(line, "%lu %u", &sec, &ignored) != 2)
+            continue; /* Purge malformed lines */
+
+        if (ts.tv_sec - sec > max_retirement)
+            continue;
+
+        fseek(f, woff, SEEK_SET);
+        fputs(line, f);
+        woff = ftell(f);
+
+        fseek(f, roff, SEEK_SET);
+    }
+
+    fseek(f, woff, SEEK_SET);
+    fprintf(f, "%lu %u\n", ts.tv_sec, domid);
+    woff = ftell(f);
+    fflush(f);
+
+    ftruncate(fd, woff); /* may now be fewer records */
+
+    close(fd);
+}
+
+bool libxl__is_retired_domid(libxl__gc *gc, uint32_t domid)
+{
+    long max_retirement = libxl__get_max_retirement();
+    bool retired = false;
+    int fd;
+    FILE *f;
+    char line[64];
+    struct timespec ts;
+
+    fd = libxl__open_domid_history(gc);
+    if (fd < 0)
+        return false;
+
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+
+    f = fdopen(fd, "r");
+
+    while (fgets(line, sizeof(line), f)) {
+        unsigned long sec;
+        unsigned int check;
+
+        if (sscanf(line, "%lu %u", &sec, &check) != 2)
+            continue;
+
+        if (check == domid &&
+            ts.tv_sec - sec <= max_retirement) {
+            retired = true;
+            break;
+        }
+    }
+
+    close(fd);
+
+    return retired;
+}
+
 static void devices_destroy_cb(libxl__egc *egc,
                                libxl__devices_remove_state *drs,
                                int rc)
@@ -1331,6 +1462,7 @@ static void devices_destroy_cb(libxl__egc *egc,
         if (!ctx->xch) goto badchild;
 
         if (!dis->soft_reset) {
+            libxl__retire_domid(gc, domid);
             rc = xc_domain_destroy(ctx->xch, domid);
         } else {
             rc = xc_domain_pause(ctx->xch, domid);
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index cb23490c59..fcac8a93c5 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -4770,6 +4770,16 @@ _hidden int libxl__domain_pvcontrol(libxl__egc *egc,
                                     libxl__xswait_state *pvcontrol,
                                     domid_t domid, const char *cmd);
 
+/*
+ * Maximum number of seconds a domid remains in retirement after domain
+ * destruction. This can be overidden by the environment variable of the
+ * same name.
+ */
+#define LIBXL_DOMID_MAX_RETIREMENT 60
+
+/* Check whether a domid is in retirement */
+bool libxl__is_retired_domid(libxl__gc *gc, uint32_t domid);
+
 #endif
 
 /*
-- 
2.20.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply index

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-16  9:35 [Xen-devel] [PATCH v3 0/6] xl/libxl: domid allocation/preservation changes Paul Durrant
2020-01-16  9:35 ` [Xen-devel] [PATCH v3 1/6] libxl: add definition of INVALID_DOMID to the API Paul Durrant
2020-01-16  9:35 ` [Xen-devel] [PATCH v3 2/6] libxl_create: make 'soft reset' explicit Paul Durrant
2020-01-16  9:35 ` Paul Durrant [this message]
2020-01-16 18:27   ` [Xen-devel] [PATCH v3 3/6] libxl: add infrastructure to track and query 'retired' domids Ian Jackson
2020-01-17  9:26     ` Durrant, Paul
2020-01-17 11:31       ` Ian Jackson
2020-01-16  9:36 ` [Xen-devel] [PATCH v3 4/6] libxl: allow creation of domains with a specified or random domid Paul Durrant
2020-01-16  9:40   ` Jan Beulich
2020-01-16  9:46     ` Durrant, Paul
2020-01-16  9:59       ` Jan Beulich
2020-01-16 15:53   ` Jason Andryuk
2020-01-16 18:36   ` Ian Jackson
2020-01-17  9:37     ` Durrant, Paul
2020-01-17 11:35       ` Ian Jackson
2020-01-17 12:06         ` Durrant, Paul
2020-01-17 15:30           ` Ian Jackson
2020-01-20  8:18             ` Durrant, Paul
2020-01-16  9:36 ` [Xen-devel] [PATCH v3 5/6] xl.conf: introduce 'domid_policy' Paul Durrant
2020-01-16 18:37   ` Ian Jackson
2020-01-16  9:36 ` [Xen-devel] [PATCH v3 6/6] xl: allow domid to be preserved on save/restore or migrate Paul Durrant
2020-01-16 18:39   ` Ian Jackson
2020-01-16 18:43 ` [Xen-devel] [PATCH v3 0/6] xl/libxl: domid allocation/preservation changes Ian Jackson
2020-01-17  9:11   ` Durrant, Paul

Reply instructions:

You may reply publically 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=20200116093602.4203-4-pdurrant@amazon.com \
    --to=pdurrant@amazon.com \
    --cc=anthony.perard@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=wl@xen.org \
    --cc=xen-devel@lists.xenproject.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

Xen-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/xen-devel/0 xen-devel/git/0.git
	git clone --mirror https://lore.kernel.org/xen-devel/1 xen-devel/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 xen-devel xen-devel/ https://lore.kernel.org/xen-devel \
		xen-devel@lists.xenproject.org xen-devel@lists.xen.org
	public-inbox-index xen-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.xenproject.lists.xen-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git