diff options
author | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2010-09-22 18:02:36 +0100 |
---|---|---|
committer | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2010-09-22 18:02:36 +0100 |
commit | ea4dce89d478d62341cd2f9d8944e215f7086144 (patch) | |
tree | b876308b4100df10cf2347265339e5bb66a87b1d | |
parent | 2dbb423e17aa902de141cc735f0c496f65cd89ba (diff) | |
download | xen-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>
-rw-r--r-- | tools/examples/xl.conf | 3 | ||||
-rw-r--r-- | tools/libxl/xl.c | 12 | ||||
-rw-r--r-- | tools/libxl/xl.h | 1 | ||||
-rw-r--r-- | tools/libxl/xl_cmdimpl.c | 116 |
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); |