On 05/29/2013 11:21 PM, Serge Hallyn wrote: > And update the comment explaining the locking. > > Also take memlock in want_daemonize. > > Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com>
Is that patch still relevant? It doesn't appear to have been reviewed/applied to staging and touches bits that have been changed with more recent patches, so just want to confirm that I can ignore it. > --- > src/lxc/lxccontainer.c | 153 > +++++++++++++++++++++++++++++++++++++------------ > 1 file changed, 115 insertions(+), 38 deletions(-) > > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c > index 9bc1caf..145ed7c 100644 > --- a/src/lxc/lxccontainer.c > +++ b/src/lxc/lxccontainer.c > @@ -131,7 +131,12 @@ void remove_partial(struct lxc_container *c, int fd) > char *path = alloca(len); > int ret; > > + if (process_lock()) { > + ERROR("Failed getting process lock"); > + return; > + } > close(fd); > + process_unlock(); > ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name); > if (ret < 0 || ret >= len) { > ERROR("Error writing partial pathname"); > @@ -145,11 +150,11 @@ void remove_partial(struct lxc_container *c, int fd) > } > > /* LOCKING > - * 1. c->privlock protects the struct lxc_container from multiple threads. > - * 2. c->slock protects the on-disk container data > + * 1. container_mem_lock(c) protects the struct lxc_container from multiple > threads. > + * 2. container_disk_lock(c) protects the on-disk container data - in > particular the > + * container configuration file. > + * The container_disk_lock also takes the container_mem_lock. > * 3. thread_mutex protects process data (ex: fd table) from multiple threads > - * slock is an flock, which does not exclude threads. Therefore slock should > - * always be wrapped inside privlock. > * NOTHING mutexes two independent programs with their own struct > * lxc_container for the same c->name, between API calls. For instance, > * c->config_read(); c->start(); Between those calls, data on disk > @@ -160,7 +165,7 @@ void remove_partial(struct lxc_container *c, int fd) > * due to hung callers. So I prefer to keep the locks only within our own > * functions, not across functions. > * > - * If you're going to fork while holding a lxccontainer, increment > + * If you're going to clone while holding a lxccontainer, increment > * c->numthreads (under privlock) before forking. When deleting, > * decrement numthreads under privlock, then if it hits 0 you can delete. > * Do not ever use a lxccontainer whose numthreads you did not bump. > @@ -358,11 +363,14 @@ static pid_t lxcapi_init_pid(struct lxc_container *c) > > static bool load_config_locked(struct lxc_container *c, const char *fname) > { > + bool ret = false; > if (!c->lxc_conf) > c->lxc_conf = lxc_conf_init(); > + process_lock(); > if (c->lxc_conf && !lxc_config_read(fname, c->lxc_conf)) > - return true; > - return false; > + ret = true; > + process_unlock(); > + return ret; > } > > static bool lxcapi_load_config(struct lxc_container *c, const char *alt_file) > @@ -406,7 +414,12 @@ static void lxcapi_want_daemonize(struct lxc_container > *c) > { > if (!c) > return; > + if (!container_mem_lock(c)) { > + ERROR("Error getting mem lock"); > + return; > + } > c->daemonize = 1; > + container_mem_unlock(c); > } > > static bool lxcapi_wait(struct lxc_container *c, const char *state, int > timeout) > @@ -512,6 +525,7 @@ static bool lxcapi_start(struct lxc_container *c, int > useinit, char * const argv > process_unlock(); > return ret; > } > + // In a forked task, no longer threaded > process_unlock(); > /* second fork to be reparented by init */ > pid = fork(); > @@ -1023,7 +1037,9 @@ char** lxcapi_get_ips(struct lxc_container *c, char* > interface, char* family, in > goto out; > > /* Save reference to old netns */ > + process_lock(); > old_netns = open("/proc/self/ns/net", O_RDONLY); > + process_unlock(); > if (old_netns < 0) { > SYSERROR("failed to open /proc/self/ns/net"); > goto out; > @@ -1034,7 +1050,9 @@ char** lxcapi_get_ips(struct lxc_container *c, char* > interface, char* family, in > if (ret < 0 || ret >= MAXPATHLEN) > goto out; > > + process_lock(); > new_netns = open(new_netns_path, O_RDONLY); > + process_unlock(); > if (new_netns < 0) { > SYSERROR("failed to open %s", new_netns_path); > goto out; > @@ -1097,10 +1115,12 @@ out: > /* Switch back to original netns */ > if (old_netns >= 0 && setns(old_netns, CLONE_NEWNET)) > SYSERROR("failed to setns"); > + process_lock(); > if (new_netns >= 0) > close(new_netns); > if (old_netns >= 0) > close(old_netns); > + process_unlock(); > > /* Append NULL to the array */ > if (count) { > @@ -1194,11 +1214,15 @@ static bool lxcapi_save_config(struct lxc_container > *c, const char *alt_file) > if (lret) > return false; > > + process_lock(); > fout = fopen(alt_file, "w"); > + process_unlock(); > if (!fout) > goto out; > write_config(fout, c->lxc_conf); > + process_lock(); > fclose(fout); > + process_unlock(); > ret = true; > > out: > @@ -1214,16 +1238,13 @@ static bool lxcapi_destroy(struct lxc_container *c) > { > struct bdev *r = NULL; > bool ret = false; > + int v; > > if (!c || !lxcapi_is_defined(c)) > return false; > > - if (lxclock(c->privlock, 0)) > + if (container_disk_lock(c)) > return false; > - if (lxclock(c->slock, 0)) { > - lxcunlock(c->privlock); > - return false; > - } > > if (!is_stopped(c)) { > // we should queue some sort of error - in c->error_string? > @@ -1231,10 +1252,16 @@ static bool lxcapi_destroy(struct lxc_container *c) > goto out; > } > > - if (c->lxc_conf->rootfs.path && c->lxc_conf->rootfs.mount) > + if (c->lxc_conf->rootfs.path && c->lxc_conf->rootfs.mount) { > + process_lock(); > r = bdev_init(c->lxc_conf->rootfs.path, > c->lxc_conf->rootfs.mount, NULL); > + process_unlock(); > + } > if (r) { > - if (r->ops->destroy(r) < 0) { > + process_lock(); > + v = r->ops->destroy(r); > + process_unlock(); > + if (v < 0) { > ERROR("Error destroying rootfs for %s", c->name); > goto out; > } > @@ -1243,15 +1270,17 @@ static bool lxcapi_destroy(struct lxc_container *c) > const char *p1 = lxcapi_get_config_path(c); > char *path = alloca(strlen(p1) + strlen(c->name) + 2); > sprintf(path, "%s/%s", p1, c->name); > - if (lxc_rmdir_onedev(path) < 0) { > + process_lock(); > + v = lxc_rmdir_onedev(path); > + process_unlock(); > + if (v < 0) { > ERROR("Error destroying container directory for %s", c->name); > goto out; > } > ret = true; > > out: > - lxcunlock(c->privlock); > - lxcunlock(c->slock); > + container_disk_unlock(c); > return ret; > } > > @@ -1374,23 +1403,17 @@ err: > static bool lxcapi_set_cgroup_item(struct lxc_container *c, const char > *subsys, const char *value) > { > int ret; > - bool b = false; > > if (!c) > return false; > > - if (container_mem_lock(c)) > - return false; > - > if (is_stopped(c)) > - goto err; > + return false; > > + process_lock(); > ret = lxc_cgroup_set(c->name, subsys, value, c->config_path); > - if (!ret) > - b = true; > -err: > - container_mem_unlock(c); > - return b; > + process_unlock(); > + return ret == 0; > } > > static int lxcapi_get_cgroup_item(struct lxc_container *c, const char > *subsys, char *retv, int inlen) > @@ -1400,32 +1423,41 @@ static int lxcapi_get_cgroup_item(struct > lxc_container *c, const char *subsys, c > if (!c || !c->lxc_conf) > return -1; > > - if (container_mem_lock(c)) > - return -1; > - > if (is_stopped(c)) > - goto out; > + return -1; > > + process_lock(); > ret = lxc_cgroup_get(c->name, subsys, retv, inlen, c->config_path); > + process_unlock(); > > -out: > - container_mem_unlock(c); > return ret; > } > > const char *lxc_get_default_config_path(void) > { > - return default_lxc_path(); > + const char *ret; > + process_lock(); > + ret = default_lxc_path(); > + process_unlock(); > + return ret; > } > > const char *lxc_get_default_lvm_vg(void) > { > - return default_lvm_vg(); > + const char *ret; > + process_lock(); > + ret = default_lvm_vg(); > + process_unlock(); > + return ret; > } > > const char *lxc_get_default_zfs_root(void) > { > - return default_zfs_root(); > + const char *ret; > + process_lock(); > + ret = default_zfs_root(); > + process_unlock(); > + return ret; > } > > const char *lxc_get_version(void) > @@ -1450,12 +1482,16 @@ static int copy_file(char *old, char *new) > return -1; > } > > + process_lock(); > in = open(old, O_RDONLY); > + process_unlock(); > if (in < 0) { > SYSERROR("opening original file %s", old); > return -1; > } > + process_lock(); > out = open(new, O_CREAT | O_EXCL | O_WRONLY, 0644); > + process_unlock(); > if (out < 0) { > SYSERROR("opening new file %s", new); > close(in); > @@ -1476,8 +1512,10 @@ static int copy_file(char *old, char *new) > goto err; > } > } > + process_lock(); > close(in); > close(out); > + process_unlock(); > > // we set mode, but not owner/group > ret = chmod(new, sbuf.st_mode); > @@ -1489,8 +1527,10 @@ static int copy_file(char *old, char *new) > return 0; > > err: > + process_lock(); > close(in); > close(out); > + process_unlock(); > return -1; > } > > @@ -1547,48 +1587,67 @@ static int update_name_and_paths(const char *path, > struct lxc_container *oldc, > const char *p0, *p1, *p2, *end; > const char *oldpath = oldc->get_config_path(oldc); > const char *oldname = oldc->name; > + int ret; > > + process_lock(); > f = fopen(path, "r"); > + process_unlock(); > if (!f) { > SYSERROR("opening old config"); > return -1; > } > if (fseek(f, 0, SEEK_END) < 0) { > SYSERROR("seeking to end of old config"); > + process_lock(); > fclose(f); > + process_unlock(); > return -1; > } > flen = ftell(f); > if (flen < 0) { > + process_lock(); > fclose(f); > + process_unlock(); > SYSERROR("telling size of old config"); > return -1; > } > if (fseek(f, 0, SEEK_SET) < 0) { > + process_lock(); > fclose(f); > + process_unlock(); > SYSERROR("rewinding old config"); > return -1; > } > contents = malloc(flen+1); > if (!contents) { > SYSERROR("out of memory"); > + process_lock(); > fclose(f); > + process_unlock(); > return -1; > } > if (fread(contents, 1, flen, f) != flen) { > free(contents); > + process_lock(); > fclose(f); > + process_unlock(); > SYSERROR("reading old config"); > return -1; > } > contents[flen] = '\0'; > - if (fclose(f) < 0) { > + > + process_lock(); > + ret = fclose(f); > + process_unlock(); > + if (ret < 0) { > free(contents); > SYSERROR("closing old config"); > return -1; > } > > + process_lock(); > f = fopen(path, "w"); > + process_unlock(); > if (!f) { > SYSERROR("reopening config"); > free(contents); > @@ -1605,11 +1664,15 @@ static int update_name_and_paths(const char *path, > struct lxc_container *oldc, > if (fwrite(p0, 1, (end-p0), f) != (end-p0)) { > SYSERROR("writing new config"); > free(contents); > + process_lock(); > fclose(f); > + process_unlock(); > return -1; > } > free(contents); > + process_lock(); > fclose(f); > + process_unlock(); > // success > return 0; > } else { > @@ -1618,7 +1681,9 @@ static int update_name_and_paths(const char *path, > struct lxc_container *oldc, > if (fwrite(p0, 1, (p-p0), f) != (p-p0)) { > SYSERROR("writing new config"); > free(contents); > + process_lock(); > fclose(f); > + process_unlock(); > return -1; > } > p0 = p; > @@ -1626,7 +1691,9 @@ static int update_name_and_paths(const char *path, > struct lxc_container *oldc, > if (fwrite(new, 1, strlen(new), f) != strlen(new)) { > SYSERROR("writing new name or path in new > config"); > free(contents); > + process_lock(); > fclose(f); > + process_unlock(); > return -1; > } > p0 += (p == p2) ? strlen(oldname) : strlen(oldpath); > @@ -1671,13 +1738,19 @@ static int copyhooks(struct lxc_container *oldc, > struct lxc_container *c) > > static void new_hwaddr(char *hwaddr) > { > - FILE *f = fopen("/dev/urandom", "r"); > + FILE *f; > + > + process_lock(); > + f = fopen("/dev/urandom", "r"); > + process_unlock(); > if (f) { > unsigned int seed; > int ret = fread(&seed, sizeof(seed), 1, f); > if (ret != 1) > seed = time(NULL); > + process_lock(); > fclose(f); > + process_unlock(); > srand(seed); > } else > srand(time(NULL)); > @@ -1891,13 +1964,17 @@ struct lxc_container *lxcapi_clone(struct > lxc_container *c, const char *newname, > } > > // copy the configuration, tweak it as needed, > + process_lock(); > fout = fopen(newpath, "w"); > + process_unlock(); > if (!fout) { > SYSERROR("open %s", newpath); > goto out; > } > write_config(fout, c->lxc_conf); > + process_lock(); > fclose(fout); > + process_unlock(); > > if (update_name_and_paths(newpath, c, n, l) < 0) { > ERROR("Error updating name in cloned config"); > -- Stéphane Graber Ubuntu developer http://www.ubuntu.com
signature.asc
Description: OpenPGP digital signature
------------------------------------------------------------------------------ Get 100% visibility into Java/.NET code with AppDynamics Lite It's a free troubleshooting tool designed for production Get down to code-level detail for bottlenecks, with <2% overhead. Download for free and get started troubleshooting in minutes. http://p.sf.net/sfu/appdyn_d2d_ap2
_______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel