Hi Serge, On Tue, May 27, 2014 at 5:24 PM, Serge Hallyn <serge.hal...@ubuntu.com> wrote: > Originally we kept snapshots under /var/lib/lxcsnaps. If a > separate btrfs is mounted at /var/lib/lxc, then we can't > make btrfs snapshots under /var/lib/lxcsnaps. > > This patch moves the default directory to /var/lib/lxc/c/snaps. > If /var/lib/lxcsnaps already exists, then we continue to use that. > > add c->destroy_with_snapshots() and c->snapshot_destroy_all() > API methods. c->snashot_destroy_all() can be triggered from > lxc-snapshot using '-d ALL'. There is no command to call > c->destroy_with_snapshots(c) as of yet. > > lxclock: use ".$lxcname" for container lock files > that way we can use /run/lock/lxc/$lxcpath/$lxcname/snaps as a > directory when locking snapshots without having to worry about > /run/lock//lxc/$lxcpath/$lxcname being a file. > > destroy: split off a container_destroy > container_destroy() doesn't check for snapshots, so snapshot_rename can > use it. api_destroy() now does check for snapshots (previously it only > checked for fs - i.e. overlayfs/aufs - snapshots). > > Add destroy to the manpage, as it was previously undocumented. > > Update snapshot testcase accordingly. > > Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com>
This version is not cleanly getting applied on top of current master so I ended up modifying the patch locally. I might have introduced a problem or two while doing that cause my tests started to fail with this. Unfortunately I haven't been able to find some time to debug it further. Will try again and catch you on irc tomorrow. > --- > doc/lxc-snapshot.sgml.in | 13 +++ > src/lxc/bdev.c | 6 +- > src/lxc/lxc_snapshot.c | 11 ++- > src/lxc/lxccontainer.c | 217 > ++++++++++++++++++++++++++++++++++++++--------- > src/lxc/lxccontainer.h | 24 +++++- > src/lxc/lxclock.c | 10 +-- > src/lxc/utils.c | 39 +++++++-- > src/lxc/utils.h | 2 +- > src/tests/snapshot.c | 29 ++----- > 9 files changed, 271 insertions(+), 80 deletions(-) > > diff --git a/doc/lxc-snapshot.sgml.in b/doc/lxc-snapshot.sgml.in > index 4b70279..029534e 100644 > --- a/doc/lxc-snapshot.sgml.in > +++ b/doc/lxc-snapshot.sgml.in > @@ -55,6 +55,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, > MA 02110-1301 USA > <cmdsynopsis> > <command>lxc-snapshot</command> > <arg choice="req">-n, --name <replaceable>name</replaceable></arg> > + <arg choice="req">-d, -destroy > <replaceable>snapshot-name</replaceable></arg> > + </cmdsynopsis> > + <cmdsynopsis> > + <command>lxc-snapshot</command> > + <arg choice="req">-n, --name <replaceable>name</replaceable></arg> > <arg choice="req">-L, --list </arg> > <arg choice="opt">-C, --showcomments </arg> > </cmdsynopsis> > @@ -92,6 +97,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, > MA 02110-1301 USA > </varlistentry> > > <varlistentry> > + <term> <option>-d,--destroy snapshot-name</option> </term> > + <listitem> > + <para> Destroy the named snapshot. If the named snapshot is ALL, > then all snapshots > + will be destroyed.</para> > + </listitem> > + </varlistentry> > + > + <varlistentry> > <term> <option>-L,--list </option> </term> > <listitem> > <para> List existing snapshots. </para> > diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c > index 751fa9f..efdbecc 100644 > --- a/src/lxc/bdev.c > +++ b/src/lxc/bdev.c > @@ -482,7 +482,7 @@ static int dir_clonepaths(struct bdev *orig, struct bdev > *new, const char *oldna > > static int dir_destroy(struct bdev *orig) > { > - if (lxc_rmdir_onedev(orig->src) < 0) > + if (lxc_rmdir_onedev(orig->src, NULL) < 0) > return -1; > return 0; > } > @@ -2073,7 +2073,7 @@ static int overlayfs_destroy(struct bdev *orig) > if (!upper) > return -22; > upper++; > - return lxc_rmdir_onedev(upper); > + return lxc_rmdir_onedev(upper, NULL); > } > > /* > @@ -2350,7 +2350,7 @@ static int aufs_destroy(struct bdev *orig) > if (!upper) > return -22; > upper++; > - return lxc_rmdir_onedev(upper); > + return lxc_rmdir_onedev(upper, NULL); > } > > /* > diff --git a/src/lxc/lxc_snapshot.c b/src/lxc/lxc_snapshot.c > index 1f8fdaf..58288e0 100644 > --- a/src/lxc/lxc_snapshot.c > +++ b/src/lxc/lxc_snapshot.c > @@ -112,7 +112,13 @@ static int do_restore_snapshots(struct lxc_container *c) > > static int do_destroy_snapshots(struct lxc_container *c) > { > - if (c->snapshot_destroy(c, snapshot)) > + bool bret; > + if (strcmp(snapshot, "ALL") == 0) > + bret = c->snapshot_destroy_all(c); > + else > + bret = c->snapshot_destroy(c, snapshot); > + > + if (bret) > return 0; > > ERROR("Error destroying snapshot %s", snapshot); > @@ -154,7 +160,8 @@ Options :\n\ > -C, --showcomments show snapshot comments in list\n\ > -c, --comment=file add file as a comment\n\ > -r, --restore=name restore snapshot name, i.e. 'snap0'\n\ > - -d, --destroy=name destroy snapshot name, i.e. 'snap0'\n", > + -d, --destroy=name destroy snapshot name, i.e. 'snap0'\n\ > + use ALL to destroy all snapshots\n", > .options = my_longopts, > .parser = my_parser, > .checker = NULL, > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c > index fdac433..b0003d1 100644 > --- a/src/lxc/lxccontainer.c > +++ b/src/lxc/lxccontainer.c > @@ -1203,6 +1203,8 @@ static void lxcapi_clear_config(struct lxc_container *c) > } > > static bool lxcapi_destroy(struct lxc_container *c); > +static bool container_destroy(struct lxc_container *c); > +static bool get_snappath_dir(struct lxc_container *c, char *snappath); > /* > * lxcapi_create: > * create a container with the given parameters. > @@ -1344,7 +1346,7 @@ out_unlock: > remove_partial(c, partial_fd); > out: > if (!ret && c) > - lxcapi_destroy(c); > + container_destroy(c); > free_tpath: > if (tpath) > free(tpath); > @@ -1950,7 +1952,7 @@ out: > fclose(f); > } > > -static bool has_snapshots(struct lxc_container *c) > +static bool has_fs_snapshots(struct lxc_container *c) > { > char path[MAXPATHLEN]; > int ret, v; > @@ -1974,10 +1976,38 @@ out: > return bret; > } > > +static bool has_snapshots(struct lxc_container *c) > +{ > + char path[MAXPATHLEN]; > + struct dirent dirent, *direntp; > + int count=0; > + DIR *dir; > + > + if (!get_snappath_dir(c, path)) > + return false; > + dir = opendir(path); > + if (!dir) > + return false; > + while (!readdir_r(dir, &dirent, &direntp)) { > + if (!direntp) > + break; > + > + if (!strcmp(direntp->d_name, ".")) > + continue; > + > + if (!strcmp(direntp->d_name, "..")) > + continue; > + count++; > + break; > + } > + closedir(dir); > + return count > 0; > +} > + > static int lxc_rmdir_onedev_wrapper(void *data) > { > char *arg = (char *) data; > - return lxc_rmdir_onedev(arg); > + return lxc_rmdir_onedev(arg, "snaps"); > } > > static int do_bdev_destroy(struct lxc_conf *conf) > @@ -2012,8 +2042,7 @@ static int bdev_destroy_wrapper(void *data) > return do_bdev_destroy(conf); > } > > -// do we want the api to support --force, or leave that to the caller? > -static bool lxcapi_destroy(struct lxc_container *c) > +static bool container_destroy(struct lxc_container *c) > { > bool bret = false; > int ret; > @@ -2030,11 +2059,6 @@ static bool lxcapi_destroy(struct lxc_container *c) > goto out; > } > > - if (c->lxc_conf && has_snapshots(c)) { > - ERROR("container %s has dependent snapshots", c->name); > - goto out; > - } > - > if (c->lxc_conf && c->lxc_conf->rootfs.path && > c->lxc_conf->rootfs.mount) { > if (am_unpriv()) > ret = userns_exec_1(c->lxc_conf, > bdev_destroy_wrapper, c->lxc_conf); > @@ -2054,7 +2078,7 @@ static bool lxcapi_destroy(struct lxc_container *c) > if (am_unpriv()) > ret = userns_exec_1(c->lxc_conf, lxc_rmdir_onedev_wrapper, > path); > else > - ret = lxc_rmdir_onedev(path); > + ret = lxc_rmdir_onedev(path, "snaps"); > if (ret < 0) { > ERROR("Error destroying container directory for %s", c->name); > goto out; > @@ -2066,6 +2090,37 @@ out: > return bret; > } > > +static bool lxcapi_destroy(struct lxc_container *c) > +{ > + if (!c || !lxcapi_is_defined(c)) > + return false; > + if (has_snapshots(c)) { > + ERROR("Container %s has snapshots; not removing", c->name); > + return false; > + } > + > + if (has_fs_snapshots(c)) { > + ERROR("container %s has snapshots on its rootfs", c->name); > + return false; > + } > + > + return container_destroy(c); > +} > + > +static bool lxcapi_snapshot_destroy_all(struct lxc_container *c); > + > +static bool lxcapi_destroy_with_snapshots(struct lxc_container *c) > +{ > + if (!c || !lxcapi_is_defined(c)) > + return false; > + if (!lxcapi_snapshot_destroy_all(c)) { > + ERROR("Error deleting all snapshots"); > + return false; > + } > + return lxcapi_destroy(c); > +} > + > + > static bool set_config_item_locked(struct lxc_container *c, const char *key, > const char *v) > { > struct lxc_config_t *config; > @@ -2780,6 +2835,10 @@ static bool lxcapi_rename(struct lxc_container *c, > const char *newname) > if (!c || !c->name || !c->config_path || !c->lxc_conf) > return false; > > + if (has_fs_snapshots(c) || has_snapshots(c)) { > + ERROR("Renaming a container with snapshots is not supported"); > + return false; > + } > bdev = bdev_init(c->lxc_conf, c->lxc_conf->rootfs.path, > c->lxc_conf->rootfs.mount, NULL); > if (!bdev) { > ERROR("Failed to find original backing store type"); > @@ -2796,7 +2855,7 @@ static bool lxcapi_rename(struct lxc_container *c, > const char *newname) > if (newc && lxcapi_is_defined(newc)) > lxc_container_put(newc); > > - if (!lxcapi_destroy(c)) { > + if (!container_destroy(c)) { > ERROR("Could not destroy existing container %s", c->name); > return false; > } > @@ -2846,16 +2905,42 @@ static int get_next_index(const char *lxcpath, char > *cname) > } > } > > +static bool get_snappath_dir(struct lxc_container *c, char *snappath) > +{ > + int ret; > + /* > + * If the old style snapshot path exists, use it > + * /var/lib/lxc -> /var/lib/lxcsnaps > + */ > + ret = snprintf(snappath, MAXPATHLEN, "%ssnaps", c->config_path); > + if (ret < 0 || ret >= MAXPATHLEN) > + return false; > + if (dir_exists(snappath)) { > + ret = snprintf(snappath, MAXPATHLEN, "%ssnaps/%s", > c->config_path, c->name); > + if (ret < 0 || ret >= MAXPATHLEN) > + return false; > + return true; > + } > + > + /* > + * Use the new style path > + * /var/lib/lxc -> /var/lib/lxc + c->name + /snaps + \0 > + */ > + ret = snprintf(snappath, MAXPATHLEN, "%s/%s/snaps", c->config_path, > c->name); > + if (ret < 0 || ret >= MAXPATHLEN) > + return false; > + return true; > +} > + > static int lxcapi_snapshot(struct lxc_container *c, const char *commentfile) > { > int i, flags, ret; > struct lxc_container *c2; > char snappath[MAXPATHLEN], newname[20]; > > - // /var/lib/lxc -> /var/lib/lxcsnaps \0 > - ret = snprintf(snappath, MAXPATHLEN, "%ssnaps/%s", c->config_path, > c->name); > - if (ret < 0 || ret >= MAXPATHLEN) > + if (!get_snappath_dir(c, snappath)) { > return -1; > + } > i = get_next_index(snappath, c->name); > > if (mkdir_p(snappath, 0755) < 0) { > @@ -2989,7 +3074,7 @@ static char *get_timestamp(char* snappath, char *name) > static int lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot > **ret_snaps) > { > char snappath[MAXPATHLEN], path2[MAXPATHLEN]; > - int dirlen, count = 0, ret; > + int count = 0, ret; > struct dirent dirent, *direntp; > struct lxc_snapshot *snaps =NULL, *nsnaps; > DIR *dir; > @@ -2997,9 +3082,7 @@ static int lxcapi_snapshot_list(struct lxc_container > *c, struct lxc_snapshot **r > if (!c || !lxcapi_is_defined(c)) > return -1; > > - // snappath is ${lxcpath}snaps/${lxcname}/ > - dirlen = snprintf(snappath, MAXPATHLEN, "%ssnaps/%s", c->config_path, > c->name); > - if (dirlen < 0 || dirlen >= MAXPATHLEN) { > + if (!get_snappath_dir(c, snappath)) { > ERROR("path name too long"); > return -1; > } > @@ -3067,7 +3150,7 @@ out_free: > static bool lxcapi_snapshot_restore(struct lxc_container *c, const char > *snapname, const char *newname) > { > char clonelxcpath[MAXPATHLEN]; > - int flags = 0,ret; > + int flags = 0; > struct lxc_container *snap, *rest; > struct bdev *bdev; > bool b = false; > @@ -3075,6 +3158,11 @@ static bool lxcapi_snapshot_restore(struct > lxc_container *c, const char *snapnam > if (!c || !c->name || !c->config_path) > return false; > > + if (has_fs_snapshots(c)) { > + ERROR("container rootfs has dependent snapshots"); > + return false; > + } > + > bdev = bdev_init(c->lxc_conf, c->lxc_conf->rootfs.path, > c->lxc_conf->rootfs.mount, NULL); > if (!bdev) { > ERROR("Failed to find original backing store type"); > @@ -3084,14 +3172,13 @@ static bool lxcapi_snapshot_restore(struct > lxc_container *c, const char *snapnam > if (!newname) > newname = c->name; > if (strcmp(c->name, newname) == 0) { > - if (!lxcapi_destroy(c)) { > + if (!container_destroy(c)) { > ERROR("Could not destroy existing container %s", > newname); > bdev_put(bdev); > return false; > } > } > - ret = snprintf(clonelxcpath, MAXPATHLEN, "%ssnaps/%s", > c->config_path, c->name); > - if (ret < 0 || ret >= MAXPATHLEN) { > + if (!get_snappath_dir(c, clonelxcpath)) { > bdev_put(bdev); > return false; > } > @@ -3118,21 +3205,13 @@ static bool lxcapi_snapshot_restore(struct > lxc_container *c, const char *snapnam > return b; > } > > -static bool lxcapi_snapshot_destroy(struct lxc_container *c, const char > *snapname) > +static bool do_snapshot_destroy(const char *snapname, const char > *clonelxcpath) > { > - int ret; > - char clonelxcpath[MAXPATHLEN]; > struct lxc_container *snap = NULL; > - > - if (!c || !c->name || !c->config_path) > - return false; > - > - ret = snprintf(clonelxcpath, MAXPATHLEN, "%ssnaps/%s", > c->config_path, c->name); > - if (ret < 0 || ret >= MAXPATHLEN) > - goto err; > + bool bret = false; > > snap = lxc_container_new(snapname, clonelxcpath); > - if (!snap || !lxcapi_is_defined(snap)) { > + if (!snap) { > ERROR("Could not find snapshot %s", snapname); > goto err; > } > @@ -3141,13 +3220,70 @@ static bool lxcapi_snapshot_destroy(struct > lxc_container *c, const char *snapnam > ERROR("Could not destroy snapshot %s", snapname); > goto err; > } > - lxc_container_put(snap); > + bret = true; > > - return true; > err: > if (snap) > lxc_container_put(snap); > - return false; > + return bret; > +} > + > +static bool remove_all_snapshots(const char *path) > +{ > + DIR *dir; > + struct dirent dirent, *direntp; > + bool bret = true; > + > + dir = opendir(path); > + if (!dir) { > + SYSERROR("opendir on snapshot path %s", path); > + return false; > + } > + while (!readdir_r(dir, &dirent, &direntp)) { > + if (!direntp) > + break; > + if (!strcmp(direntp->d_name, ".")) > + continue; > + if (!strcmp(direntp->d_name, "..")) > + continue; > + if (!do_snapshot_destroy(direntp->d_name, path)) { > + bret = false; > + continue; > + } > + } > + > + closedir(dir); > + > + if (rmdir(path)) > + SYSERROR("Error removing directory %s", path); > + > + return bret; > +} > + > +static bool lxcapi_snapshot_destroy(struct lxc_container *c, const char > *snapname) > +{ > + char clonelxcpath[MAXPATHLEN]; > + > + if (!c || !c->name || !c->config_path || !snapname) > + return false; > + > + if (!get_snappath_dir(c, clonelxcpath)) > + return false; > + > + return do_snapshot_destroy(snapname, clonelxcpath); > +} > + > +static bool lxcapi_snapshot_destroy_all(struct lxc_container *c) > +{ > + char clonelxcpath[MAXPATHLEN]; > + > + if (!c || !c->name || !c->config_path) > + return false; > + > + if (!get_snappath_dir(c, clonelxcpath)) > + return false; > + > + return remove_all_snapshots(clonelxcpath); > } > > static bool lxcapi_may_control(struct lxc_container *c) > @@ -3307,6 +3443,9 @@ struct lxc_container *lxc_container_new(const char > *name, const char *configpath > { > struct lxc_container *c; > > + if (!name) > + return NULL; > + > c = malloc(sizeof(*c)); > if (!c) { > fprintf(stderr, "failed to malloc lxc_container\n"); > @@ -3353,7 +3492,7 @@ struct lxc_container *lxc_container_new(const char > *name, const char *configpath > > if (ongoing_create(c) == 2) { > ERROR("Error: %s creation was not completed", c->name); > - lxcapi_destroy(c); > + container_destroy(c); > lxcapi_clear_config(c); > } > c->daemonize = true; > @@ -3378,6 +3517,7 @@ struct lxc_container *lxc_container_new(const char > *name, const char *configpath > c->wait = lxcapi_wait; > c->set_config_item = lxcapi_set_config_item; > c->destroy = lxcapi_destroy; > + c->destroy_with_snapshots = lxcapi_destroy_with_snapshots; > c->rename = lxcapi_rename; > c->save_config = lxcapi_save_config; > c->get_keys = lxcapi_get_keys; > @@ -3403,6 +3543,7 @@ struct lxc_container *lxc_container_new(const char > *name, const char *configpath > c->snapshot_list = lxcapi_snapshot_list; > c->snapshot_restore = lxcapi_snapshot_restore; > c->snapshot_destroy = lxcapi_snapshot_destroy; > + c->snapshot_destroy_all = lxcapi_snapshot_destroy_all; > c->may_control = lxcapi_may_control; > c->add_device_node = lxcapi_add_device_node; > c->remove_device_node = lxcapi_remove_device_node; > diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h > index 1d0628a..5085c43 100644 > --- a/src/lxc/lxccontainer.h > +++ b/src/lxc/lxccontainer.h > @@ -286,6 +286,17 @@ struct lxc_container { > bool (*destroy)(struct lxc_container *c); > > /*! > + * \brief Delete the container and all its snapshots. > + * > + * \param c Container. > + * > + * \return \c true on success, else \c false. > + * > + * \note Container must be stopped. > + */ > + bool (*destroy_with_snapshots)(struct lxc_container *c); > + > + /*! > * \brief Save configuaration to a file. > * > * \param c Container. > @@ -649,7 +660,7 @@ struct lxc_container { > * \brief Create a container snapshot. > * > * Assuming default paths, snapshots will be created as > - * \c /var/lib/lxcsnaps/\<c\>/snap\<n\> > + * \c /var/lib/lxc/\<c\>/snaps/snap\<n\> > * where \c \<c\> represents the container name and \c \<n\> > * represents the zero-based snapshot number. > * > @@ -691,7 +702,7 @@ struct lxc_container { > * fail if the snapshot is overlay-based, since the snapshots > * will pin the original container. > * \note As an example, if the container exists as \c > /var/lib/lxc/c1, snapname might be \c 'snap0' > - * (representing \c /var/lib/lxcsnaps/c1/snap0). If \p newname is \p > c2, > + * (representing \c /var/lib/lxc/c1/snaps/snap0). If \p newname is > \p c2, > * then \c snap0 will be copied to \c /var/lib/lxc/c2. > */ > bool (*snapshot_restore)(struct lxc_container *c, const char > *snapname, const char *newname); > @@ -707,6 +718,15 @@ struct lxc_container { > bool (*snapshot_destroy)(struct lxc_container *c, const char > *snapname); > > /*! > + * \brief Destroy all the container's snapshot. > + * > + * \param c Container. > + * > + * \return \c true on success, else \c false. > + */ > + bool (*snapshot_destroy_all)(struct lxc_container *c); > + > + /*! > * \brief Determine if the caller may control the container. > * > * \param c Container. > diff --git a/src/lxc/lxclock.c b/src/lxc/lxclock.c > index 1d62729..9d1c6f4 100644 > --- a/src/lxc/lxclock.c > +++ b/src/lxc/lxclock.c > @@ -108,8 +108,8 @@ static char *lxclock_name(const char *p, const char *n) > * $XDG_RUNTIME_DIR + "/lock/lxc/$lxcpath/$lxcname + '\0' if non-root > */ > > - /* length of "/lock/lxc/" + $lxcpath + "/" + $lxcname + '\0' */ > - len = strlen("/lock/lxc/") + strlen(n) + strlen(p) + 2; > + /* length of "/lock/lxc/" + $lxcpath + "/" + "." + $lxcname + '\0' */ > + len = strlen("/lock/lxc/") + strlen(n) + strlen(p) + 3; > rundir = get_rundir(); > if (!rundir) > return NULL; > @@ -129,7 +129,7 @@ static char *lxclock_name(const char *p, const char *n) > ret = mkdir_p(dest, 0755); > if (ret < 0) { > /* fall back to "/tmp/" $(id -u) "/lxc/" $lxcpath / $lxcname > + '\0' */ > - int l2 = 33 + strlen(n) + strlen(p); > + int l2 = 34 + strlen(n) + strlen(p); > if (l2 > len) { > char *d; > d = realloc(dest, l2); > @@ -147,9 +147,9 @@ static char *lxclock_name(const char *p, const char *n) > free(rundir); > return NULL; > } > - ret = snprintf(dest, len, "/tmp/%d/lxc/%s/%s", geteuid(), p, > n); > + ret = snprintf(dest, len, "/tmp/%d/lxc/%s/.%s", geteuid(), p, > n); > } else > - ret = snprintf(dest, len, "%s/lock/lxc/%s/%s", rundir, p, n); > + ret = snprintf(dest, len, "%s/lock/lxc/%s/.%s", rundir, p, n); > > free(rundir); > > diff --git a/src/lxc/utils.c b/src/lxc/utils.c > index b076ce7..738bf5e 100644 > --- a/src/lxc/utils.c > +++ b/src/lxc/utils.c > @@ -46,12 +46,14 @@ > > lxc_log_define(lxc_utils, lxc); > > -static int _recursive_rmdir_onedev(char *dirname, dev_t pdev) > +static int _recursive_rmdir_onedev(char *dirname, dev_t pdev, > + const char *exclude, int level) > { > struct dirent dirent, *direntp; > DIR *dir; > int ret, failed=0; > char pathname[MAXPATHLEN]; > + bool hadexclude = false; > > dir = opendir(dirname); > if (!dir) { > @@ -76,6 +78,29 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t > pdev) > failed=1; > continue; > } > + > + if (!level && exclude && !strcmp(direntp->d_name, exclude)) { > + ret = rmdir(pathname); > + if (ret < 0) { > + switch(errno) { > + case ENOTEMPTY: > + INFO("Not deleting snapshots"); > + hadexclude = true; > + break; > + case ENOTDIR: > + ret = unlink(pathname); > + if (ret) > + INFO("%s: failed to remove > %s", __func__, pathname); > + break; > + default: > + SYSERROR("%s: failed to rmdir %s", > __func__, pathname); > + failed = 1; > + break; > + } > + } > + continue; > + } > + > ret = lstat(pathname, &mystat); > if (ret) { > ERROR("%s: failed to stat %s", __func__, pathname); > @@ -85,7 +110,7 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t > pdev) > if (mystat.st_dev != pdev) > continue; > if (S_ISDIR(mystat.st_mode)) { > - if (_recursive_rmdir_onedev(pathname, pdev) < 0) > + if (_recursive_rmdir_onedev(pathname, pdev, exclude, > level+1) < 0) > failed=1; > } else { > if (unlink(pathname) < 0) { > @@ -96,8 +121,10 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t > pdev) > } > > if (rmdir(dirname) < 0) { > - ERROR("%s: failed to delete %s", __func__, dirname); > - failed=1; > + if (!hadexclude) { > + ERROR("%s: failed to delete %s", __func__, dirname); > + failed=1; > + } > } > > ret = closedir(dir); > @@ -110,7 +137,7 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t > pdev) > } > > /* returns 0 on success, -1 if there were any failures */ > -extern int lxc_rmdir_onedev(char *path) > +extern int lxc_rmdir_onedev(char *path, const char *exclude) > { > struct stat mystat; > > @@ -119,7 +146,7 @@ extern int lxc_rmdir_onedev(char *path) > return -1; > } > > - return _recursive_rmdir_onedev(path, mystat.st_dev); > + return _recursive_rmdir_onedev(path, mystat.st_dev, exclude, 0); > } > > static int mount_fs(const char *source, const char *target, const char *type) > diff --git a/src/lxc/utils.h b/src/lxc/utils.h > index 691e56c..8516fcf 100644 > --- a/src/lxc/utils.h > +++ b/src/lxc/utils.h > @@ -34,7 +34,7 @@ > #include "config.h" > > /* returns 1 on success, 0 if there were any failures */ > -extern int lxc_rmdir_onedev(char *path); > +extern int lxc_rmdir_onedev(char *path, const char *exclude); > extern void lxc_setup_fs(void); > extern int get_u16(unsigned short *val, const char *arg, int base); > extern int mkdir_p(const char *dir, mode_t mode); > diff --git a/src/tests/snapshot.c b/src/tests/snapshot.c > index 09cee1a..21acd3e 100644 > --- a/src/tests/snapshot.c > +++ b/src/tests/snapshot.c > @@ -32,28 +32,21 @@ > static void try_to_remove(void) > { > struct lxc_container *c; > - char snappath[1024]; > c = lxc_container_new(RESTNAME, NULL); > if (c) { > - if (c->is_defined(c)) > - c->destroy(c); > - lxc_container_put(c); > - } > - snprintf(snappath, 1024, "%ssnaps/%s", > lxc_get_global_config_item("lxc.lxcpath"), MYNAME); > - c = lxc_container_new("snap0", snappath); > - if (c) { > + c->snapshot_destroy_all(c); > if (c->is_defined(c)) > c->destroy(c); > lxc_container_put(c); > } > c = lxc_container_new(MYNAME2, NULL); > if (c) { > - if (c->is_defined(c)) > - c->destroy(c); > + c->destroy_with_snapshots(c); > lxc_container_put(c); > } > c = lxc_container_new(MYNAME, NULL); > if (c) { > + c->snapshot_destroy_all(c); > if (c->is_defined(c)) > c->destroy(c); > lxc_container_put(c); > @@ -77,7 +70,7 @@ int main(int argc, char *argv[]) > > if (c->is_defined(c)) { > fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, > MYNAME); > - (void) c->destroy(c); > + (void) c->destroy_with_snapshots(c); > } > if (!c->set_config_item(c, "lxc.network.type", "empty")) { > fprintf(stderr, "%s: %d: failed to set network type\n", > __FILE__, __LINE__); > @@ -95,11 +88,11 @@ int main(int argc, char *argv[]) > goto err; > } > > - // rootfs should be ${lxcpath}snaps/${lxcname}/snap0/rootfs > + // rootfs should be ${lxcpath}${lxcname}/snaps/snap0/rootfs > struct stat sb; > int ret; > char path[1024]; > - snprintf(path, 1024, "%ssnaps/%s/snap0/rootfs", > lxc_get_global_config_item("lxc.lxcpath"), MYNAME); > + snprintf(path, 1024, "%s/%s/snaps/snap0/rootfs", > lxc_get_global_config_item("lxc.lxcpath"), MYNAME); > ret = stat(path, &sb); > if (ret != 0) { > fprintf(stderr, "%s: %d: snapshot was not actually > created\n", __FILE__, __LINE__); > @@ -169,17 +162,7 @@ int main(int argc, char *argv[]) > goto err; > } > > - if (!c2->destroy(c2)) { > - fprintf(stderr, "%s: %d: failed to destroy container\n", > __FILE__, __LINE__); > - goto err; > - } > - > good: > - if (!c->destroy(c)) { > - fprintf(stderr, "%s: %d: failed to destroy container\n", > __FILE__, __LINE__); > - goto err; > - } > - > lxc_container_put(c); > try_to_remove(); > > -- > 2.0.0.rc0 > > _______________________________________________ > lxc-devel mailing list > lxc-devel@lists.linuxcontainers.org > http://lists.linuxcontainers.org/listinfo/lxc-devel -- S.Çağlar Onur <cag...@10ur.org> _______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel