Commit 789edffe by Stéphane Graber Committed by GitHub

Merge pull request #1747 from brauner/2017-08-15/stable_2_0_cherry_picks

stable 2.0: revert a bunch of cherry picks
parents 93b8f59a 7d3391cb
......@@ -73,10 +73,6 @@ struct bdev_ops {
const char *oldname, const char *cname,
const char *oldpath, const char *lxcpath, int snap,
uint64_t newsize, struct lxc_conf *conf);
bool (*create_clone)(struct lxc_conf *conf, struct bdev *orig,
struct bdev *new, uint64_t newsize);
bool (*create_snapshot)(struct lxc_conf *conf, struct bdev *orig,
struct bdev *new, uint64_t newsize);
bool can_snapshot;
bool can_backup;
};
......@@ -129,6 +125,5 @@ bool bdev_destroy(struct lxc_conf *conf);
/* callback function to be used with userns_exec_1() */
int bdev_destroy_wrapper(void *data);
extern bool rootfs_is_blockdev(struct lxc_conf *conf);
extern char *lxc_storage_get_path(char *src, const char *prefix);
#endif // __LXC_BDEV_H
......@@ -32,7 +32,6 @@
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/vfs.h>
......@@ -40,10 +39,14 @@
#include "log.h"
#include "lxcbtrfs.h"
#include "lxcrsync.h"
#include "../utils.h"
#include "utils.h"
lxc_log_define(lxcbtrfs, lxc);
/* defined in lxccontainer.c: needs to become common helper */
extern char *dir_new_path(char *src, const char *oldname, const char *name,
const char *oldpath, const char *lxcpath);
/*
* Return the full path of objid under dirid. Let's say dirid is
* /lxc/c1/rootfs, and objid is /lxc/c1/rootfs/a/b/c. Then we will
......@@ -188,12 +191,11 @@ int btrfs_detect(const char *path)
int btrfs_mount(struct bdev *bdev)
{
unsigned long mntflags;
char *mntdata, *src;
char *mntdata;
int ret;
if (strcmp(bdev->type, "btrfs"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
......@@ -202,9 +204,7 @@ int btrfs_mount(struct bdev *bdev)
return -22;
}
src = lxc_storage_get_path(bdev->src, "btrfs");
ret = mount(src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
free(mntdata);
return ret;
}
......@@ -213,50 +213,45 @@ int btrfs_umount(struct bdev *bdev)
{
if (strcmp(bdev->type, "btrfs"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
return umount(bdev->dest);
}
static int btrfs_subvolume_create(const char *path)
{
int ret, saved_errno;
struct btrfs_ioctl_vol_args args;
char *p, *newfull;
int fd = -1;
int ret, fd = -1;
struct btrfs_ioctl_vol_args args;
char *p, *newfull = strdup(path);
newfull = strdup(path);
if (!newfull) {
errno = ENOMEM;
return -ENOMEM;
ERROR("Error: out of memory");
return -1;
}
p = strrchr(newfull, '/');
if (!p) {
ERROR("bad path: %s", path);
free(newfull);
errno = EINVAL;
return -EINVAL;
return -1;
}
*p = '\0';
fd = open(newfull, O_RDONLY);
if (fd < 0) {
ERROR("Error opening %s", newfull);
free(newfull);
return -errno;
return -1;
}
memset(&args, 0, sizeof(args));
strncpy(args.name, p + 1, BTRFS_SUBVOL_NAME_MAX);
args.name[BTRFS_SUBVOL_NAME_MAX - 1] = 0;
strncpy(args.name, p+1, BTRFS_SUBVOL_NAME_MAX);
args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
ret = ioctl(fd, BTRFS_IOC_SUBVOL_CREATE, &args);
saved_errno = errno;
INFO("btrfs: snapshot create ioctl returned %d", ret);
close(fd);
free(newfull);
errno = saved_errno;
close(fd);
return ret;
}
......@@ -303,37 +298,39 @@ out:
int btrfs_snapshot(const char *orig, const char *new)
{
struct btrfs_ioctl_vol_args_v2 args;
char *newdir, *newname;
char *newfull = NULL;
int saved_errno = -1;
int fd = -1, fddst = -1, ret = -1;
struct btrfs_ioctl_vol_args_v2 args;
char *newdir, *newname, *newfull = NULL;
newfull = strdup(new);
if (!newfull)
if (!newfull) {
ERROR("Error: out of memory");
goto out;
ret = rmdir(newfull);
if (ret < 0 && errno != ENOENT)
}
// make sure the directory doesn't already exist
if (rmdir(newfull) < 0 && errno != ENOENT) {
SYSERROR("Error removing empty new rootfs");
goto out;
}
newname = basename(newfull);
newdir = dirname(newfull);
fd = open(orig, O_RDONLY);
if (fd < 0)
if (fd < 0) {
SYSERROR("Error opening original rootfs %s", orig);
goto out;
newdir = dirname(newfull);
}
fddst = open(newdir, O_RDONLY);
if (fddst < 0)
if (fddst < 0) {
SYSERROR("Error opening new container dir %s", newdir);
goto out;
}
memset(&args, 0, sizeof(args));
args.fd = fd;
strncpy(args.name, newname, BTRFS_SUBVOL_NAME_MAX);
args.name[BTRFS_SUBVOL_NAME_MAX - 1] = 0;
args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
ret = ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args);
saved_errno = errno;
INFO("btrfs: snapshot create ioctl returned %d", ret);
out:
if (fddst != -1)
......@@ -341,31 +338,23 @@ out:
if (fd != -1)
close(fd);
free(newfull);
if (saved_errno >= 0)
errno = saved_errno;
return ret;
}
int btrfs_snapshot_wrapper(void *data)
static int btrfs_snapshot_wrapper(void *data)
{
char *src;
struct rsync_data_char *arg = data;
if (setgid(0) < 0) {
ERROR("Failed to setgid to 0");
return -1;
}
if (setgroups(0, NULL) < 0)
WARN("Failed to clear groups");
if (setuid(0) < 0) {
ERROR("Failed to setuid to 0");
return -1;
}
src = lxc_storage_get_path(arg->src, "btrfs");
return btrfs_snapshot(src, arg->dest);
return btrfs_snapshot(arg->src, arg->dest);
}
int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
......@@ -373,126 +362,52 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *lxcpath, int snap, uint64_t newsize,
struct lxc_conf *conf)
{
char *src;
if (!orig->dest || !orig->src)
return -1;
if (strcmp(orig->type, "btrfs") && snap) {
ERROR("btrfs snapshot from %s backing store is not supported",
orig->type);
return -1;
}
new->src = lxc_string_join(
"/",
(const char *[]){"btrfs:", *lxcpath != '/' ? lxcpath : ++lxcpath,
cname, "rootfs", NULL},
false);
if (!new->src) {
ERROR("Failed to create new rootfs path");
return -1;
}
TRACE("Constructed new rootfs path \"%s\"", new->src);
src = lxc_storage_get_path(new->src, "btrfs");
new->dest = strdup(src);
if (!new->dest) {
ERROR("Failed to duplicate string \"%s\"", src);
return -1;
}
if (orig->mntopts) {
new->mntopts = strdup(orig->mntopts);
if (!new->mntopts) {
ERROR("Failed to duplicate string \"%s\"",
orig->mntopts);
if (strcmp(orig->type, "btrfs")) {
int len, ret;
if (snap) {
ERROR("btrfs snapshot from %s backing store is not supported",
orig->type);
return -1;
}
}
return 0;
}
bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig,
struct bdev *new, uint64_t newsize)
{
int ret;
struct rsync_data data = {0, 0};
char cmd_output[MAXPATHLEN] = {0};
ret = rmdir(new->dest);
if (ret < 0 && errno != ENOENT)
return false;
ret = btrfs_subvolume_create(new->dest);
if (ret < 0) {
SYSERROR("Failed to create btrfs subvolume \"%s\"", new->dest);
return false;
}
/* rsync the contents from source to target */
data.orig = orig;
data.new = new;
if (am_unpriv()) {
ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &data,
"lxc_rsync_exec_wrapper");
if (ret < 0) {
ERROR("Failed to rsync from \"%s\" into \"%s\"",
orig->dest, new->dest);
return false;
}
return true;
}
len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3;
new->src = malloc(len);
if (!new->src)
return -1;
ret = snprintf(new->src, len, "%s/%s/rootfs", lxcpath, cname);
if (ret < 0 || ret >= len)
return -1;
} else {
// in case rootfs is in custom path, reuse it
if ((new->src = dir_new_path(orig->src, oldname, cname, oldpath, lxcpath)) == NULL)
return -1;
ret = run_command(cmd_output, sizeof(cmd_output),
lxc_rsync_exec_wrapper, (void *)&data);
if (ret < 0) {
ERROR("Failed to rsync from \"%s\" into \"%s\": %s", orig->dest,
new->dest, cmd_output);
return false;
}
return true;
}
bool btrfs_create_snapshot(struct lxc_conf *conf, struct bdev *orig,
struct bdev *new, uint64_t newsize)
{
int ret;
ret = rmdir(new->dest);
if (ret < 0 && errno != ENOENT)
return false;
if (am_unpriv()) {
struct rsync_data_char args;
args.src = orig->dest;
args.dest = new->dest;
if ((new->dest = strdup(new->src)) == NULL)
return -1;
ret = userns_exec_1(conf, btrfs_snapshot_wrapper, &args,
"btrfs_snapshot_wrapper");
if (ret < 0) {
ERROR("Failed to run \"btrfs_snapshot_wrapper\"");
return false;
}
if (orig->mntopts && (new->mntopts = strdup(orig->mntopts)) == NULL)
return -1;
TRACE("Created btrfs snapshot \"%s\" from \"%s\"", new->dest,
orig->dest);
return true;
if (snap) {
struct rsync_data_char sdata;
if (!am_unpriv())
return btrfs_snapshot(orig->dest, new->dest);
sdata.dest = new->dest;
sdata.src = orig->dest;
return userns_exec_1(conf, btrfs_snapshot_wrapper, &sdata,
"btrfs_snapshot_wrapper");
}
ret = btrfs_snapshot(orig->dest, new->dest);
if (ret < 0) {
SYSERROR("Failed to create btrfs snapshot \"%s\" from \"%s\"",
new->dest, orig->dest);
return false;
if (rmdir(new->dest) < 0 && errno != ENOENT) {
SYSERROR("removing %s", new->dest);
return -1;
}
TRACE("Created btrfs snapshot \"%s\" from \"%s\"", new->dest, orig->dest);
return true;
return btrfs_subvolume_create(new->dest);
}
static int btrfs_do_destroy_subvol(const char *path)
......@@ -816,50 +731,21 @@ bool btrfs_try_remove_subvol(const char *path)
{
if (!btrfs_detect(path))
return false;
return btrfs_recursive_destroy(path) == 0;
}
int btrfs_destroy(struct bdev *orig)
{
char *src;
src = lxc_storage_get_path(orig->src, "btrfs");
return btrfs_recursive_destroy(src);
return btrfs_recursive_destroy(orig->src);
}
int btrfs_create(struct bdev *bdev, const char *dest, const char *n,
struct bdev_specs *specs)
{
int ret;
size_t len;
len = strlen(dest) + 1;
/* strlen("btrfs:") */
len += 6;
bdev->src = malloc(len);
if (!bdev->src) {
ERROR("Failed to allocate memory");
return -1;
}
ret = snprintf(bdev->src, len, "btrfs:%s", dest);
if (ret < 0 || (size_t)ret >= len) {
ERROR("Failed to create string");
return -1;
}
bdev->src = strdup(dest);
bdev->dest = strdup(dest);
if (!bdev->dest) {
ERROR("Failed to duplicate string \"%s\"", dest);
if (!bdev->src || !bdev->dest)
return -1;
}
ret = btrfs_subvolume_create(bdev->dest);
if (ret < 0) {
SYSERROR("Failed to create btrfs subvolume \"%s\"", bdev->dest);
}
return ret;
return btrfs_subvolume_create(bdev->dest);
}
......@@ -412,10 +412,5 @@ 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);
int btrfs_snapshot_wrapper(void *data);
bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig,
struct bdev *new, uint64_t newsize);
bool btrfs_create_snapshot(struct lxc_conf *conf, struct bdev *orig,
struct bdev *new, uint64_t newsize);
#endif // __LXC_BTRFS_H
......@@ -36,101 +36,61 @@ lxc_log_define(lxcdir, lxc);
* name and paths for the new
*/
int dir_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath,
int snap, uint64_t newsize, struct lxc_conf *conf)
const char *cname, const char *oldpath, const char *lxcpath,
int snap, uint64_t newsize, struct lxc_conf *conf)
{
char *src_no_prefix;
int ret;
size_t len;
int len, ret;
if (snap) {
ERROR("Directories cannot be snapshotted");
ERROR("directories cannot be snapshotted. Try aufs or overlayfs.");
return -1;
}
if (!orig->dest || !orig->src)
return -1;
len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 4 + 3;
len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3;
new->src = malloc(len);
if (!new->src) {
ERROR("Failed to allocate memory");
if (!new->src)
return -1;
}
ret = snprintf(new->src, len, "dir:%s/%s/rootfs", lxcpath, cname);
if (ret < 0 || (size_t)ret >= len) {
ERROR("Failed to create string");
ret = snprintf(new->src, len, "%s/%s/rootfs", lxcpath, cname);
if (ret < 0 || ret >= len)
return -1;
}
src_no_prefix = lxc_storage_get_path(new->src, new->type);
new->dest = strdup(src_no_prefix);
if (!new->dest) {
ERROR("Failed to duplicate string \"%s\"", new->src);
if ((new->dest = strdup(new->src)) == NULL)
return -1;
}
TRACE("Created new path \"%s\" for dir storage driver", new->dest);
return 0;
}
int dir_create(struct bdev *bdev, const char *dest, const char *n,
struct bdev_specs *specs)
struct bdev_specs *specs)
{
int ret;
const char *src;
size_t len;
/* strlen("dir:") */
len = 4;
if (specs && specs->dir)
src = specs->dir;
bdev->src = strdup(specs->dir);
else
src = dest;
len += strlen(src) + 1;
bdev->src = malloc(len);
if (!bdev->src) {
ERROR("Failed to allocate memory");
return -1;
}
ret = snprintf(bdev->src, len, "dir:%s", src);
if (ret < 0 || (size_t)ret >= len) {
ERROR("Failed to create string");
bdev->src = strdup(dest);
bdev->dest = strdup(dest);
if (!bdev->src || !bdev->dest) {
ERROR("Out of memory");
return -1;
}
bdev->dest = strdup(dest);
if (!bdev->dest) {
ERROR("Failed to duplicate string \"%s\"", dest);
if (mkdir_p(bdev->src, 0755) < 0) {
ERROR("Error creating %s", bdev->src);
return -1;
}
ret = mkdir_p(dest, 0755);
if (ret < 0) {
ERROR("Failed to create directory \"%s\"", dest);
if (mkdir_p(bdev->dest, 0755) < 0) {
ERROR("Error creating %s", bdev->dest);
return -1;
}
TRACE("Created directory \"%s\"", dest);
return 0;
}
int dir_destroy(struct bdev *orig)
{
int ret;
char *src;
src = lxc_storage_get_path(orig->src, orig->src);
ret = lxc_rmdir_onedev(src, NULL);
if (ret < 0) {
ERROR("Failed to delete \"%s\"", src);
if (lxc_rmdir_onedev(orig->src, NULL) < 0)
return -1;
}
return 0;
}
......@@ -140,47 +100,34 @@ int dir_detect(const char *path)
return 1; // take their word for it
if (is_dir(path))
return 1;
return 0;
}
int dir_mount(struct bdev *bdev)
{
unsigned long mntflags;
char *mntdata;
int ret;
unsigned long mflags, mntflags;
char *src, *mntdata;
unsigned long mflags;
if (strcmp(bdev->type, "dir"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata);
if (ret < 0) {
ERROR("Failed to parse mount options \"%s\"", bdev->mntopts);
if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
free(mntdata);
return -22;
}
src = lxc_storage_get_path(bdev->src, bdev->type);
ret = mount(src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags,
mntdata);
ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
if ((0 == ret) && (mntflags & MS_RDONLY)) {
DEBUG("Remounting \"%s\" on \"%s\" readonly",
src ? src : "(none)", bdev->dest ? bdev->dest : "(none)");
mflags = add_required_remount_flags(src, bdev->dest, MS_BIND | MS_REC | mntflags | MS_REMOUNT);
ret = mount(src, bdev->dest, "bind", mflags, mntdata);
DEBUG("remounting %s on %s with readonly options",
bdev->src ? bdev->src : "(none)", bdev->dest ? bdev->dest : "(none)");
mflags = add_required_remount_flags(bdev->src, bdev->dest, MS_BIND | MS_REC | mntflags | MS_REMOUNT);
ret = mount(bdev->src, bdev->dest, "bind", mflags, mntdata);
}
if (ret < 0) {
SYSERROR("Failed to mount \"%s\" on \"%s\"", src, bdev->dest);
free(mntdata);
return -1;
}
TRACE("Mounted \"%s\" on \"%s\"", src, bdev->dest);
free(mntdata);
return ret;
}
......@@ -189,9 +136,7 @@ int dir_umount(struct bdev *bdev)
{
if (strcmp(bdev->type, "dir"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
return umount(bdev->dest);
}
......@@ -22,15 +22,12 @@
*/
#define _GNU_SOURCE
#define __STDC_FORMAT_MACROS
#include <dirent.h>
#include <errno.h>
#include <inttypes.h>
#include <linux/loop.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/loop.h>
#include <sys/stat.h>
#include <sys/types.h>
......@@ -49,16 +46,16 @@ static int do_loop_create(const char *path, uint64_t size, const char *fstype);
* called $lxcpath/$lxcname/rootdev
*/
int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath,
int snap, uint64_t newsize, struct lxc_conf *conf)
const char *cname, const char *oldpath, const char *lxcpath,
int snap, uint64_t newsize, struct lxc_conf *conf)
{
char fstype[100];
uint64_t size = newsize;
int len, ret;
char *srcdev;
char fstype[100] = "ext4";
if (snap) {
ERROR("The loop storage driver does not support snapshots");
ERROR("loop devices cannot be snapshotted.");
return -1;
}
......@@ -68,65 +65,43 @@ int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
len = strlen(lxcpath) + strlen(cname) + strlen("rootdev") + 3;
srcdev = alloca(len);
ret = snprintf(srcdev, len, "%s/%s/rootdev", lxcpath, cname);
if (ret < 0 || ret >= len) {
ERROR("Failed to create string");
if (ret < 0 || ret >= len)
return -1;
}
new->src = malloc(len + 5);
if (!new->src) {
ERROR("Failed to allocate memory");
if (!new->src)
return -1;
}
ret = snprintf(new->src, (len + 5), "loop:%s", srcdev);
if (ret < 0 || ret >= (len + 5)) {
ERROR("Failed to create string");
ret = snprintf(new->src, len + 5, "loop:%s", srcdev);
if (ret < 0 || ret >= len + 5)
return -1;
}
new->dest = malloc(len);
if (!new->dest) {
ERROR("Failed to allocate memory");
if (!new->dest)
return -1;
}
ret = snprintf(new->dest, len, "%s/%s/rootfs", lxcpath, cname);
if (ret < 0 || ret >= len) {
ERROR("Failed to create string");
if (ret < 0 || ret >= len)
return -1;
}
/* It's tempting to say: if orig->src == loopback and !newsize, then
* copy the loopback file. However, we'd have to make sure to correctly
* keep holes! So punt for now.
*/
// it's tempting to say: if orig->src == loopback and !newsize, then
// copy the loopback file. However, we'd have to make sure to
// correctly keep holes! So punt for now.
if (is_blktype(orig)) {
/* detect size */
if (!newsize && blk_getsize(orig, &size) < 0) {
ERROR("Failed to detect size of loop file \"%s\"",
orig->src);
ERROR("Error getting size of %s", orig->src);
return -1;
}
/* detect filesystem */
if (detect_fs(orig, fstype, 100) < 0) {
INFO("Failed to detect filesystem type for \"%s\"", orig->src);
INFO("could not find fstype for %s, using %s", orig->src,
DEFAULT_FSTYPE);
return -1;
}
} else if (!newsize) {
} else {
sprintf(fstype, "%s", DEFAULT_FSTYPE);
if (!newsize)
size = DEFAULT_FS_SIZE;
}
ret = do_loop_create(srcdev, size, fstype);
if (ret < 0) {
ERROR("Failed to create loop storage volume \"%s\" with "
"filesystem \"%s\" and size \"%" PRIu64 "\"",
srcdev, fstype, size);
return -1;
}
return 0;
return do_loop_create(srcdev, size, fstype);
}
int loop_create(struct bdev *bdev, const char *dest, const char *n,
......@@ -140,35 +115,23 @@ int loop_create(struct bdev *bdev, const char *dest, const char *n,
if (!specs)
return -1;
/* <dest> is passed in as <lxcpath>/<lxcname>/rootfs, <srcdev> will
* be <lxcpath>/<lxcname>/rootdev, and <src> will be "loop:<srcdev>".
*/
// dest is passed in as $lxcpath / $lxcname / rootfs
// srcdev will be: $lxcpath / $lxcname / rootdev
// src will be 'loop:$srcdev'
len = strlen(dest) + 2;
srcdev = alloca(len);
ret = snprintf(srcdev, len, "%s", dest);
if (ret < 0 || ret >= len) {
ERROR("Failed to create string");
return -1;
}
ret = sprintf(srcdev + len - 4, "dev");
if (ret < 0) {
ERROR("Failed to create string");
if (ret < 0 || ret >= len)
return -1;
}
sprintf(srcdev + len - 4, "dev");
bdev->src = malloc(len + 5);
if (!bdev->src) {
ERROR("Failed to allocate memory");
if (!bdev->src)
return -1;
}
ret = snprintf(bdev->src, len + 5, "loop:%s", srcdev);
if (ret < 0 || ret >= len + 5) {
ERROR("Failed to create string");
if (ret < 0 || ret >= len + 5)
return -1;
}
sz = specs->fssize;
if (!sz)
......@@ -178,31 +141,19 @@ int loop_create(struct bdev *bdev, const char *dest, const char *n,
if (!fstype)
fstype = DEFAULT_FSTYPE;
bdev->dest = strdup(dest);
if (!bdev->dest) {
ERROR("Failed to duplicate string \"%s\"", dest);
if (!(bdev->dest = strdup(dest)))
return -1;
}
ret = mkdir_p(bdev->dest, 0755);
if (ret < 0) {
ERROR("Failed creating directory \"%s\"", bdev->dest);
if (mkdir_p(bdev->dest, 0755) < 0) {
ERROR("Error creating %s", bdev->dest);
return -1;
}
ret = do_loop_create(srcdev, sz, fstype);
if (ret < 0) {
ERROR("Failed to create loop storage volume \"%s\" with "
"filesystem \"%s\" and size \"%" PRIu64 "\"",
srcdev, fstype, sz);
return -1;
}
return 0;
return do_loop_create(srcdev, sz, fstype);
}
int loop_destroy(struct bdev *orig) {
int loop_destroy(struct bdev *orig)
{
return unlink(orig->src + 5);
}
......@@ -228,7 +179,7 @@ int loop_mount(struct bdev *bdev)
{
int ret, loopfd;
char loname[MAXPATHLEN];
char *src;
char *src = bdev->src;
if (strcmp(bdev->type, "loop"))
return -22;
......@@ -237,98 +188,73 @@ int loop_mount(struct bdev *bdev)
return -22;
/* skip prefix */
src = lxc_storage_get_path(bdev->src, bdev->type);
if (!strncmp(bdev->src, "loop:", 5))
src += 5;
loopfd = lxc_prepare_loop_dev(src, loname, LO_FLAGS_AUTOCLEAR);
if (loopfd < 0) {
ERROR("Failed to prepare loop device for loop file \"%s\"", src);
ERROR("failed to prepare loop device for loop file \"%s\"", src);
return -1;
}
DEBUG("Prepared loop device \"%s\"", loname);
DEBUG("prepared loop device \"%s\"", loname);
ret = mount_unknown_fs(loname, bdev->dest, bdev->mntopts);
if (ret < 0) {
ERROR("Failed to mount rootfs \"%s\" on \"%s\" via loop device \"%s\"",
bdev->src, bdev->dest, loname);
close(loopfd);
return -1;
}
bdev->lofd = loopfd;
DEBUG("Mounted rootfs \"%s\" on \"%s\" via loop device \"%s\"",
bdev->src, bdev->dest, loname);
if (ret < 0)
ERROR("failed to mount rootfs \"%s\" onto \"%s\" via loop device \"%s\"", bdev->src, bdev->dest, loname);
else
bdev->lofd = loopfd;
DEBUG("mounted rootfs \"%s\" onto \"%s\" via loop device \"%s\"", bdev->src, bdev->dest, loname);
return 0;
return ret;
}
int loop_umount(struct bdev *bdev)
{
int ret, saved_errno;
int ret;
if (strcmp(bdev->type, "loop"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
ret = umount(bdev->dest);
saved_errno = errno;
if (bdev->lofd >= 0) {
close(bdev->lofd);
bdev->lofd = -1;
}
errno = saved_errno;
if (ret < 0) {
SYSERROR("Failed to umount \"%s\"", bdev->dest);
return -1;
}
return 0;
return ret;
}
static int do_loop_create(const char *path, uint64_t size, const char *fstype)
{
int fd, ret;
char cmd_output[MAXPATHLEN];
const char *cmd_args[2] = {fstype, path};
char cmd_output[MAXPATHLEN];
/* create the new loopback file */
fd = creat(path, S_IRUSR | S_IWUSR);
if (fd < 0) {
SYSERROR("Failed to create new loop file \"%s\"", path);
// create the new loopback file.
fd = creat(path, S_IRUSR|S_IWUSR);
if (fd < 0)
return -1;
}
ret = lseek(fd, size, SEEK_SET);
if (ret < 0) {
SYSERROR("Failed to seek to set new loop file size for loop "
"file \"%s\"", path);
if (lseek(fd, size, SEEK_SET) < 0) {
SYSERROR("Error seeking to set new loop file size");
close(fd);
return -1;
}
ret = write(fd, "1", 1);
if (ret != 1) {
SYSERROR("Failed creating new loop file \"%s\"", path);
if (write(fd, "1", 1) != 1) {
SYSERROR("Error creating new loop file");
close(fd);
return -1;
}
ret = close(fd);
if (ret < 0) {
SYSERROR("Failed to create new loop file \"%s\"", path);
SYSERROR("Error closing new loop file");
return -1;
}
// create an fs in the loopback file
ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
(void *)cmd_args);
if (ret < 0) {
ERROR("Failed to create new filesystem \"%s\" for loop file "
"\"%s\": %s", fstype, path, cmd_output);
if (ret < 0)
return -1;
}
return 0;
}
......@@ -25,7 +25,6 @@
#define __LXC_LVM_H
#define _GNU_SOURCE
#include <stdbool.h>
#include <stdint.h>
/* defined in bdev.h */
......@@ -53,9 +52,5 @@ int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
int lvm_destroy(struct bdev *orig);
int lvm_create(struct bdev *bdev, const char *dest, const char *n,
struct bdev_specs *specs);
bool lvm_create_clone(struct lxc_conf *conf, struct bdev *orig,
struct bdev *new, uint64_t newsize);
bool lvm_create_snapshot(struct lxc_conf *conf, struct bdev *orig,
struct bdev *new, uint64_t newsize);
#endif /* __LXC_LVM_H */
......@@ -116,21 +116,17 @@ int nbd_detect(const char *path)
int nbd_mount(struct bdev *bdev)
{
int ret = -1, partition;
char *src;
char path[50];
if (strcmp(bdev->type, "nbd"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
/* nbd_idx should have been copied by bdev_init from the lxc_conf */
if (bdev->nbd_idx < 0)
return -22;
src = lxc_storage_get_path(bdev->src, bdev->type);
partition = nbd_get_partition(src);
partition = nbd_get_partition(bdev->src);
if (partition)
ret = snprintf(path, 50, "/dev/nbd%dp%d", bdev->nbd_idx,
partition);
......@@ -155,13 +151,14 @@ int nbd_mount(struct bdev *bdev)
int nbd_umount(struct bdev *bdev)
{
int ret;
if (strcmp(bdev->type, "nbd"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
return umount(bdev->dest);
ret = umount(bdev->dest);
return ret;
}
bool requires_nbd(const char *path)
......
......@@ -34,7 +34,6 @@
#include "lxccontainer.h"
#include "lxcoverlay.h"
#include "lxcrsync.h"
#include "storage_utils.h"
#include "utils.h"
lxc_log_define(lxcoverlay, lxc);
......@@ -42,6 +41,10 @@ lxc_log_define(lxcoverlay, lxc);
static char *ovl_name;
static char *ovl_version[] = {"overlay", "overlayfs"};
/* defined in lxccontainer.c: needs to become common helper */
extern char *dir_new_path(char *src, const char *oldname, const char *name,
const char *oldpath, const char *lxcpath);
static char *ovl_detect_name(void);
static int ovl_do_rsync(struct bdev *orig, struct bdev *new,
struct lxc_conf *conf);
......@@ -55,21 +58,17 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath,
int snap, uint64_t newsize, struct lxc_conf *conf)
{
char *src;
if (!snap) {
ERROR("overlay is only for snapshot clones");
ERROR("overlayfs is only for snapshot clones");
return -22;
}
if (!orig->src || !orig->dest)
return -1;
new->dest = lxc_string_join(
"/", (const char *[]){lxcpath, cname, "rootfs", NULL}, false);
new->dest = dir_new_path(orig->dest, oldname, cname, oldpath, lxcpath);
if (!new->dest)
return -1;
if (mkdir_p(new->dest, 0755) < 0)
return -1;
......@@ -134,19 +133,18 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
WARN("Failed to update ownership of %s", work);
free(work);
src = lxc_storage_get_path(orig->src, orig->type);
// the src will be 'overlayfs:lowerdir:upperdir'
len = strlen(delta) + strlen(src) + 12;
len = strlen(delta) + strlen(orig->src) + 12;
new->src = malloc(len);
if (!new->src) {
free(delta);
return -ENOMEM;
}
ret = snprintf(new->src, len, "overlay:%s:%s", src, delta);
ret = snprintf(new->src, len, "overlayfs:%s:%s", orig->src, delta);
free(delta);
if (ret < 0 || ret >= len)
return -1;
} else if (!strcmp(orig->type, "overlayfs") || !strcmp(orig->type, "overlay")) {
return -ENOMEM;
} else if (strcmp(orig->type, "overlayfs") == 0) {
/*
* What exactly do we want to do here? I think we want to use
* the original lowerdir, with a private delta which is
......@@ -155,44 +153,26 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
char *osrc, *odelta, *nsrc, *ndelta, *work;
char *lastslash;
int len, ret, lastslashidx;
osrc = strdup(orig->src);
if (!osrc) {
SYSERROR("Failed to duplicate \"%s\"", orig->src);
if (!(osrc = strdup(orig->src)))
return -22;
}
nsrc = strchr(osrc, ':') + 1;
if ((nsrc != osrc + 8) && (nsrc != osrc + 10)) {
free(osrc);
ERROR("Detected \":\" in \"%s\" at wrong position", osrc);
return -22;
}
odelta = strchr(nsrc, ':');
if (!odelta) {
if (nsrc != osrc + 10 || (odelta = strchr(nsrc, ':')) == NULL) {
free(osrc);
ERROR("Failed to find \":\" in \"%s\"", nsrc);
return -22;
}
*odelta = '\0';
odelta++;
ndelta = lxc_string_join("/", (const char *[]){lxcpath, cname, "rootfs", NULL}, false);
if (!ndelta) {
ndelta = dir_new_path(odelta, oldname, cname, oldpath, lxcpath);
if (!ndelta) {
free(osrc);
ERROR("Failed to create new path");
return -ENOMEM;
}
ret = mkdir(ndelta, 0755);
if (ret < 0 && errno != EEXIST) {
}
if ((ret = mkdir(ndelta, 0755)) < 0 && errno != EEXIST) {
SYSERROR("error: mkdir %s", ndelta);
free(osrc);
free(ndelta);
SYSERROR("Failed to create \"%s\"", ndelta);
return -1;
}
if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0)
WARN("Failed to update ownership of %s", ndelta);
......@@ -204,7 +184,6 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
if (!lastslash) {
free(osrc);
free(ndelta);
ERROR("Failed to detect \"/\" in \"%s\"", ndelta);
return -1;
}
lastslash++;
......@@ -214,43 +193,37 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
if (!work) {
free(osrc);
free(ndelta);
ERROR("Failed to allocate memory");
return -1;
}
strncpy(work, ndelta, lastslashidx + 1);
strcpy(work + lastslashidx, "olwork");
ret = mkdir(work, 0755);
if (ret < 0 && errno != EEXIST) {
if ((mkdir(work, 0755) < 0) && errno != EEXIST) {
SYSERROR("error: mkdir %s", work);
free(osrc);
free(ndelta);
free(work);
SYSERROR("Failed to create \"%s\"", ndelta);
return -1;
}
if (am_unpriv() && chown_mapped_root(work, conf) < 0)
WARN("Failed to update ownership of %s", work);
free(work);
len = strlen(nsrc) + strlen(ndelta) + 10;
len = strlen(nsrc) + strlen(ndelta) + 12;
new->src = malloc(len);
if (!new->src) {
free(osrc);
free(ndelta);
ERROR("Failed to allocate memory");
return -ENOMEM;
}
ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta);
ret = snprintf(new->src, len, "overlayfs:%s:%s", nsrc, ndelta);
free(osrc);
free(ndelta);
if (ret < 0 || ret >= len) {
ERROR("Failed to create string");
return -1;
}
if (ret < 0 || ret >= len)
return -ENOMEM;
return ovl_do_rsync(orig, new, conf);
} else {
ERROR("overlay clone of %s container is not yet supported",
ERROR("overlayfs clone of %s container is not yet supported",
orig->type);
/*
* Note, supporting this will require ovl_mount supporting
......@@ -263,7 +236,7 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
}
/*
* to say 'lxc-create -t ubuntu -n o1 -B overlay' means you want
* to say 'lxc-create -t ubuntu -n o1 -B overlayfs' means you want
* $lxcpath/$lxcname/rootfs to have the created container, while all
* changes after starting the container are written to
* $lxcpath/$lxcname/delta0
......@@ -291,14 +264,14 @@ int ovl_create(struct bdev *bdev, const char *dest, const char *n,
return -1;
}
// overlay:lower:upper
newlen = (2 * len) + strlen("overlay:") + 2;
// overlayfs:lower:upper
newlen = (2 * len) + strlen("overlayfs:") + 2;
bdev->src = malloc(newlen);
if (!bdev->src) {
ERROR("Out of memory");
return -1;
}
ret = snprintf(bdev->src, newlen, "overlay:%s:%s", dest, delta);
ret = snprintf(bdev->src, newlen, "overlayfs:%s:%s", dest, delta);
if (ret < 0 || ret >= newlen)
return -1;
......@@ -312,23 +285,14 @@ int ovl_create(struct bdev *bdev, const char *dest, const char *n,
int ovl_destroy(struct bdev *orig)
{
bool ovl;
char *upper = orig->src;
char *upper;
ovl = !strncmp(upper, "overlay:", 8);
if (!ovl && strncmp(upper, "overlayfs:", 10))
if (strncmp(orig->src, "overlayfs:", 10) != 0)
return -22;
if (ovl)
upper += 8;
else
upper += 10;
upper = strchr(upper, ':');
upper = strchr(orig->src + 10, ':');
if (!upper)
return -22;
upper++;
return lxc_rmdir_onedev(upper, NULL);
}
......@@ -339,6 +303,14 @@ int ovl_detect(const char *path)
return 0;
}
char *ovl_getlower(char *p)
{
char *p1 = strchr(p, ':');
if (p1)
*p1 = '\0';
return p;
}
int ovl_mount(struct bdev *bdev)
{
char *tmp, *options, *dup, *lower, *upper;
......@@ -349,9 +321,8 @@ int ovl_mount(struct bdev *bdev)
char *mntdata;
int ret, ret2;
if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
if (strcmp(bdev->type, "overlayfs"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
......@@ -445,7 +416,7 @@ int ovl_mount(struct bdev *bdev)
ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
MS_MGC_VAL | mntflags, options_work);
if (ret < 0) {
INFO("Overlay: Error mounting %s onto %s with options %s. "
INFO("Overlayfs: Error mounting %s onto %s with options %s. "
"Retrying without workdir: %s.",
lower, bdev->dest, options_work, strerror(errno));
......@@ -453,15 +424,15 @@ int ovl_mount(struct bdev *bdev)
ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
MS_MGC_VAL | mntflags, options);
if (ret < 0)
SYSERROR("Overlay: Error mounting %s onto %s with "
SYSERROR("Overlayfs: Error mounting %s onto %s with "
"options %s: %s.",
lower, bdev->dest, options,
strerror(errno));
else
INFO("Overlay: Mounted %s onto %s with options %s.",
INFO("Overlayfs: Mounted %s onto %s with options %s.",
lower, bdev->dest, options);
} else {
INFO("Overlay: Mounted %s onto %s with options %s.", lower,
INFO("Overlayfs: Mounted %s onto %s with options %s.", lower,
bdev->dest, options_work);
}
return ret;
......@@ -469,31 +440,13 @@ int ovl_mount(struct bdev *bdev)
int ovl_umount(struct bdev *bdev)
{
if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
if (strcmp(bdev->type, "overlayfs"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
return umount(bdev->dest);
}
char *ovl_get_lower(const char *rootfs_path)
{
char *s1;
s1 = strstr(rootfs_path, ":/");
if (!s1)
return NULL;
s1++;
s1 = strstr(s1, ":/");
if (!s1)
return NULL;
s1++;
return s1;
}
char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen)
{
char *rootfsdir = NULL;
......@@ -802,7 +755,7 @@ static int ovl_do_rsync(struct bdev *orig, struct bdev *new, struct lxc_conf *co
else
ret = ovl_rsync(&rdata);
if (ret)
ERROR("copying overlay delta");
ERROR("copying overlayfs delta");
return ret;
}
......
......@@ -76,7 +76,7 @@ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
* To be called from functions in lxccontainer.c: Get lower directory for
* overlay rootfs.
*/
char *ovl_get_lower(const char *rootfs_path);
char *ovl_getlower(char *p);
/*
* Get rootfs path for overlay backed containers. Allocated memory must be freed
......
......@@ -23,7 +23,7 @@
#define _GNU_SOURCE
#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
#include <inttypes.h> /* Required for PRIu64 to work. */
#include <inttypes.h> /* Required for PRIu64 to work. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -36,69 +36,24 @@
lxc_log_define(lxcrbd, lxc);
struct rbd_args {
const char *osd_pool_name;
const char *rbd_name;
const char *size;
};
int rbd_create_wrapper(void *data)
{
struct rbd_args *args = data;
execlp("rbd", "rbd", "create", "--pool", args->osd_pool_name,
args->rbd_name, "--size", args->size, (char *)NULL);
return -1;
}
int rbd_map_wrapper(void *data)
{
struct rbd_args *args = data;
execlp("rbd", "rbd", "map", "--pool", args->osd_pool_name,
args->rbd_name, (char *)NULL);
return -1;
}
int rbd_unmap_wrapper(void *data)
{
struct rbd_args *args = data;
execlp("rbd", "rbd", "unmap", args->rbd_name, (char *)NULL);
return -1;
}
int rbd_delete_wrapper(void *data)
{
struct rbd_args *args = data;
execlp("rbd", "rbd", "rm", args->rbd_name, (char *)NULL);
return -1;
}
int rbd_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath,
int snap, uint64_t newsize, struct lxc_conf *conf)
const char *cname, const char *oldpath, const char *lxcpath,
int snap, uint64_t newsize, struct lxc_conf *conf)
{
ERROR("rbd clonepaths not implemented");
return -1;
}
int rbd_create(struct bdev *bdev, const char *dest, const char *n,
struct bdev_specs *specs)
struct bdev_specs *specs)
{
const char *rbdpool, *fstype;
const char *rbdpool, *rbdname = n, *fstype;
uint64_t size;
int ret, len;
char sz[24];
pid_t pid;
const char *cmd_args[2];
char cmd_output[MAXPATHLEN];
const char *rbdname = n;
struct rbd_args args = {0};
if (!specs)
return -1;
......@@ -111,112 +66,91 @@ int rbd_create(struct bdev *bdev, const char *dest, const char *n,
rbdname = specs->rbd.rbdname;
/* source device /dev/rbd/lxc/ctn */
len = strlen(rbdpool) + strlen(rbdname) + 4 + 11;
len = strlen(rbdpool) + strlen(rbdname) + 11;
bdev->src = malloc(len);
if (!bdev->src) {
ERROR("Failed to allocate memory");
if (!bdev->src)
return -1;
}
ret = snprintf(bdev->src, len, "rbd:/dev/rbd/%s/%s", rbdpool, rbdname);
if (ret < 0 || ret >= len) {
ERROR("Failed to create string");
ret = snprintf(bdev->src, len, "/dev/rbd/%s/%s", rbdpool, rbdname);
if (ret < 0 || ret >= len)
return -1;
}
/* fssize is in bytes */
// fssize is in bytes.
size = specs->fssize;
if (!size)
size = DEFAULT_FS_SIZE;
/* in megabytes for rbd tool */
ret = snprintf(sz, 24, "%" PRIu64, size / 1024 / 1024);
if (ret < 0 || ret >= 24) {
ERROR("Failed to create string");
return -1;
}
// in megabytes for rbd tool
ret = snprintf(sz, 24, "%"PRIu64, size / 1024 / 1024 );
if (ret < 0 || ret >= 24)
exit(1);
args.osd_pool_name = rbdpool;
args.rbd_name = rbdname;
args.size = sz;
ret = run_command(cmd_output, sizeof(cmd_output), rbd_create_wrapper,
(void *)&args);
if (ret < 0) {
ERROR("Failed to create rbd storage volume \"%s\": %s", rbdname,
cmd_output);
if ((pid = fork()) < 0)
return -1;
if (!pid) {
execlp("rbd", "rbd", "create" , "--pool", rbdpool, rbdname, "--size", sz, (char *)NULL);
exit(1);
}
if (wait_for_pid(pid) < 0)
return -1;
ret = run_command(cmd_output, sizeof(cmd_output), rbd_map_wrapper,
(void *)&args);
if (ret < 0) {
ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname,
cmd_output);
if ((pid = fork()) < 0)
return -1;
if (!pid) {
execlp("rbd", "rbd", "map", "--pool", rbdpool, rbdname, (char *)NULL);
exit(1);
}
if (wait_for_pid(pid) < 0)
return -1;
fstype = specs->fstype;
if (!fstype)
fstype = DEFAULT_FSTYPE;
cmd_args[0] = fstype;
cmd_args[1] = lxc_storage_get_path(bdev->src, bdev->type);
cmd_args[1] = bdev->src;
ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
(void *)cmd_args);
if (ret < 0) {
ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname,
cmd_output);
if (ret < 0)
return -1;
}
bdev->dest = strdup(dest);
if (!bdev->dest) {
ERROR("Failed to duplicate string \"%s\"", dest);
if (!(bdev->dest = strdup(dest)))
return -1;
}
ret = mkdir_p(bdev->dest, 0755);
if (ret < 0 && errno != EEXIST) {
ERROR("Failed to create directory \"%s\"", bdev->dest);
if (mkdir_p(bdev->dest, 0755) < 0 && errno != EEXIST) {
ERROR("Error creating %s", bdev->dest);
return -1;
}
TRACE("Created rbd storage volume \"%s\"", bdev->dest);
return 0;
}
int rbd_destroy(struct bdev *orig)
{
int ret;
char *src;
pid_t pid;
char *rbdfullname;
char cmd_output[MAXPATHLEN];
struct rbd_args args = {0};
src = lxc_storage_get_path(orig->src, orig->type);
if (file_exists(src)) {
args.rbd_name = src;
ret = run_command(cmd_output, sizeof(cmd_output),
rbd_unmap_wrapper, (void *)&args);
if (ret < 0) {
ERROR("Failed to map rbd storage volume \"%s\": %s",
src, cmd_output);
if ( file_exists(orig->src) ) {
if ((pid = fork()) < 0)
return -1;
if (!pid) {
execlp("rbd", "rbd", "unmap" , orig->src, (char *)NULL);
exit(1);
}
if (wait_for_pid(pid) < 0)
return -1;
}
rbdfullname = alloca(strlen(src) - 8);
strcpy(rbdfullname, &src[9]);
args.rbd_name = rbdfullname;
ret = run_command(cmd_output, sizeof(cmd_output),
rbd_delete_wrapper, (void *)&args);
if (ret < 0) {
ERROR("Failed to delete rbd storage volume \"%s\": %s",
rbdfullname, cmd_output);
if ((pid = fork()) < 0)
return -1;
if (!pid) {
rbdfullname = alloca(strlen(orig->src) - 8);
strcpy( rbdfullname, &orig->src[9] );
execlp("rbd", "rbd", "rm" , rbdfullname, (char *)NULL);
exit(1);
}
return wait_for_pid(pid);
return 0;
}
int rbd_detect(const char *path)
......@@ -228,33 +162,25 @@ int rbd_detect(const char *path)
int rbd_mount(struct bdev *bdev)
{
char *src;
if (strcmp(bdev->type, "rbd"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
src = lxc_storage_get_path(bdev->src, bdev->type);
if (!file_exists(src)) {
/* If blkdev does not exist it should be mapped, because it is
* not persistent on reboot.
*/
if ( !file_exists(bdev->src) ) {
// if blkdev does not exist it should be mapped, because it is not persistent on reboot
ERROR("Block device %s is not mapped.", bdev->src);
return -1;
}
return mount_unknown_fs(src, bdev->dest, bdev->mntopts);
return mount_unknown_fs(bdev->src, bdev->dest, bdev->mntopts);
}
int rbd_umount(struct bdev *bdev)
{
if (strcmp(bdev->type, "rbd"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
return umount(bdev->dest);
}
......@@ -140,81 +140,3 @@ int rsync_rootfs_wrapper(void *data)
return rsync_rootfs(arg);
}
/* new helpers */
int lxc_rsync_exec_wrapper(void *data)
{
struct rsync_data *arg = data;
return lxc_rsync(arg);
}
int lxc_rsync_exec(const char *src, const char *dest)
{
int ret;
size_t l;
char *s;
l = strlen(src) + 2;
s = malloc(l);
if (!s)
return -1;
ret = snprintf(s, l, "%s", src);
if (ret < 0 || (size_t)ret >= l)
return -1;
s[l - 2] = '/';
s[l - 1] = '\0';
execlp("rsync", "rsync", "-aHXS", "--delete", s, dest, (char *)NULL);
return -1;
}
int lxc_rsync(struct rsync_data *data)
{
int ret;
struct bdev *orig = data->orig, *new = data->new;
char *dest, *src;
ret = unshare(CLONE_NEWNS);
if (ret < 0) {
SYSERROR("Failed to unshare CLONE_NEWNS");
return -1;
}
ret = detect_shared_rootfs();
if (ret) {
ret = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL);
if (ret < 0)
SYSERROR("Failed to make \"/\" a slave mount");
}
ret = orig->ops->mount(orig);
if (ret < 0) {
ERROR("Failed mounting \"%s\" on \"%s\"", orig->src, orig->dest);
return -1;
}
ret = new->ops->mount(new);
if (ret < 0) {
ERROR("Failed mounting \"%s\" onto \"%s\"", new->src, new->dest);
return -1;
}
ret = lxc_switch_uid_gid(0, 0);
if (ret < 0)
return -1;
ret = lxc_setgroups(0, NULL);
if (ret < 0)
return -1;
src = lxc_storage_get_path(orig->dest, orig->type);
dest = lxc_storage_get_path(new->dest, new->type);
ret = lxc_rsync_exec(src, dest);
if (ret < 0) {
ERROR("Failed to rsync from \"%s\" into \"%s\"", src, dest);
return -1;
}
return 0;
}
......@@ -43,9 +43,4 @@ int rsync_delta(struct rsync_data_char *data);
int rsync_rootfs(struct rsync_data *data);
int rsync_rootfs_wrapper(void *data);
/* new helpers */
extern int lxc_rsync_exec_wrapper(void *data);
extern int lxc_rsync_exec(const char *src, const char *dest);
extern int lxc_rsync(struct rsync_data *data);
#endif // __LXC_RSYNC_H
......@@ -85,23 +85,20 @@ int zfs_detect(const char *path)
int zfs_mount(struct bdev *bdev)
{
int ret;
char *mntdata, *src;
unsigned long mntflags;
if (strcmp(bdev->type, "zfs"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
char *mntdata;
unsigned long mntflags;
if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
free(mntdata);
return -22;
}
src = lxc_storage_get_path(bdev->src, bdev->type);
ret = mount(src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
int ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
free(mntdata);
return ret;
......@@ -208,7 +205,6 @@ int zfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath, int snap,
uint64_t newsize, struct lxc_conf *conf)
{
char *origsrc, *newsrc;
int len, ret;
if (!orig->src || !orig->dest)
......@@ -219,22 +215,19 @@ int zfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
return -1;
}
len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 4 + 3;
len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3;
new->src = malloc(len);
if (!new->src)
return -1;
ret = snprintf(new->src, len, "zfs:%s/%s/rootfs", lxcpath, cname);
ret = snprintf(new->src, len, "%s/%s/rootfs", lxcpath, cname);
if (ret < 0 || ret >= len)
return -1;
newsrc = lxc_storage_get_path(new->src, new->type);
new->dest = strdup(newsrc);
if (!new->dest)
if ((new->dest = strdup(new->src)) == NULL)
return -1;
origsrc = lxc_storage_get_path(orig->src, orig->type);
return zfs_clone(origsrc, newsrc, oldname, cname, lxcpath, snap);
return zfs_clone(orig->src, new->src, oldname, cname, lxcpath, snap);
}
/*
......@@ -246,15 +239,14 @@ int zfs_destroy(struct bdev *orig)
{
pid_t pid;
char output[MAXPATHLEN];
char *p, *src;
char *p;
if ((pid = fork()) < 0)
return -1;
if (pid)
return wait_for_pid(pid);
src = lxc_storage_get_path(orig->src, orig->type);
if (!zfs_list_entry(src, output, MAXPATHLEN)) {
if (!zfs_list_entry(orig->src, output, MAXPATHLEN)) {
ERROR("Error: zfs entry for %s not found", orig->src);
return -1;
}
......@@ -268,64 +260,41 @@ int zfs_destroy(struct bdev *orig)
exit(EXIT_FAILURE);
}
struct zfs_exec_args {
char *dataset;
char *options;
};
int zfs_create_exec_wrapper(void *args)
{
struct zfs_exec_args *zfs_args = args;
execlp("zfs", "zfs", "create", zfs_args->options, zfs_args->dataset,
(char *)NULL);
return -1;
}
int zfs_create(struct bdev *bdev, const char *dest, const char *n,
struct bdev_specs *specs)
{
const char *zfsroot;
char cmd_output[MAXPATHLEN], dev[MAXPATHLEN], option[MAXPATHLEN];
char option[MAXPATHLEN];
int ret;
size_t len;
struct zfs_exec_args cmd_args;
pid_t pid;
if (!specs || !specs->zfs.zfsroot)
zfsroot = lxc_global_config_value("lxc.bdev.zfs.root");
else
zfsroot = specs->zfs.zfsroot;
bdev->dest = strdup(dest);
if (!bdev->dest) {
if (!(bdev->dest = strdup(dest))) {
ERROR("No mount target specified or out of memory");
return -1;
}
len = strlen(bdev->dest) + 1;
/* strlen("zfs:") */
len += 4;
bdev->src = malloc(len);
if (!bdev->src)
return -1;
ret = snprintf(bdev->src, len, "zfs:%s", bdev->dest);
if (ret < 0 || (size_t)ret >= len)
if (!(bdev->src = strdup(bdev->dest))) {
ERROR("out of memory");
return -1;
}
ret = snprintf(option, MAXPATHLEN, "-omountpoint=%s", bdev->dest);
if (ret < 0 || ret >= MAXPATHLEN)
return -1;
if ((pid = fork()) < 0)
return -1;
if (pid)
return wait_for_pid(pid);
char dev[MAXPATHLEN];
ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, n);
if (ret < 0 || ret >= MAXPATHLEN)
return -1;
exit(EXIT_FAILURE);
cmd_args.options = option;
cmd_args.dataset = dev;
ret = run_command(cmd_output, sizeof(cmd_output),
zfs_create_exec_wrapper, (void *)&cmd_args);
if (ret < 0)
ERROR("Failed to create zfs dataset \"%s\": %s", dev, cmd_output);
return ret;
execlp("zfs", "zfs", "create", option, dev, (char *)NULL);
exit(EXIT_FAILURE);
}
......@@ -129,10 +129,12 @@ bool attach_block_device(struct lxc_conf *conf)
int blk_getsize(struct bdev *bdev, uint64_t *size)
{
int fd, ret;
char *src;
char *path = bdev->src;
src = lxc_storage_get_path(bdev->src, bdev->type);
fd = open(src, O_RDONLY);
if (strcmp(bdev->type, "loop") == 0)
path = bdev->src + 5;
fd = open(path, O_RDONLY);
if (fd < 0)
return -1;
......@@ -161,12 +163,15 @@ int detect_fs(struct bdev *bdev, char *type, int len)
size_t linelen;
pid_t pid;
FILE *f;
char *sp1, *sp2, *sp3, *srcdev, *line = NULL;
char *sp1, *sp2, *sp3, *line = NULL;
char *srcdev;
if (!bdev || !bdev->src || !bdev->dest)
return -1;
srcdev = lxc_storage_get_path(bdev->src, bdev->type);
srcdev = bdev->src;
if (strcmp(bdev->type, "loop") == 0)
srcdev = bdev->src + 5;
ret = pipe(p);
if (ret < 0)
......@@ -415,7 +420,6 @@ bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
// overlayfs -- which is also allowed)
if (strcmp(b->type, "dir") == 0 ||
strcmp(b->type, "aufs") == 0 ||
strcmp(b->type, "overlay") == 0 ||
strcmp(b->type, "overlayfs") == 0 ||
strcmp(b->type, "btrfs") == 0 ||
strcmp(b->type, "loop") == 0)
......@@ -428,7 +432,6 @@ bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
// and loop. In particular, not zfs, btrfs, or lvm.
if (strcmp(t, "dir") == 0 ||
strcmp(t, "aufs") == 0 ||
strcmp(t, "overlay") == 0 ||
strcmp(t, "overlayfs") == 0 ||
strcmp(t, "btrfs") == 0 ||
strcmp(t, "loop") == 0)
......
......@@ -3623,6 +3623,7 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
{
uid_t rootuid, rootgid;
unsigned long val;
char *chownpath = path;
int hostuid, hostgid, ret;
struct stat sb;
char map1[100], map2[100], map3[100], map4[100], map5[100];
......@@ -3658,6 +3659,23 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
}
rootgid = (gid_t)val;
/*
* In case of overlay, we want only the writeable layer to be chowned
*/
if (strncmp(path, "overlayfs:", 10) == 0 || strncmp(path, "aufs:", 5) == 0) {
chownpath = strchr(path, ':');
if (!chownpath) {
ERROR("Bad overlay path: %s", path);
return -1;
}
chownpath = strchr(chownpath + 1, ':');
if (!chownpath) {
ERROR("Bad overlay path: %s", path);
return -1;
}
chownpath++;
}
path = chownpath;
if (hostuid == 0) {
if (chown(path, rootuid, rootgid) < 0) {
ERROR("Error chowning %s", path);
......
......@@ -1265,10 +1265,8 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
exit(1);
}
} else { // TODO come up with a better way here!
char *src;
free(bdev->dest);
src = lxc_storage_get_path(bdev->src, bdev->type);
bdev->dest = strdup(src);
bdev->dest = strdup(bdev->src);
}
/*
......@@ -1433,7 +1431,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
}
/* execute */
execvp(tpath, newargv);
SYSERROR("Failed to execute template %s", tpath);
SYSERROR("failed to execute template %s", tpath);
exit(1);
}
......@@ -3225,8 +3223,8 @@ static int clone_update_rootfs_wrapper(void *data)
sudo lxc-clone -o o1 -n n1 -s -L|-fssize fssize -v|--vgname vgname \
-p|--lvprefix lvprefix -t|--fstype fstype -B backingstore
-s [ implies overlay]
-s -B overlay
-s [ implies overlayfs]
-s -B overlayfs
-s -B aufs
only rootfs gets converted (copied/snapshotted) on clone.
......@@ -3600,7 +3598,7 @@ static int do_lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
if (bdev_is_dir(c->lxc_conf, c->lxc_conf->rootfs.path)) {
ERROR("Snapshot of directory-backed container requested.");
ERROR("Making a copy-clone. If you do want snapshots, then");
ERROR("please create an aufs or overlay clone first, snapshot that");
ERROR("please create an aufs or overlayfs clone first, snapshot that");
ERROR("and keep the original container pristine.");
flags &= ~LXC_CLONE_SNAPSHOT | LXC_CLONE_MAYBE_SNAPSHOT;
}
......
......@@ -171,7 +171,7 @@ static bool do_destroy(struct lxc_container *c)
if (ret < 0 || ret >= MAXPATHLEN)
return false;
if (rmdir(path) < 0 && errno != ENOENT) {
if (dir_exists(path)) {
if (!quiet)
fprintf(stdout, "Destroying %s failed: %s has snapshots.\n", c->name, c->name);
return false;
......@@ -271,7 +271,7 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
if (ret < 0 || ret >= MAXPATHLEN)
return false;
if (rmdir(path) < 0 && errno != ENOENT)
if (dir_exists(path))
bret = c->destroy_with_snapshots(c);
else
bret = do_destroy(c);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment