aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2010-09-22 18:02:36 +0100
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2010-09-22 18:02:36 +0100
commitea4dce89d478d62341cd2f9d8944e215f7086144 (patch)
treeb876308b4100df10cf2347265339e5bb66a87b1d /tools
parent2dbb423e17aa902de141cc735f0c496f65cd89ba (diff)
downloadxen-ea4dce89d478d62341cd2f9d8944e215f7086144.tar.gz
xen-ea4dce89d478d62341cd2f9d8944e215f7086144.tar.bz2
xen-ea4dce89d478d62341cd2f9d8944e215f7086144.zip
xl: free memory before building a domain
Free the needed amount of memory before proceeding with the domain build. Use a filelock to prevent other xl instances from conflicting during this operation. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/examples/xl.conf3
-rw-r--r--tools/libxl/xl.c12
-rw-r--r--tools/libxl/xl.h1
-rw-r--r--tools/libxl/xl_cmdimpl.c116
4 files changed, 132 insertions, 0 deletions
diff --git a/tools/examples/xl.conf b/tools/examples/xl.conf
index c7bf8c045a..a17069b812 100644
--- a/tools/examples/xl.conf
+++ b/tools/examples/xl.conf
@@ -3,3 +3,6 @@
# automatically balloon down dom0 when xen doesn't have enough free
# memory to create a domain
#autoballon=1
+
+# full path of the lockfile used by xl during domain creation
+#lockfile="/var/lock/xl"
diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c
index 345f4a5f35..2ad117f56d 100644
--- a/tools/libxl/xl.c
+++ b/tools/libxl/xl.c
@@ -34,6 +34,7 @@
xentoollog_logger_stdiostream *logger;
int autoballoon = 1;
+char *lockfile;
static xentoollog_level minmsglevel = XTL_PROGRESS;
@@ -44,6 +45,7 @@ static void parse_global_config(const char *configfile,
long l;
XLU_Config *config;
int e;
+ const char *buf;
config = xlu_cfg_init(stderr, configfile);
if (!config) {
@@ -60,6 +62,16 @@ static void parse_global_config(const char *configfile,
if (!xlu_cfg_get_long (config, "autoballoon", &l))
autoballoon = l;
+ if (!xlu_cfg_get_string (config, "lockfile", &buf))
+ lockfile = strdup(buf);
+ else {
+ e = asprintf(&lockfile, "%s/xl", (char *)libxl_lock_dir_path());
+ if (e < 0) {
+ fprintf(stderr, "asprintf memory allocation failed\n");
+ exit(1);
+ }
+ }
+
xlu_cfg_destroy(config);
}
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 55f83599f9..ad3adafb34 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -92,5 +92,6 @@ extern xentoollog_logger_stdiostream *logger;
/* global options */
extern int autoballoon;
+extern char *lockfile;
#endif /* XL_H */
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 2c1e88fc7f..83dda9627a 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -68,6 +68,7 @@ libxl_ctx ctx;
/* when we operate on a domain, it is this one: */
static uint32_t domid;
static const char *common_domname;
+static int fd_lock = -1;
static const char savefileheader_magic[32]=
@@ -234,6 +235,65 @@ static void find_domain(const char *p)
common_domname = was_name ? p : libxl_domid_to_name(&ctx, domid);
}
+static int acquire_lock(void)
+{
+ int rc;
+ struct flock fl;
+
+ /* lock already acquired */
+ if (fd_lock >= 0)
+ return ERROR_INVAL;
+
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fd_lock = open(lockfile, O_WRONLY|O_CREAT, S_IWUSR);
+ if (fd_lock < 0) {
+ fprintf(stderr, "cannot open the lockfile %s errno=%d\n", lockfile, errno);
+ return ERROR_FAIL;
+ }
+get_lock:
+ rc = fcntl(fd_lock, F_SETLKW, &fl);
+ if (rc < 0 && errno == EINTR)
+ goto get_lock;
+ if (rc < 0) {
+ fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
+ rc = ERROR_FAIL;
+ } else
+ rc = 0;
+ return rc;
+}
+
+static int release_lock(void)
+{
+ int rc;
+ struct flock fl;
+
+ /* lock not acquired */
+ if (fd_lock < 0)
+ return ERROR_INVAL;
+
+release_lock:
+ fl.l_type = F_UNLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+
+ rc = fcntl(fd_lock, F_SETLKW, &fl);
+ if (rc < 0 && errno == EINTR)
+ goto release_lock;
+ if (rc < 0) {
+ fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
+ rc = ERROR_FAIL;
+ } else
+ rc = 0;
+ close(fd_lock);
+ fd_lock = -1;
+
+ return rc;
+}
+
#define LOG(_f, _a...) dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
static void dolog(const char *file, int line, const char *func, char *fmt, ...)
@@ -1213,6 +1273,48 @@ struct domain_create {
char **migration_domname_r; /* from malloc */
};
+static int freemem(libxl_domain_build_info *b_info, libxl_device_model_info *dm_info)
+{
+ int rc, retries = 3;
+ uint32_t need_memkb, free_memkb;
+
+ if (!autoballoon)
+ return 0;
+
+ rc = libxl_domain_need_memory(&ctx, b_info, dm_info, &need_memkb);
+ if (rc < 0)
+ return rc;
+
+ do {
+ rc = libxl_get_free_memory(&ctx, &free_memkb);
+ if (rc < 0)
+ return rc;
+
+ if (free_memkb >= need_memkb)
+ return 0;
+
+ rc = libxl_set_memory_target(&ctx, 0, free_memkb - need_memkb, 1, 0);
+ if (rc < 0)
+ return rc;
+
+ rc = libxl_wait_for_free_memory(&ctx, domid, need_memkb, 10);
+ if (!rc)
+ return 0;
+ else if (rc != ERROR_NOMEM)
+ return rc;
+
+ /* the memory target has been reached but the free memory is still
+ * not enough: loop over again */
+ rc = libxl_wait_for_memory_target(&ctx, 0, 1);
+ if (rc < 0)
+ return rc;
+
+ retries--;
+ } while (retries > 0);
+
+ return ERROR_NOMEM;
+}
+
static int create_domain(struct domain_create *dom_info)
{
struct domain_config d_config;
@@ -1372,6 +1474,17 @@ static int create_domain(struct domain_create *dom_info)
start:
domid = 0;
+ rc = acquire_lock();
+ if (rc < 0)
+ goto error_out;
+
+ ret = freemem(&d_config.b_info, &dm_info);
+ if (ret < 0) {
+ fprintf(stderr, "failed to free memory for the domain\n");
+ ret = ERROR_FAIL;
+ goto error_out;
+ }
+
ret = libxl_domain_make(&ctx, &d_config.c_info, &domid);
if (ret) {
fprintf(stderr, "cannot make domain: %d\n", ret);
@@ -1482,6 +1595,8 @@ start:
goto error_out;
}
+ release_lock();
+
if (!paused)
libxl_domain_unpause(&ctx, domid);
@@ -1619,6 +1734,7 @@ start:
}
error_out:
+ release_lock();
if (domid)
libxl_domain_destroy(&ctx, domid, 0);