debuggers.hg

changeset 22250:d4a30bee5701

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>
author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
date Wed Sep 22 18:02:36 2010 +0100 (2010-09-22)
parents afe7d12da941
children e01600ac7295
files tools/examples/xl.conf tools/libxl/xl.c tools/libxl/xl.h tools/libxl/xl_cmdimpl.c
line diff
     1.1 --- a/tools/examples/xl.conf	Wed Sep 22 17:55:38 2010 +0100
     1.2 +++ b/tools/examples/xl.conf	Wed Sep 22 18:02:36 2010 +0100
     1.3 @@ -3,3 +3,6 @@
     1.4  # automatically balloon down dom0 when xen doesn't have enough free
     1.5  # memory to create a domain
     1.6  #autoballon=1
     1.7 +
     1.8 +# full path of the lockfile used by xl during domain creation
     1.9 +#lockfile="/var/lock/xl"
     2.1 --- a/tools/libxl/xl.c	Wed Sep 22 17:55:38 2010 +0100
     2.2 +++ b/tools/libxl/xl.c	Wed Sep 22 18:02:36 2010 +0100
     2.3 @@ -34,6 +34,7 @@
     2.4  
     2.5  xentoollog_logger_stdiostream *logger;
     2.6  int autoballoon = 1;
     2.7 +char *lockfile;
     2.8  
     2.9  static xentoollog_level minmsglevel = XTL_PROGRESS;
    2.10  
    2.11 @@ -44,6 +45,7 @@ static void parse_global_config(const ch
    2.12      long l;
    2.13      XLU_Config *config;
    2.14      int e;
    2.15 +    const char *buf;
    2.16  
    2.17      config = xlu_cfg_init(stderr, configfile);
    2.18      if (!config) {
    2.19 @@ -60,6 +62,16 @@ static void parse_global_config(const ch
    2.20      if (!xlu_cfg_get_long (config, "autoballoon", &l))
    2.21          autoballoon = l;
    2.22  
    2.23 +    if (!xlu_cfg_get_string (config, "lockfile", &buf))
    2.24 +        lockfile = strdup(buf);
    2.25 +    else {
    2.26 +        e = asprintf(&lockfile, "%s/xl", (char *)libxl_lock_dir_path());
    2.27 +        if (e < 0) {
    2.28 +            fprintf(stderr, "asprintf memory allocation failed\n");
    2.29 +            exit(1);
    2.30 +        }
    2.31 +    }
    2.32 +
    2.33      xlu_cfg_destroy(config);
    2.34  }
    2.35   
     3.1 --- a/tools/libxl/xl.h	Wed Sep 22 17:55:38 2010 +0100
     3.2 +++ b/tools/libxl/xl.h	Wed Sep 22 18:02:36 2010 +0100
     3.3 @@ -92,5 +92,6 @@ extern xentoollog_logger_stdiostream *lo
     3.4  
     3.5  /* global options */
     3.6  extern int autoballoon;
     3.7 +extern char *lockfile;
     3.8  
     3.9  #endif /* XL_H */
     4.1 --- a/tools/libxl/xl_cmdimpl.c	Wed Sep 22 17:55:38 2010 +0100
     4.2 +++ b/tools/libxl/xl_cmdimpl.c	Wed Sep 22 18:02:36 2010 +0100
     4.3 @@ -68,6 +68,7 @@ libxl_ctx ctx;
     4.4  /* when we operate on a domain, it is this one: */
     4.5  static uint32_t domid;
     4.6  static const char *common_domname;
     4.7 +static int fd_lock = -1;
     4.8  
     4.9  
    4.10  static const char savefileheader_magic[32]=
    4.11 @@ -234,6 +235,65 @@ static void find_domain(const char *p)
    4.12      common_domname = was_name ? p : libxl_domid_to_name(&ctx, domid);
    4.13  }
    4.14  
    4.15 +static int acquire_lock(void)
    4.16 +{
    4.17 +    int rc;
    4.18 +    struct flock fl;
    4.19 +
    4.20 +    /* lock already acquired */
    4.21 +    if (fd_lock >= 0)
    4.22 +        return ERROR_INVAL;
    4.23 +
    4.24 +    fl.l_type = F_WRLCK;
    4.25 +    fl.l_whence = SEEK_SET;
    4.26 +    fl.l_start = 0;
    4.27 +    fl.l_len = 0;
    4.28 +    fd_lock = open(lockfile, O_WRONLY|O_CREAT, S_IWUSR);
    4.29 +    if (fd_lock < 0) {
    4.30 +        fprintf(stderr, "cannot open the lockfile %s errno=%d\n", lockfile, errno);
    4.31 +        return ERROR_FAIL;
    4.32 +    }
    4.33 +get_lock:
    4.34 +    rc = fcntl(fd_lock, F_SETLKW, &fl);
    4.35 +    if (rc < 0 && errno == EINTR)
    4.36 +        goto get_lock;
    4.37 +    if (rc < 0) {
    4.38 +        fprintf(stderr, "cannot acquire lock %s errno=%d\n", lockfile, errno);
    4.39 +        rc = ERROR_FAIL;
    4.40 +    } else
    4.41 +        rc = 0;
    4.42 +    return rc;
    4.43 +}
    4.44 +
    4.45 +static int release_lock(void)
    4.46 +{
    4.47 +    int rc;
    4.48 +    struct flock fl;
    4.49 +
    4.50 +    /* lock not acquired */
    4.51 +    if (fd_lock < 0)
    4.52 +        return ERROR_INVAL;
    4.53 +
    4.54 +release_lock:
    4.55 +    fl.l_type = F_UNLCK;
    4.56 +    fl.l_whence = SEEK_SET;
    4.57 +    fl.l_start = 0;
    4.58 +    fl.l_len = 0;
    4.59 +
    4.60 +    rc = fcntl(fd_lock, F_SETLKW, &fl);
    4.61 +    if (rc < 0 && errno == EINTR)
    4.62 +        goto release_lock;
    4.63 +    if (rc < 0) {
    4.64 +        fprintf(stderr, "cannot release lock %s, errno=%d\n", lockfile, errno);
    4.65 +        rc = ERROR_FAIL;
    4.66 +    } else
    4.67 +        rc = 0;
    4.68 +    close(fd_lock);
    4.69 +    fd_lock = -1;
    4.70 +
    4.71 +    return rc;
    4.72 +}
    4.73 +
    4.74  #define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
    4.75  
    4.76  static void dolog(const char *file, int line, const char *func, char *fmt, ...)
    4.77 @@ -1213,6 +1273,48 @@ struct domain_create {
    4.78      char **migration_domname_r; /* from malloc */
    4.79  };
    4.80  
    4.81 +static int freemem(libxl_domain_build_info *b_info, libxl_device_model_info *dm_info)
    4.82 +{
    4.83 +    int rc, retries = 3;
    4.84 +    uint32_t need_memkb, free_memkb;
    4.85 +
    4.86 +    if (!autoballoon)
    4.87 +        return 0;
    4.88 +
    4.89 +    rc = libxl_domain_need_memory(&ctx, b_info, dm_info, &need_memkb);
    4.90 +    if (rc < 0)
    4.91 +        return rc;
    4.92 +
    4.93 +    do {
    4.94 +        rc = libxl_get_free_memory(&ctx, &free_memkb);
    4.95 +        if (rc < 0)
    4.96 +            return rc;
    4.97 +
    4.98 +        if (free_memkb >= need_memkb)
    4.99 +            return 0;
   4.100 +
   4.101 +        rc = libxl_set_memory_target(&ctx, 0, free_memkb - need_memkb, 1, 0);
   4.102 +        if (rc < 0)
   4.103 +            return rc;
   4.104 +
   4.105 +        rc = libxl_wait_for_free_memory(&ctx, domid, need_memkb, 10);
   4.106 +        if (!rc)
   4.107 +            return 0;
   4.108 +        else if (rc != ERROR_NOMEM)
   4.109 +            return rc;
   4.110 +
   4.111 +        /* the memory target has been reached but the free memory is still
   4.112 +         * not enough: loop over again */
   4.113 +        rc = libxl_wait_for_memory_target(&ctx, 0, 1);
   4.114 +        if (rc < 0)
   4.115 +            return rc;
   4.116 +
   4.117 +        retries--;
   4.118 +    } while (retries > 0);
   4.119 +
   4.120 +    return ERROR_NOMEM;
   4.121 +}
   4.122 +
   4.123  static int create_domain(struct domain_create *dom_info)
   4.124  {
   4.125      struct domain_config d_config;
   4.126 @@ -1372,6 +1474,17 @@ static int create_domain(struct domain_c
   4.127  start:
   4.128      domid = 0;
   4.129  
   4.130 +    rc = acquire_lock();
   4.131 +    if (rc < 0)
   4.132 +        goto error_out;
   4.133 +
   4.134 +    ret = freemem(&d_config.b_info, &dm_info);
   4.135 +    if (ret < 0) {
   4.136 +        fprintf(stderr, "failed to free memory for the domain\n");
   4.137 +        ret = ERROR_FAIL;
   4.138 +        goto error_out;
   4.139 +    }
   4.140 +
   4.141      ret = libxl_domain_make(&ctx, &d_config.c_info, &domid);
   4.142      if (ret) {
   4.143          fprintf(stderr, "cannot make domain: %d\n", ret);
   4.144 @@ -1482,6 +1595,8 @@ start:
   4.145              goto error_out;
   4.146      }
   4.147  
   4.148 +    release_lock();
   4.149 +
   4.150      if (!paused)
   4.151          libxl_domain_unpause(&ctx, domid);
   4.152  
   4.153 @@ -1619,6 +1734,7 @@ start:
   4.154      }
   4.155  
   4.156  error_out:
   4.157 +    release_lock();
   4.158      if (domid)
   4.159          libxl_domain_destroy(&ctx, domid, 0);
   4.160