Skip to content

Commit

Permalink
lxc-destroy: actually work if underlying fs is overlayfs
Browse files Browse the repository at this point in the history
One of the 'features' of overlayfs is that depending on whether a file
is on the upper or lower dir you get back a different device from stat.
That breaks our lxc_rmdir_onedev.

So at lxc_rmdir_ondev check the device of the directory being deleted.
If it is overlayfs, then skip the device check.

Note this is unrelated to overlayfs snapshots - in those cases when you
delete a container, /var/lib/lxc/$container/ does not actually have an
overlayfs under it.  Rather, to reproduce this you would

sudo mkdir /opt/{lower,upper,workdir}
sudo mount -t overlayfs -o lower=/opt/lower,upper=/opt/upper,workdir=/opt/workdir \
	lxc /var/lib/lxc
sudo lxc-create -t download -n c1 -- -d ubuntu -r trusty -a amd64
sudo lxc-destroy -n c1

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Tested-by: Marko Ratkaj <marko.ratkaj@sartura.hr>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
  • Loading branch information
hallyn authored and stgraber committed Apr 6, 2015
1 parent 7b7d76e commit 0cc417b
Showing 1 changed file with 32 additions and 7 deletions.
39 changes: 32 additions & 7 deletions src/lxc/utils.c
Expand Up @@ -29,6 +29,7 @@
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/param.h>
Expand Down Expand Up @@ -68,8 +69,8 @@

lxc_log_define(lxc_utils, lxc);

static int _recursive_rmdir_onedev(char *dirname, dev_t pdev,
const char *exclude, int level)
static int _recursive_rmdir(char *dirname, dev_t pdev,
const char *exclude, int level, bool onedev)
{
struct dirent dirent, *direntp;
DIR *dir;
Expand Down Expand Up @@ -106,7 +107,7 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev,
if (ret < 0) {
switch(errno) {
case ENOTEMPTY:
INFO("Not deleting snapshots");
INFO("Not deleting snapshot %s", pathname);
hadexclude = true;
break;
case ENOTDIR:
Expand All @@ -129,14 +130,14 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev,
failed=1;
continue;
}
if (mystat.st_dev != pdev)
if (onedev && mystat.st_dev != pdev)
continue;
if (S_ISDIR(mystat.st_mode)) {
if (_recursive_rmdir_onedev(pathname, pdev, exclude, level+1) < 0)
if (_recursive_rmdir(pathname, pdev, exclude, level+1, onedev) < 0)
failed=1;
} else {
if (unlink(pathname) < 0) {
ERROR("%s: failed to delete %s", __func__, pathname);
SYSERROR("%s: failed to delete %s", __func__, pathname);
failed=1;
}
}
Expand All @@ -158,17 +159,41 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev,
return failed ? -1 : 0;
}

/* we have two different magic values for overlayfs, yay */
#define OVERLAYFS_SUPER_MAGIC 0x794c764f
#define OVERLAY_SUPER_MAGIC 0x794c7630
/*
* In overlayfs, st_dev is unreliable. so on overlayfs we don't do
* the lxc_rmdir_onedev()
*/
static bool is_native_overlayfs(const char *path)
{
struct statfs sb;

if (statfs(path, &sb) < 0)
return false;
if (sb.f_type == OVERLAYFS_SUPER_MAGIC ||
sb.f_type == OVERLAY_SUPER_MAGIC)
return true;
return false;
}

/* returns 0 on success, -1 if there were any failures */
extern int lxc_rmdir_onedev(char *path, const char *exclude)
{
struct stat mystat;
bool onedev = true;

if (is_native_overlayfs(path)) {
onedev = false;
}

if (lstat(path, &mystat) < 0) {
ERROR("%s: failed to stat %s", __func__, path);
return -1;
}

return _recursive_rmdir_onedev(path, mystat.st_dev, exclude, 0);
return _recursive_rmdir(path, mystat.st_dev, exclude, 0, onedev);
}

static int mount_fs(const char *source, const char *target, const char *type)
Expand Down

0 comments on commit 0cc417b

Please sign in to comment.