mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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>
This commit is contained in:
1 parent
2dbb423e17
commit
ea4dce89d4
4 files changed
+132
No files matched your search
@@ -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"
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -92,5 +92,6 @@ extern xentoollog_logger_stdiostream *logger;
|
||||
|
||||
/* global options */
|
||||
extern int autoballoon;
|
||||
extern char *lockfile;
|
||||
|
||||
#endif /* XL_H */
|
||||
@@ -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);
|
||||
|
||||
|
||||