From: Serge Hallyn Date: Mon, 16 Mar 2015 17:02:12 +0000 (+0000) Subject: lxc-destroy: actually work if underlying fs is overlayfs X-Git-Tag: lxc-1.0.8~67 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6147fe2e157cf9928a053efdd8027445e3d57507;p=thirdparty%2Flxc.git lxc-destroy: actually work if underlying fs is overlayfs 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 Tested-by: Marko Ratkaj Acked-by: Stéphane Graber --- diff --git a/src/lxc/utils.c b/src/lxc/utils.c index 2728edbeb..a252fcdfb 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -46,7 +47,7 @@ lxc_log_define(lxc_utils, lxc); -static int _recursive_rmdir_onedev(char *dirname, dev_t pdev) +static int _recursive_rmdir(char *dirname, dev_t pdev, bool onedev) { struct dirent dirent, *direntp; DIR *dir; @@ -76,20 +77,21 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev) failed=1; continue; } + ret = lstat(pathname, &mystat); if (ret) { ERROR("%s: failed to stat %s", __func__, pathname); 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) < 0) + if (_recursive_rmdir(pathname, pdev, 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; } } @@ -109,17 +111,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) { 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); + return _recursive_rmdir(path, mystat.st_dev, onedev); } static int mount_fs(const char *source, const char *target, const char *type)