mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-06 03:36:04 +00:00
Split bdev into modules: lxczfs
The functions: - zfs_clone(); - zfs_clonepaths(); - zfs_create(); - zfs_destroy(); - zfs_detect(); - zfs_list_entry(); - zfs_mount(); - zfs_umount(); move from bdev.c to lxczfs.{c,h}. All functions previously declared as static become public. Adapt Makefile.am to include lxczfs.{c,h}. The structs: - struct bdev; /* defined in bdev.h */ - struct bdev_specs; /* defined in lxccontainer.h */ - struct lxc_conf; /* defined conf.h */ are forward declared/put as incomplete types into lxczfs.h as the functions associated with zfs need access to it. Minor changes: - Use exit(EXIT_FAILURE) instead of exit(1). - Use brackets around else {} if the if {} did: I.e. instead of: if { // do one; // do two; } else // do three; use: if { // do one; // do two; } else { // do three; } - Instead of declaring char pointers and arrays on the same line, i.e.: char arr[len], *p; do: char arr[len]; char *p; which makes intentions a lot clearer. - Since we require c99 anyway, use finer-grained scoping by declaring variables where they are needed instead of simply at the top. Signed-off-by: Christian Brauner <christian.brauner@mailbox.org>
This commit is contained in:
parent
4dbfaf3084
commit
8907f44457
@ -10,6 +10,7 @@ noinst_HEADERS = \
|
||||
bdev/lxcbtrfs.h \
|
||||
bdev/lxcoverlay.h \
|
||||
bdev/lxcrsync.h \
|
||||
bdev/lxczfs.h \
|
||||
caps.h \
|
||||
cgroup.h \
|
||||
conf.h \
|
||||
@ -66,6 +67,7 @@ liblxc_so_SOURCES = \
|
||||
bdev/lxcbtrfs.c bdev/lxcbtrfs.h \
|
||||
bdev/lxcoverlay.c bdev/lxcoverlay.h \
|
||||
bdev/lxcrsync.c bdev/lxcrsync.h \
|
||||
bdev/lxczfs.c bdev/lxczfs.h \
|
||||
commands.c commands.h \
|
||||
start.c start.h \
|
||||
execute.c \
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "lxclock.h"
|
||||
#include "lxcoverlay.h"
|
||||
#include "lxcrsync.h"
|
||||
#include "lxczfs.h"
|
||||
#include "namespace.h"
|
||||
#include "parse.h"
|
||||
#include "utils.h"
|
||||
@ -491,271 +492,6 @@ static const struct bdev_ops dir_ops = {
|
||||
.can_backup = true,
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// XXXXXXX zfs ops
|
||||
// There are two ways we could do this. We could always specify the
|
||||
// 'zfs device' (i.e. tank/lxc lxc/container) as rootfs. But instead
|
||||
// (at least right now) we have lxc-create specify $lxcpath/$lxcname/rootfs
|
||||
// as the mountpoint, so that it is always mounted.
|
||||
//
|
||||
// That means 'mount' is really never needed and could be noop, but for the
|
||||
// sake of flexibility let's always bind-mount.
|
||||
//
|
||||
|
||||
static int zfs_list_entry(const char *path, char *output, size_t inlen)
|
||||
{
|
||||
struct lxc_popen_FILE *f;
|
||||
int found=0;
|
||||
|
||||
f = lxc_popen("zfs list 2> /dev/null");
|
||||
if (f == NULL) {
|
||||
SYSERROR("popen failed");
|
||||
return 0;
|
||||
}
|
||||
while (fgets(output, inlen, f->f)) {
|
||||
if (strstr(output, path)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
(void) lxc_pclose(f);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static int zfs_detect(const char *path)
|
||||
{
|
||||
char *output = malloc(LXC_LOG_BUFFER_SIZE);
|
||||
int found;
|
||||
|
||||
if (!output) {
|
||||
ERROR("out of memory");
|
||||
return 0;
|
||||
}
|
||||
found = zfs_list_entry(path, output, LXC_LOG_BUFFER_SIZE);
|
||||
free(output);
|
||||
return found;
|
||||
}
|
||||
|
||||
static int zfs_mount(struct bdev *bdev)
|
||||
{
|
||||
unsigned long mntflags;
|
||||
char *mntdata;
|
||||
int ret;
|
||||
|
||||
if (strcmp(bdev->type, "zfs"))
|
||||
return -22;
|
||||
if (!bdev->src || !bdev->dest)
|
||||
return -22;
|
||||
|
||||
if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
|
||||
free(mntdata);
|
||||
return -22;
|
||||
}
|
||||
|
||||
ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
|
||||
free(mntdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int zfs_umount(struct bdev *bdev)
|
||||
{
|
||||
if (strcmp(bdev->type, "zfs"))
|
||||
return -22;
|
||||
if (!bdev->src || !bdev->dest)
|
||||
return -22;
|
||||
return umount(bdev->dest);
|
||||
}
|
||||
|
||||
static int zfs_clone(const char *opath, const char *npath, const char *oname,
|
||||
const char *nname, const char *lxcpath, int snapshot)
|
||||
{
|
||||
// use the 'zfs list | grep opath' entry to get the zfsroot
|
||||
char output[MAXPATHLEN], option[MAXPATHLEN], *p;
|
||||
const char *zfsroot = output;
|
||||
int ret;
|
||||
pid_t pid;
|
||||
|
||||
if (zfs_list_entry(opath, output, MAXPATHLEN)) {
|
||||
// zfsroot is output up to ' '
|
||||
if ((p = strchr(output, ' ')) == NULL)
|
||||
return -1;
|
||||
*p = '\0';
|
||||
if ((p = strrchr(output, '/')) == NULL)
|
||||
return -1;
|
||||
*p = '\0';
|
||||
} else
|
||||
zfsroot = lxc_global_config_value("lxc.bdev.zfs.root");
|
||||
|
||||
ret = snprintf(option, MAXPATHLEN, "-omountpoint=%s/%s/rootfs",
|
||||
lxcpath, nname);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
return -1;
|
||||
|
||||
// zfs create -omountpoint=$lxcpath/$lxcname $zfsroot/$nname
|
||||
if (!snapshot) {
|
||||
if ((pid = fork()) < 0)
|
||||
return -1;
|
||||
if (!pid) {
|
||||
char dev[MAXPATHLEN];
|
||||
|
||||
ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, nname);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
exit(1);
|
||||
execlp("zfs", "zfs", "create", option, dev, NULL);
|
||||
exit(1);
|
||||
}
|
||||
return wait_for_pid(pid);
|
||||
} else {
|
||||
// if snapshot, do
|
||||
// 'zfs snapshot zfsroot/oname@nname
|
||||
// zfs clone zfsroot/oname@nname zfsroot/nname
|
||||
char path1[MAXPATHLEN], path2[MAXPATHLEN];
|
||||
|
||||
ret = snprintf(path1, MAXPATHLEN, "%s/%s@%s", zfsroot,
|
||||
oname, nname);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
return -1;
|
||||
(void) snprintf(path2, MAXPATHLEN, "%s/%s", zfsroot, nname);
|
||||
|
||||
// if the snapshot exists, delete it
|
||||
if ((pid = fork()) < 0)
|
||||
return -1;
|
||||
if (!pid) {
|
||||
execlp("zfs", "zfs", "destroy", path1, NULL);
|
||||
exit(1);
|
||||
}
|
||||
// it probably doesn't exist so destroy probably will fail.
|
||||
(void) wait_for_pid(pid);
|
||||
|
||||
// run first (snapshot) command
|
||||
if ((pid = fork()) < 0)
|
||||
return -1;
|
||||
if (!pid) {
|
||||
execlp("zfs", "zfs", "snapshot", path1, NULL);
|
||||
exit(1);
|
||||
}
|
||||
if (wait_for_pid(pid) < 0)
|
||||
return -1;
|
||||
|
||||
// run second (clone) command
|
||||
if ((pid = fork()) < 0)
|
||||
return -1;
|
||||
if (!pid) {
|
||||
execlp("zfs", "zfs", "clone", option, path1, path2, NULL);
|
||||
exit(1);
|
||||
}
|
||||
return wait_for_pid(pid);
|
||||
}
|
||||
}
|
||||
|
||||
static 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)
|
||||
{
|
||||
int len, ret;
|
||||
|
||||
if (!orig->src || !orig->dest)
|
||||
return -1;
|
||||
|
||||
if (snap && strcmp(orig->type, "zfs")) {
|
||||
ERROR("zfs snapshot from %s backing store is not supported",
|
||||
orig->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
if ((new->dest = strdup(new->src)) == NULL)
|
||||
return -1;
|
||||
|
||||
return zfs_clone(orig->src, new->src, oldname, cname, lxcpath, snap);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: detect whether this was a clone, and if so then also delete the
|
||||
* snapshot it was based on, so that we don't hold the original
|
||||
* container busy.
|
||||
*/
|
||||
static int zfs_destroy(struct bdev *orig)
|
||||
{
|
||||
pid_t pid;
|
||||
char output[MAXPATHLEN], *p;
|
||||
|
||||
if ((pid = fork()) < 0)
|
||||
return -1;
|
||||
if (pid)
|
||||
return wait_for_pid(pid);
|
||||
|
||||
if (!zfs_list_entry(orig->src, output, MAXPATHLEN)) {
|
||||
ERROR("Error: zfs entry for %s not found", orig->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// zfs mount is output up to ' '
|
||||
if ((p = strchr(output, ' ')) == NULL)
|
||||
return -1;
|
||||
*p = '\0';
|
||||
|
||||
execlp("zfs", "zfs", "destroy", output, NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int zfs_create(struct bdev *bdev, const char *dest, const char *n,
|
||||
struct bdev_specs *specs)
|
||||
{
|
||||
const char *zfsroot;
|
||||
char option[MAXPATHLEN];
|
||||
int ret;
|
||||
pid_t pid;
|
||||
|
||||
if (!specs || !specs->zfs.zfsroot)
|
||||
zfsroot = lxc_global_config_value("lxc.bdev.zfs.root");
|
||||
else
|
||||
zfsroot = specs->zfs.zfsroot;
|
||||
|
||||
if (!(bdev->dest = strdup(dest))) {
|
||||
ERROR("No mount target specified or out of memory");
|
||||
return -1;
|
||||
}
|
||||
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)
|
||||
exit(1);
|
||||
execlp("zfs", "zfs", "create", option, dev, NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static const struct bdev_ops zfs_ops = {
|
||||
.detect = &zfs_detect,
|
||||
.mount = &zfs_mount,
|
||||
.umount = &zfs_umount,
|
||||
.clone_paths = &zfs_clonepaths,
|
||||
.destroy = &zfs_destroy,
|
||||
.create = &zfs_create,
|
||||
.can_snapshot = true,
|
||||
.can_backup = true,
|
||||
};
|
||||
|
||||
//
|
||||
// LVM ops
|
||||
//
|
||||
@ -1628,6 +1364,18 @@ static const struct bdev_ops ovl_ops = {
|
||||
.can_backup = true,
|
||||
};
|
||||
|
||||
/* zfs */
|
||||
static const struct bdev_ops zfs_ops = {
|
||||
.detect = &zfs_detect,
|
||||
.mount = &zfs_mount,
|
||||
.umount = &zfs_umount,
|
||||
.clone_paths = &zfs_clonepaths,
|
||||
.destroy = &zfs_destroy,
|
||||
.create = &zfs_create,
|
||||
.can_snapshot = true,
|
||||
.can_backup = true,
|
||||
};
|
||||
|
||||
//
|
||||
// aufs ops
|
||||
//
|
||||
|
296
src/lxc/bdev/lxczfs.c
Normal file
296
src/lxc/bdev/lxczfs.c
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* lxc: linux Container library
|
||||
*
|
||||
* (C) Copyright IBM Corp. 2007, 2008
|
||||
*
|
||||
* Authors:
|
||||
* Daniel Lezcano <daniel.lezcano at free.fr>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include "bdev.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "lxczfs.h"
|
||||
#include "utils.h"
|
||||
|
||||
lxc_log_define(lxczfs, lxc);
|
||||
|
||||
/*
|
||||
* zfs ops:
|
||||
* There are two ways we could do this. We could always specify the 'zfs device'
|
||||
* (i.e. tank/lxc lxc/container) as rootfs. But instead (at least right now) we
|
||||
* have lxc-create specify $lxcpath/$lxcname/rootfs as the mountpoint, so that
|
||||
* it is always mounted. That means 'mount' is really never needed and could be
|
||||
* noop, but for the sake of flexibility let's always bind-mount.
|
||||
*/
|
||||
|
||||
int zfs_list_entry(const char *path, char *output, size_t inlen)
|
||||
{
|
||||
struct lxc_popen_FILE *f;
|
||||
int found=0;
|
||||
|
||||
f = lxc_popen("zfs list 2> /dev/null");
|
||||
if (f == NULL) {
|
||||
SYSERROR("popen failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fgets(output, inlen, f->f)) {
|
||||
if (strstr(output, path)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
(void) lxc_pclose(f);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
int zfs_detect(const char *path)
|
||||
{
|
||||
char *output = malloc(LXC_LOG_BUFFER_SIZE);
|
||||
|
||||
if (!output) {
|
||||
ERROR("out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int found = zfs_list_entry(path, output, LXC_LOG_BUFFER_SIZE);
|
||||
free(output);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
int zfs_mount(struct bdev *bdev)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
int ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
|
||||
free(mntdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int zfs_umount(struct bdev *bdev)
|
||||
{
|
||||
if (strcmp(bdev->type, "zfs"))
|
||||
return -22;
|
||||
|
||||
if (!bdev->src || !bdev->dest)
|
||||
return -22;
|
||||
|
||||
return umount(bdev->dest);
|
||||
}
|
||||
|
||||
int zfs_clone(const char *opath, const char *npath, const char *oname,
|
||||
const char *nname, const char *lxcpath, int snapshot)
|
||||
{
|
||||
// use the 'zfs list | grep opath' entry to get the zfsroot
|
||||
char output[MAXPATHLEN], option[MAXPATHLEN];
|
||||
char *p;
|
||||
const char *zfsroot = output;
|
||||
int ret;
|
||||
pid_t pid;
|
||||
|
||||
if (zfs_list_entry(opath, output, MAXPATHLEN)) {
|
||||
// zfsroot is output up to ' '
|
||||
if ((p = strchr(output, ' ')) == NULL)
|
||||
return -1;
|
||||
*p = '\0';
|
||||
|
||||
if ((p = strrchr(output, '/')) == NULL)
|
||||
return -1;
|
||||
*p = '\0';
|
||||
} else {
|
||||
zfsroot = lxc_global_config_value("lxc.bdev.zfs.root");
|
||||
}
|
||||
|
||||
ret = snprintf(option, MAXPATHLEN, "-omountpoint=%s/%s/rootfs", lxcpath, nname);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
return -1;
|
||||
|
||||
// zfs create -omountpoint=$lxcpath/$lxcname $zfsroot/$nname
|
||||
if (!snapshot) {
|
||||
if ((pid = fork()) < 0)
|
||||
return -1;
|
||||
if (!pid) {
|
||||
char dev[MAXPATHLEN];
|
||||
ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, nname);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
exit(EXIT_FAILURE);
|
||||
execlp("zfs", "zfs", "create", option, dev, NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return wait_for_pid(pid);
|
||||
} else {
|
||||
// if snapshot, do
|
||||
// 'zfs snapshot zfsroot/oname@nname
|
||||
// zfs clone zfsroot/oname@nname zfsroot/nname
|
||||
char path1[MAXPATHLEN], path2[MAXPATHLEN];
|
||||
|
||||
ret = snprintf(path1, MAXPATHLEN, "%s/%s@%s", zfsroot,
|
||||
oname, nname);
|
||||
if (ret < 0 || ret >= MAXPATHLEN)
|
||||
return -1;
|
||||
(void) snprintf(path2, MAXPATHLEN, "%s/%s", zfsroot, nname);
|
||||
|
||||
// if the snapshot exists, delete it
|
||||
if ((pid = fork()) < 0)
|
||||
return -1;
|
||||
if (!pid) {
|
||||
execlp("zfs", "zfs", "destroy", path1, NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// it probably doesn't exist so destroy probably will fail.
|
||||
(void) wait_for_pid(pid);
|
||||
|
||||
// run first (snapshot) command
|
||||
if ((pid = fork()) < 0)
|
||||
return -1;
|
||||
if (!pid) {
|
||||
execlp("zfs", "zfs", "snapshot", path1, NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (wait_for_pid(pid) < 0)
|
||||
return -1;
|
||||
|
||||
// run second (clone) command
|
||||
if ((pid = fork()) < 0)
|
||||
return -1;
|
||||
if (!pid) {
|
||||
execlp("zfs", "zfs", "clone", option, path1, path2, NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return wait_for_pid(pid);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int len, ret;
|
||||
|
||||
if (!orig->src || !orig->dest)
|
||||
return -1;
|
||||
|
||||
if (snap && strcmp(orig->type, "zfs")) {
|
||||
ERROR("zfs snapshot from %s backing store is not supported", orig->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if ((new->dest = strdup(new->src)) == NULL)
|
||||
return -1;
|
||||
|
||||
return zfs_clone(orig->src, new->src, oldname, cname, lxcpath, snap);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: detect whether this was a clone, and if so then also delete the
|
||||
* snapshot it was based on, so that we don't hold the original
|
||||
* container busy.
|
||||
*/
|
||||
int zfs_destroy(struct bdev *orig)
|
||||
{
|
||||
pid_t pid;
|
||||
char output[MAXPATHLEN];
|
||||
char *p;
|
||||
|
||||
if ((pid = fork()) < 0)
|
||||
return -1;
|
||||
if (pid)
|
||||
return wait_for_pid(pid);
|
||||
|
||||
if (!zfs_list_entry(orig->src, output, MAXPATHLEN)) {
|
||||
ERROR("Error: zfs entry for %s not found", orig->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// zfs mount is output up to ' '
|
||||
if ((p = strchr(output, ' ')) == NULL)
|
||||
return -1;
|
||||
*p = '\0';
|
||||
|
||||
execlp("zfs", "zfs", "destroy", output, NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int zfs_create(struct bdev *bdev, const char *dest, const char *n,
|
||||
struct bdev_specs *specs)
|
||||
{
|
||||
const char *zfsroot;
|
||||
char option[MAXPATHLEN];
|
||||
int ret;
|
||||
pid_t pid;
|
||||
|
||||
if (!specs || !specs->zfs.zfsroot)
|
||||
zfsroot = lxc_global_config_value("lxc.bdev.zfs.root");
|
||||
else
|
||||
zfsroot = specs->zfs.zfsroot;
|
||||
|
||||
if (!(bdev->dest = strdup(dest))) {
|
||||
ERROR("No mount target specified or out of memory");
|
||||
return -1;
|
||||
}
|
||||
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)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
execlp("zfs", "zfs", "create", option, dev, NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
61
src/lxc/bdev/lxczfs.h
Normal file
61
src/lxc/bdev/lxczfs.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* lxc: linux Container library
|
||||
*
|
||||
* (C) Copyright IBM Corp. 2007, 2008
|
||||
*
|
||||
* Authors:
|
||||
* Daniel Lezcano <daniel.lezcano at free.fr>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __LXC_ZFS_H
|
||||
#define __LXC_ZFS_H
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* defined in bdev.h */
|
||||
struct bdev;
|
||||
|
||||
/* defined in lxccontainer.h */
|
||||
struct bdev_specs;
|
||||
|
||||
/* defined conf.h */
|
||||
struct lxc_conf;
|
||||
|
||||
/*
|
||||
* Functions associated with an zfs bdev struct.
|
||||
*/
|
||||
int zfs_clone(const char *opath, const char *npath, const char *oname,
|
||||
const char *nname, const char *lxcpath, int snapshot);
|
||||
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);
|
||||
int zfs_create(struct bdev *bdev, const char *dest, const char *n,
|
||||
struct bdev_specs *specs);
|
||||
/*
|
||||
* TODO: detect whether this was a clone, and if so then also delete the
|
||||
* snapshot it was based on, so that we don't hold the original
|
||||
* container busy.
|
||||
*/
|
||||
int zfs_destroy(struct bdev *orig);
|
||||
int zfs_detect(const char *path);
|
||||
int zfs_list_entry(const char *path, char *output, size_t inlen);
|
||||
int zfs_mount(struct bdev *bdev);
|
||||
int zfs_umount(struct bdev *bdev);
|
||||
|
||||
#endif /* __LXC_ZFS_H */
|
Loading…
Reference in New Issue
Block a user