#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/vfs.h>
#include "bdev.h"
#include "log.h"
return true;
}
+/*
+ * Taken from btrfs toolsuite. Test if path is a subvolume.
+ * return 0; path exists but it is not a subvolume
+ * return 1; path exists and it is a subvolume
+ * return < 0; error
+ */
+int is_btrfs_subvol(const char *path)
+{
+ struct stat st;
+ struct statfs stfs;
+ int ret;
+
+ ret = stat(path, &st);
+ if (ret < 0)
+ return -errno;
+
+ if (st.st_ino != BTRFS_FIRST_FREE_OBJECTID || !S_ISDIR(st.st_mode))
+ return 0;
+
+ ret = statfs(path, &stfs);
+ if (ret < 0)
+ return -errno;
+
+ return stfs.f_type == BTRFS_SUPER_MAGIC;
+}
+
int btrfs_detect(const char *path)
{
struct stat st;
#include <stdint.h>
#include <byteswap.h>
+#ifndef BTRFS_SUPER_MAGIC
+# define BTRFS_SUPER_MAGIC 0x9123683E
+#endif
+
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
int name_len);
int btrfs_list_get_path_rootid(int fd, u64 *treeid);
bool is_btrfs_fs(const char *path);
+int is_btrfs_subvol(const char *path);
bool btrfs_try_remove_subvol(const char *path);
int btrfs_same_fs(const char *orig, const char *new);
int btrfs_snapshot(const char *orig, const char *new);
size_t l1 = strlen(c1->config_path) + strlen(c1->name) + 2;
char *p0 = alloca(l0 + 1);
char *p1 = alloca(l1 + 1);
+ char *rootfs = c0->lxc_conf->rootfs.path;
snprintf(p0, l0, "%s/%s", c0->config_path, c0->name);
snprintf(p1, l1, "%s/%s", c1->config_path, c1->name);
if (!is_btrfs_fs(p0) || !is_btrfs_fs(p1))
return false;
+ if (is_btrfs_subvol(rootfs) <= 0)
+ return false;
+
return btrfs_same_fs(p0, p1) == 0;
}