[lxc-devel] [PATCH 1/1] lxccontainer: don't lock around getstate and freeze/unfreeze (v2)

Dwight Engen dwight.engen at oracle.com
Wed May 29 17:49:38 UTC 2013


On Wed, 29 May 2013 12:26:25 -0500
Serge Hallyn <serge.hallyn at ubuntu.com> wrote:

> Those go through commands.c and are already mutex'ed that way.
> 
> Also remove a unmatched container_disk_unlock in lxcapi_create.
> 
> Since is_stopped uses getstate which is no longer locked, rename
> it to drop the _locked suffix.
> 
> And convert save_config to taking the disk lock.  This way the
> save_ and load_config are mutexing each other, as they should.
> 
> Changelog: May 29:
>    Per Dwight's comment, take the lock before opening the config
>       FILE *.
>    Only take disklock at load and save_config when we're using the
>    container's config file, not when read/writing from/to another
>    file.
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

Acked-by: Dwight Engen <dwight.engen at oracle.com>

> ---
>  src/lxc/lxccontainer.c | 92
> +++++++++++++++++++++++++++++++++----------------- 1 file changed, 61
> insertions(+), 31 deletions(-)
> 
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index b34b8e8..ef95033 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -287,21 +287,15 @@ out:
>  
>  static const char *lxcapi_state(struct lxc_container *c)
>  {
> -	const char *ret;
>  	lxc_state_t s;
>  
>  	if (!c)
>  		return NULL;
> -	if (container_disk_lock(c))
> -		return NULL;
>  	s = lxc_getstate(c->name, c->config_path);
> -	ret = lxc_state2str(s);
> -	container_disk_unlock(c);
> -
> -	return ret;
> +	return lxc_state2str(s);
>  }
>  
> -static bool is_stopped_locked(struct lxc_container *c)
> +static bool is_stopped(struct lxc_container *c)
>  {
>  	lxc_state_t s;
>  	s = lxc_getstate(c->name, c->config_path);
> @@ -326,10 +320,7 @@ static bool lxcapi_freeze(struct lxc_container
> *c) if (!c)
>  		return false;
>  
> -	if (container_disk_lock(c))
> -		return false;
>  	ret = lxc_freeze(c->name, c->config_path);
> -	container_disk_unlock(c);
>  	if (ret)
>  		return false;
>  	return true;
> @@ -341,10 +332,7 @@ static bool lxcapi_unfreeze(struct lxc_container
> *c) if (!c)
>  		return false;
>  
> -	if (container_disk_lock(c))
> -		return false;
>  	ret = lxc_unfreeze(c->name, c->config_path);
> -	container_disk_unlock(c);
>  	if (ret)
>  		return false;
>  	return true;
> @@ -369,7 +357,8 @@ static bool load_config_locked(struct
> lxc_container *c, const char *fname) 
>  static bool lxcapi_load_config(struct lxc_container *c, const char
> *alt_file) {
> -	bool ret = false;
> +	bool ret = false, need_disklock = false;
> +	int lret;
>  	const char *fname;
>  	if (!c)
>  		return false;
> @@ -379,10 +368,27 @@ static bool lxcapi_load_config(struct
> lxc_container *c, const char *alt_file) fname = alt_file;
>  	if (!fname)
>  		return false;
> -	if (container_disk_lock(c))
> +	/*
> +	 * If we're reading something other than the container's
> config,
> +	 * we only need to lock the in-memory container.  If loading
> the
> +	 * container's config file, take the disk lock.
> +	 */
> +	if (strcmp(fname, c->configfile) == 0)
> +		need_disklock = true;
> +
> +	if (need_disklock)
> +		lret = container_disk_lock(c);
> +	else
> +		lret = container_mem_lock(c);
> +	if (lret)
>  		return false;
> +
>  	ret = load_config_locked(c, fname);
> -	container_disk_unlock(c);
> +
> +	if (need_disklock)
> +		container_disk_unlock(c);
> +	else
> +		container_mem_unlock(c);
>  	return ret;
>  }
>  
> @@ -888,7 +894,6 @@ static bool lxcapi_create(struct lxc_container
> *c, const char *t, out_unlock:
>  	if (partial_fd >= 0)
>  		remove_partial(c, partial_fd);
> -	container_disk_unlock(c);
>  out:
>  	if (tpath)
>  		free(tpath);
> @@ -1143,30 +1148,55 @@ static int lxcapi_get_keys(struct
> lxc_container *c, const char *key, char *retv, #define
> LXC_DEFAULT_CONFIG "/etc/lxc/default.conf" static bool
> lxcapi_save_config(struct lxc_container *c, const char *alt_file) {
> +	FILE *fout;
> +	bool ret = false, need_disklock = false;
> +	int lret;
> +
>  	if (!alt_file)
>  		alt_file = c->configfile;
>  	if (!alt_file)
>  		return false;  // should we write to stdout if no
> file is specified?
> -	if (!c->lxc_conf)
> +
> +	// If we haven't yet loaded a config, load the stock config
> +	if (!c->lxc_conf) {
>  		if (!c->load_config(c, LXC_DEFAULT_CONFIG)) {
>  			ERROR("Error loading default configuration
> file %s while saving %s\n", LXC_DEFAULT_CONFIG, c->name); return
> false; }
> +	}
>  
>  	if (!create_container_dir(c))
>  		return false;
>  
> -	FILE *fout = fopen(alt_file, "w");
> -	if (!fout)
> -		return false;
> -	if (container_mem_lock(c)) {
> -		fclose(fout);
> +	/*
> +	 * If we're writing to the container's config file, take the
> +	 * disk lock.  Otherwise just take the memlock to protect the
> +	 * struct lxc_container while we're traversing it.
> +	 */
> +	if (strcmp(c->configfile, alt_file) == 0)
> +		need_disklock = true;
> +
> +	if (need_disklock)
> +		lret = container_disk_lock(c);
> +	else
> +		lret = container_mem_lock(c);
> +
> +	if (lret)
>  		return false;
> -	}
> +
> +	fout = fopen(alt_file, "w");
> +	if (!fout)
> +		goto out;
>  	write_config(fout, c->lxc_conf);
>  	fclose(fout);
> -	container_mem_unlock(c);
> -	return true;
> +	ret = true;
> +
> +out:
> +	if (need_disklock)
> +		container_disk_unlock(c);
> +	else
> +		container_mem_unlock(c);
> +	return ret;
>  }
>  
>  // do we want the api to support --force, or leave that to the
> caller? @@ -1185,7 +1215,7 @@ static bool lxcapi_destroy(struct
> lxc_container *c) return false;
>  	}
>  
> -	if (!is_stopped_locked(c)) {
> +	if (!is_stopped(c)) {
>  		// we should queue some sort of error - in
> c->error_string? ERROR("container %s is not stopped", c->name);
>  		goto out;
> @@ -1342,7 +1372,7 @@ static bool lxcapi_set_cgroup_item(struct
> lxc_container *c, const char *subsys, if (container_mem_lock(c))
>  		return false;
>  
> -	if (is_stopped_locked(c))
> +	if (is_stopped(c))
>  		goto err;
>  
>  	ret = lxc_cgroup_set(c->name, subsys, value, c->config_path);
> @@ -1363,7 +1393,7 @@ static int lxcapi_get_cgroup_item(struct
> lxc_container *c, const char *subsys, c if (container_mem_lock(c))
>  		return -1;
>  
> -	if (is_stopped_locked(c))
> +	if (is_stopped(c))
>  		goto out;
>  
>  	ret = lxc_cgroup_get(c->name, subsys, retv, inlen,
> c->config_path); @@ -1827,7 +1857,7 @@ struct lxc_container
> *lxcapi_clone(struct lxc_container *c, const char *newname, if
> (container_mem_lock(c)) return NULL;
>  
> -	if (!is_stopped_locked(c)) {
> +	if (!is_stopped(c)) {
>  		ERROR("error: Original container (%s) is running",
> c->name); goto out;
>  	}





More information about the lxc-devel mailing list