int ret;
if ((ret = pthread_mutex_unlock(l)) != 0) {
- fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret));
+ fprintf(stderr, "%s: pthread_mutex_unlock returned:%d %s\n",
+ __FILE__, ret, strerror(ret));
exit(1);
}
}
return -1;
}
- bdev = storage_init(conf, rootfs->path, rootfs->mount, rootfs->options);
+ bdev = storage_init(conf);
if (!bdev) {
ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\".",
rootfs->path, rootfs->mount,
* root is privileged with respect to hostuid/hostgid X, allowing
* him to do the chown.
*/
-int chown_mapped_root(char *path, struct lxc_conf *conf)
+int chown_mapped_root(const char *path, struct lxc_conf *conf)
{
uid_t rootuid, rootgid;
unsigned long val;
struct stat sb;
char map1[100], map2[100], map3[100], map4[100], map5[100];
char ugid[100];
- char *args1[] = {"lxc-usernsexec",
+ const char *args1[] = {"lxc-usernsexec",
"-m", map1,
"-m", map2,
"-m", map3,
"-m", map5,
"--", "chown", ugid, path,
NULL};
- char *args2[] = {"lxc-usernsexec",
+ const char *args2[] = {"lxc-usernsexec",
"-m", map1,
"-m", map2,
"-m", map3,
extern int find_unmapped_nsid(struct lxc_conf *conf, enum idtype idtype);
extern int mapped_hostid(unsigned id, struct lxc_conf *conf,
enum idtype idtype);
-extern int chown_mapped_root(char *path, struct lxc_conf *conf);
+extern int chown_mapped_root(const char *path, struct lxc_conf *conf);
extern int lxc_ttys_shift_ids(struct lxc_conf *c);
extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
const char *fn_name);
static int set_config_rootfs_path(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- return set_config_path_item(&lxc_conf->rootfs.path, value);
+ int ret;
+ char *dup, *tmp;
+ const char *container_path;
+
+ if (lxc_config_value_empty(value)) {
+ free(lxc_conf->rootfs.path);
+ lxc_conf->rootfs.path = NULL;
+ return 0;
+ }
+
+ dup = strdup(value);
+ if (!dup)
+ return -1;
+
+ /* Split <storage type>:<container path> into <storage type> and
+ * <container path>. Set "rootfs.bdev_type" to <storage type> and
+ * "rootfs.path" to <container path>.
+ */
+ tmp = strchr(dup, ':');
+ if (tmp) {
+ *tmp = '\0';
+ ret = set_config_path_item(&lxc_conf->rootfs.bdev_type, dup);
+ if (ret < 0) {
+ free(dup);
+ return -1;
+ }
+ tmp++;
+ container_path = tmp;
+ } else {
+ container_path = value;
+ }
+
+ ret = set_config_path_item(&lxc_conf->rootfs.path, container_path);
+ free(dup);
+ return ret;
}
static int set_config_rootfs_mount(const char *key, const char *value,
switch (n->type) {
case LXC_NET_VETH:
veth = n->priv.veth_attr.pair;
+ if (veth[0] == '\0')
+ veth = n->priv.veth_attr.veth1;
if (n->link[0] != '\0') {
if (external_not_veth)
#include "start.h"
#include "state.h"
#include "storage.h"
+#include "storage_utils.h"
#include "storage/btrfs.h"
#include "storage/overlay.h"
#include "sync.h"
const char *type,
struct bdev_specs *specs)
{
- char *dest;
+ int ret;
size_t len;
+ char *dest;
struct lxc_storage *bdev;
- int ret;
/* rootfs.path or lxcpath/lxcname/rootfs */
- if (c->lxc_conf->rootfs.path && !access(c->lxc_conf->rootfs.path, F_OK)) {
+ if (c->lxc_conf->rootfs.path &&
+ (access(c->lxc_conf->rootfs.path, F_OK) == 0)) {
const char *rpath = c->lxc_conf->rootfs.path;
len = strlen(rpath) + 1;
dest = alloca(len);
dest = alloca(len);
ret = snprintf(dest, len, "%s/%s/rootfs", lxcpath, c->name);
}
- if (ret < 0 || ret >= len)
+ if (ret < 0 || (size_t)ret >= len)
return NULL;
bdev = storage_create(dest, type, c->name, specs);
if (!bdev) {
- ERROR("Failed to create backing store type %s", type);
+ ERROR("Failed to create \"%s\" storage", type);
return NULL;
}
if (!c->set_config_item(c, "lxc.rootfs.path", bdev->src)) {
- ERROR("Failed to set config item \"lxc.rootfs.path\" to \"%s\"",
- bdev->src);
+ ERROR("Failed to set \"lxc.rootfs.path = %s\"", bdev->src);
return NULL;
}
- /* If we are not root, chown the rootfs dir to root in the
- * target uidmap.
+ /* If we are not root, chown the rootfs dir to root in the target user
+ * namespace.
*/
- if (geteuid() != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) {
- if (chown_mapped_root(bdev->dest, c->lxc_conf) < 0) {
- ERROR("Error chowning %s to container root", bdev->dest);
+ ret = geteuid();
+ if (ret != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) {
+ ret = chown_mapped_root(bdev->dest, c->lxc_conf);
+ if (ret < 0) {
+ ERROR("Error chowning \"%s\" to container root", bdev->dest);
suggest_default_idmap();
storage_put(bdev);
return NULL;
exit(1);
}
- bdev = storage_init(c->lxc_conf, c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL);
+ bdev = storage_init(c->lxc_conf);
if (!bdev) {
ERROR("Error opening rootfs");
exit(1);
}
}
} else { /* TODO come up with a better way here! */
- char *src;
+ const char *src;
free(bdev->dest);
src = lxc_storage_get_path(bdev->src, bdev->type);
bdev->dest = strdup(src);
const char *bdevtype, struct bdev_specs *specs, int flags,
char *const argv[])
{
- bool ret = false;
+ int partial_fd;
pid_t pid;
+ bool ret = false;
char *tpath = NULL;
- int partial_fd;
if (!c)
return false;
if (t) {
tpath = get_template_path(t);
if (!tpath) {
- ERROR("bad template: %s", t);
+ ERROR("Unknown template \"%s\"", t);
goto out;
}
}
- /*
- * If a template is passed in, and the rootfs already is defined in
- * the container config and exists, then * caller is trying to create
- * an existing container. Return an error, but do NOT delete the
- * container.
+ /* If a template is passed in, and the rootfs already is defined in the
+ * container config and exists, then the caller is trying to create an
+ * existing container. Return an error, but do NOT delete the container.
*/
if (do_lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path &&
access(c->lxc_conf->rootfs.path, F_OK) == 0 && tpath) {
- ERROR("Container %s:%s already exists", c->config_path, c->name);
+ ERROR("Container \"%s\" already exists in \"%s\"", c->name,
+ c->config_path);
goto free_tpath;
}
if (!c->lxc_conf) {
if (!do_lxcapi_load_config(c, lxc_global_config_value("lxc.default_config"))) {
- ERROR("Error loading default configuration file %s", lxc_global_config_value("lxc.default_config"));
+ ERROR("Error loading default configuration file %s",
+ lxc_global_config_value("lxc.default_config"));
goto free_tpath;
}
}
if (!create_container_dir(c))
goto free_tpath;
- /*
- * if both template and rootfs.path are set, template is setup as rootfs.path.
- * container is already created if we have a config and rootfs.path is accessible
+ /* If both template and rootfs.path are set, template is setup as
+ * rootfs.path. The container is already created if we have a config and
+ * rootfs.path is accessible
*/
if (!c->lxc_conf->rootfs.path && !tpath) {
- /* no template passed in and rootfs does not exist */
+ /* No template passed in and rootfs does not exist. */
if (!c->save_config(c, NULL)) {
- ERROR("failed to save starting configuration for %s\n", c->name);
+ ERROR("Failed to save initial config for \"%s\"", c->name);
goto out;
}
ret = true;
goto out;
}
+
+ /* Rootfs passed into configuration, but does not exist. */
if (c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) != 0)
- /* rootfs passed into configuration, but does not exist: error */
goto out;
+
if (do_lxcapi_is_defined(c) && c->lxc_conf->rootfs.path && !tpath) {
- /* Rootfs already existed, user just wanted to save the
- * loaded configuration */
+ /* Rootfs already existed, user just wanted to save the loaded
+ * configuration.
+ */
if (!c->save_config(c, NULL))
- ERROR("failed to save starting configuration for %s\n", c->name);
+ ERROR("Failed to save initial config for \"%s\"", c->name);
ret = true;
goto out;
}
/* Mark that this container is being created */
- if ((partial_fd = create_partial(c)) < 0)
+ partial_fd = create_partial(c);
+ if (partial_fd < 0)
goto out;
- /* no need to get disk lock bc we have the partial locked */
+ /* No need to get disk lock bc we have the partial lock. */
- /*
- * Create the backing store
+ /* Create the storage.
* Note we can't do this in the same task as we use to execute the
* template because of the way zfs works.
* After you 'zfs create', zfs mounts the fs only in the initial
*/
pid = fork();
if (pid < 0) {
- SYSERROR("failed to fork task for container creation template");
+ SYSERROR("Failed to fork task for container creation template");
goto out_unlock;
}
bdev = do_storage_create(c, bdevtype, specs);
if (!bdev) {
- ERROR("Error creating backing store type %s for %s",
- bdevtype ? bdevtype : "(none)", c->name);
+ ERROR("Failed to create %s storage for %s",
+ bdevtype ? bdevtype : "(none)", c->name);
exit(EXIT_FAILURE);
}
- /* save config file again to store the new rootfs location */
+ /* Save config file again to store the new rootfs location. */
if (!do_lxcapi_save_config(c, NULL)) {
- ERROR("failed to save starting configuration for %s", c->name);
- /* Parent task won't see bdev in config so we delete it. */
+ ERROR("Failed to save initial config for %s", c->name);
+ /* Parent task won't see the storage driver in the
+ * config so we delete it.
+ */
bdev->ops->umount(bdev);
bdev->ops->destroy(bdev);
exit(EXIT_FAILURE);
if (wait_for_pid(pid) != 0)
goto out_unlock;
- /* reload config to get the rootfs */
+ /* Reload config to get the rootfs. */
lxc_conf_free(c->lxc_conf);
c->lxc_conf = NULL;
if (!load_config_locked(c, c->configfile))
if (t) {
if (!prepend_lxc_header(c->configfile, tpath, argv)) {
- ERROR("Error prepending header to configuration file");
+ ERROR("Failed to prepend header to config file");
goto out_unlock;
}
}
}
static bool lxcapi_create(struct lxc_container *c, const char *t,
- const char *bdevtype, struct bdev_specs *specs, int flags,
- char *const argv[])
+ const char *bdevtype, struct bdev_specs *specs,
+ int flags, char *const argv[])
{
bool ret;
current_config = c ? c->lxc_conf : NULL;
args = lxc_va_arg_list_to_argv(ap, 0, 0);
va_end(ap);
if (!args) {
- ERROR("Memory allocation error.");
+ ERROR("Failed to allocate memory");
goto out;
}
if (unshare(CLONE_NEWNS) < 0)
return -1;
- bdev = storage_init(c->lxc_conf, c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL);
+ bdev = storage_init(c->lxc_conf);
if (!bdev)
return -1;
if (strcmp(bdev->type, "dir") != 0) {
ERROR("Renaming a container with snapshots is not supported");
return false;
}
- bdev = storage_init(c->lxc_conf, c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL);
+ bdev = storage_init(c->lxc_conf);
if (!bdev) {
ERROR("Failed to find original backing store type");
return false;
*/
flags = LXC_CLONE_SNAPSHOT | LXC_CLONE_KEEPMACADDR | LXC_CLONE_KEEPNAME |
LXC_CLONE_KEEPBDEVTYPE | LXC_CLONE_MAYBE_SNAPSHOT;
- if (storage_is_dir(c->lxc_conf, c->lxc_conf->rootfs.path)) {
+ if (storage_is_dir(c->lxc_conf)) {
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");
return false;
}
- bdev = storage_init(c->lxc_conf, c->lxc_conf->rootfs.path,
- c->lxc_conf->rootfs.mount, NULL);
+ bdev = storage_init(c->lxc_conf);
if (!bdev) {
ERROR("Failed to find original backing store type");
return false;
if (!strcmp(bdev->type, "overlay") || !strcmp(bdev->type, "overlayfs"))
flags |= LXC_STORAGE_INTERNAL_OVERLAY_RESTORE;
- rest = lxcapi_clone(snap, newname, c->config_path, flags,
- bdev->type, NULL, 0, NULL);
+ rest = lxcapi_clone(snap, newname, c->config_path, flags, bdev->type,
+ NULL, 0, NULL);
storage_put(bdev);
if (rest && lxcapi_is_defined(rest))
b = true;
c = malloc(sizeof(*c));
if (!c) {
- fprintf(stderr, "failed to malloc lxc_container\n");
+ fprintf(stderr, "Failed to allocate memory for %s\n", name);
return NULL;
}
memset(c, 0, sizeof(*c));
c->config_path = strdup(lxc_global_config_value("lxc.lxcpath"));
if (!c->config_path) {
- fprintf(stderr, "Out of memory\n");
+ fprintf(stderr, "Failed to allocate memory for %s\n", name);
goto err;
}
remove_trailing_slashes(c->config_path);
c->name = malloc(strlen(name)+1);
if (!c->name) {
- fprintf(stderr, "Error allocating lxc_container name\n");
+ fprintf(stderr, "Failed to allocate memory for %s\n", name);
goto err;
}
strcpy(c->name, name);
c->numthreads = 1;
- if (!(c->slock = lxc_newlock(c->config_path, name))) {
- fprintf(stderr, "failed to create lock\n");
+ c->slock = lxc_newlock(c->config_path, name);
+ if (!c->slock) {
+ fprintf(stderr, "Failed to create lock for %s\n", name);
goto err;
}
- if (!(c->privlock = lxc_newlock(NULL, NULL))) {
- fprintf(stderr, "failed to alloc privlock\n");
+ c->privlock = lxc_newlock(NULL, NULL);
+ if (!c->privlock) {
+ fprintf(stderr, "Failed to create private lock for %s\n", name);
goto err;
}
if (!set_config_filename(c)) {
- fprintf(stderr, "Error allocating config file pathname\n");
+ fprintf(stderr, "Failed to create config file name for %s\n", name);
goto err;
}
- if (file_exists(c->configfile) && !lxcapi_load_config(c, NULL))
+ if (file_exists(c->configfile) && !lxcapi_load_config(c, NULL)) {
+ fprintf(stderr, "Failed to load config for %s\n", name);
goto err;
+ }
if (ongoing_create(c) == 2) {
- ERROR("Error: %s creation was not completed", c->name);
+ ERROR("Failed to complete container creation for %s", c->name);
container_destroy(c, NULL);
lxcapi_clear_config(c);
}
int ret;
if ((ret = pthread_mutex_unlock(l)) != 0) {
- fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret));
+ fprintf(stderr, "%s: pthread_mutex_unlock returned:%d %s\n",
+ __FILE__, ret, strerror(ret));
dump_stacktrace();
exit(EXIT_FAILURE);
}
int btrfs_mount(struct lxc_storage *bdev)
{
unsigned long mntflags;
- char *mntdata, *src;
+ char *mntdata;
+ const char *src;
int ret;
if (strcmp(bdev->type, "btrfs"))
int btrfs_snapshot_wrapper(void *data)
{
- char *src;
+ const char *src;
struct rsync_data_char *arg = data;
if (setgid(0) < 0) {
const char *oldpath, const char *lxcpath, int snap,
uint64_t newsize, struct lxc_conf *conf)
{
- char *src;
+ const char *src;
if (!orig->dest || !orig->src)
return -1;
return true;
}
- ret = btrfs_snapshot(orig->dest, new->dest);
+ ret = btrfs_snapshot(orig->src, new->dest);
if (ret < 0) {
SYSERROR("Failed to create btrfs snapshot \"%s\" from \"%s\"",
new->dest, orig->dest);
int btrfs_destroy(struct lxc_storage *orig)
{
- char *src;
+ const char *src;
src = lxc_storage_get_path(orig->src, "btrfs");
const char *lxcpath, int snap, uint64_t newsize,
struct lxc_conf *conf)
{
- char *src_no_prefix;
+ const char *src_no_prefix;
int ret;
size_t len;
int dir_destroy(struct lxc_storage *orig)
{
int ret;
- char *src;
+ const char *src;
src = lxc_storage_get_path(orig->src, orig->src);
{
int ret;
unsigned long mflags, mntflags;
- char *src, *mntdata;
+ char *mntdata;
+ const char *src;
if (strcmp(bdev->type, "dir"))
return -22;
}
int loop_destroy(struct lxc_storage *orig) {
- return unlink(orig->src + 5);
+ char *dir;
+
+ dir = orig->src;
+ if (strncmp(orig->src, "loop:", 5) == 0)
+ dir += 5;
+
+ return unlink(dir);
}
bool loop_detect(const char *path)
{
int ret, loopfd;
char loname[MAXPATHLEN];
- char *src;
+ const char *src;
if (strcmp(bdev->type, "loop"))
return -22;
int lvm_mount(struct lxc_storage *bdev)
{
- char *src;
+ const char *src;
if (strcmp(bdev->type, "lvm"))
return -22;
static int lvm_snapshot(struct lxc_storage *orig, const char *path, uint64_t size)
{
int ret;
- char *origsrc, *pathdup, *lv;
+ char *lv, *pathdup;
char sz[24];
char fstype[100];
char cmd_output[MAXPATHLEN];
char repairchar;
+ const char *origsrc;
struct lvcreate_args cmd_args = {0};
ret = snprintf(sz, 24, "%" PRIu64 "b", size);
(const char *[]){"lvm:", "dev", vg, cname, NULL},
false);
} else {
- char *dup, *slider, *src;
+ const char *src;
+ char *dup, *slider;
src = lxc_storage_get_path(orig->src, orig->type);
bool lvm_create_clone(struct lxc_conf *conf, struct lxc_storage *orig,
struct lxc_storage *new, uint64_t newsize)
{
- char *src;
- const char *thinpool;
int ret;
+ const char *src;
+ const char *thinpool;
struct rsync_data data;
- char *cmd_args[2];
+ const char *cmd_args[2];
char cmd_output[MAXPATHLEN] = {0};
char fstype[100] = "ext4";
uint64_t size = newsize;
struct lxc_storage *new, uint64_t newsize)
{
int ret;
- char *newsrc;
+ const char *newsrc;
uint64_t size = newsize;
if (is_blktype(orig)) {
int nbd_mount(struct lxc_storage *bdev)
{
int ret = -1, partition;
- char *src;
+ const char *src;
char path[50];
if (strcmp(bdev->type, "nbd"))
int snap, uint64_t newsize, struct lxc_conf *conf)
{
int ret;
- char *src;
+ const char *src;
if (!snap) {
ERROR("The overlay storage driver can only be used for "
return -22;
}
- nsrc = strchr(osrc, ':') + 1;
- if ((nsrc != osrc + 8) && (nsrc != osrc + 10)) {
- ERROR("Detected \":\" in \"%s\" at wrong position", osrc);
- free(osrc);
- return -22;
- }
+ nsrc = osrc;
+ if (strncmp(osrc, "overlay:", 8) == 0)
+ nsrc += 8;
+ else if (strncmp(osrc, "overlayfs:", 10) == 0)
+ nsrc += 10;
odelta = strchr(nsrc, ':');
if (!odelta) {
int ovl_destroy(struct lxc_storage *orig)
{
- bool ovl;
char *upper = orig->src;
- ovl = !strncmp(upper, "overlay:", 8);
- if (!ovl && strncmp(upper, "overlayfs:", 10))
- return -22;
-
/* For an overlay container the rootfs is considered immutable
* and cannot be removed when restoring from a snapshot.
*/
if (orig->flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)
return 0;
- if (ovl)
+ if (strncmp(upper, "overlay:", 8) == 0)
upper += 8;
- else
+ else if (strncmp(upper, "overlayfs:", 10) == 0)
upper += 10;
upper = strchr(upper, ':');
bool ovl_detect(const char *path)
{
- if (!strncmp(path, "overlayfs:", 10))
+ if (!strncmp(path, "overlay:", 8))
return true;
- if (!strncmp(path, "overlay:", 8))
+ if (!strncmp(path, "overlayfs:", 10))
return true;
return false;
ERROR("Failed to allocate memory");
return -1;
}
+ upper = dup;
+ lower = dup;
- /* support multiple lower layers */
- lower = strstr(dup, ":/");
- if (!lower) {
- ERROR("Failed to detect \":/\" in string \"%s\"", dup);
- free(dup);
- return -22;
- }
+ if (strncmp(dup, "overlay:", 8) == 0)
+ lower += 8;
+ else if (strncmp(dup, "overlayfs:", 10) == 0)
+ lower += 10;
+ if (upper != lower)
+ upper = lower;
- lower++;
- upper = lower;
- while ((tmp = strstr(++upper, ":/"))) {
+ /* support multiple lower layers */
+ while ((tmp = strstr(upper, ":/"))) {
+ tmp++;
upper = tmp;
}
return ret;
}
-char *ovl_get_lower(const char *rootfs_path)
+const char *ovl_get_lower(const char *rootfs_path)
{
- char *s1;
+ const char *s1 = rootfs_path;
- s1 = strstr(rootfs_path, ":/");
- if (!s1)
- return NULL;
- s1++;
+ if (strncmp(rootfs_path, "overlay:", 8) == 0)
+ s1 += 8;
+ else if (strncmp(rootfs_path, "overlayfs:", 10) == 0)
+ s1 += 10;
s1 = strstr(s1, ":/");
if (!s1)
if (!s1)
return NULL;
- s2 = strstr(s1, ":/");
- if (s2) {
- s2 = s2 + 1;
- if ((s3 = strstr(s2, ":/")))
- *s3 = '\0';
- rootfsdir = strdup(s2);
- if (!rootfsdir) {
- free(s1);
- return NULL;
- }
+ s2 = s1;
+ if (strncmp(rootfs_path, "overlay:", 8) == 0)
+ s2 += 8;
+ else if (strncmp(rootfs_path, "overlayfs:", 10) == 0)
+ s2 += 10;
+
+ s3 = strstr(s2, ":/");
+ if (s3)
+ *s3 = '\0';
+
+ rootfsdir = strdup(s2);
+ if (!rootfsdir) {
+ free(s1);
+ return NULL;
}
if (!rootfsdir)
/* To be called from functions in lxccontainer.c: Get lower directory for
* overlay rootfs.
*/
-extern char *ovl_get_lower(const char *rootfs_path);
+extern const char *ovl_get_lower(const char *rootfs_path);
/* Get rootfs path for overlay backed containers. Allocated memory must be freed
* by caller.
int rbd_destroy(struct lxc_storage *orig)
{
int ret;
- char *src;
+ const char *src;
char *rbdfullname;
char cmd_output[MAXPATHLEN];
struct rbd_args args = {0};
int rbd_mount(struct lxc_storage *bdev)
{
- char *src;
+ const char *src;
if (strcmp(bdev->type, "rbd"))
return -22;
int lxc_rsync(struct rsync_data *data)
{
int ret;
- char *dest, *src;
+ const char *dest, *src;
struct lxc_storage *orig = data->orig, *new = data->new;
ret = unshare(CLONE_NEWNS);
static const size_t numbdevs = sizeof(bdevs) / sizeof(struct lxc_storage_type);
-static const struct lxc_storage_type *get_storage_by_name(const char *name)
+static const struct lxc_storage_type *get_storage_by_name(const char *path,
+ const char *type)
{
+ int ret;
size_t i, cmplen;
- cmplen = strcspn(name, ":");
+ if (type)
+ cmplen = strlen(type);
+ else
+ cmplen = strcspn(path, ":");
if (cmplen == 0)
return NULL;
- for (i = 0; i < numbdevs; i++)
- if (strncmp(bdevs[i].name, name, cmplen) == 0)
+ for (i = 0; i < numbdevs; i++) {
+ if (type)
+ ret = strncmp(bdevs[i].name, type, cmplen);
+ else
+ ret = strncmp(bdevs[i].name, path, cmplen);
+ if (ret == 0)
break;
+ }
if (i == numbdevs)
return NULL;
return &bdevs[i];
}
-const struct lxc_storage_type *storage_query(struct lxc_conf *conf,
- const char *src)
+static const struct lxc_storage_type *storage_query(struct lxc_conf *conf)
{
size_t i;
const struct lxc_storage_type *bdev;
+ const char *path = conf->rootfs.path;
+ const char *type = conf->rootfs.bdev_type;
- bdev = get_storage_by_name(src);
+ bdev = get_storage_by_name(path, type);
if (bdev)
return bdev;
for (i = 0; i < numbdevs; i++)
- if (bdevs[i].ops->detect(src))
+ if (bdevs[i].ops->detect(path))
break;
if (i == numbdevs)
size_t i;
struct lxc_storage *bdev;
- for (i = 0; i < numbdevs; i++) {
+ for (i = 0; i < numbdevs; i++)
if (strcmp(bdevs[i].name, type) == 0)
break;
- }
if (i == numbdevs)
return NULL;
bdev->ops = bdevs[i].ops;
bdev->type = bdevs[i].name;
- if (!strcmp(bdev->type, "aufs"))
+ if (strcmp(bdev->type, "aufs") == 0)
WARN("The \"aufs\" driver will is deprecated and will soon be "
"removed. For similar functionality see the \"overlay\" "
"storage driver");
const char *cname,
struct bdev_specs *specs)
{
-
+ int ret;
struct lxc_storage *bdev;
if (!type)
if (!bdev)
return NULL;
- if (bdev->ops->create(bdev, dest, cname, specs) < 0) {
+ ret = bdev->ops->create(bdev, dest, cname, specs);
+ if (ret < 0) {
storage_put(bdev);
return NULL;
}
bool storage_can_backup(struct lxc_conf *conf)
{
- struct lxc_storage *bdev = storage_init(conf, NULL, NULL, NULL);
bool ret;
+ struct lxc_storage *bdev;
+ bdev = storage_init(conf);
if (!bdev)
return false;
uint64_t newsize, bool *needs_rdep)
{
int ret;
- struct lxc_storage *orig, *new;
- char *src_no_prefix;
- bool snap = flags & LXC_CLONE_SNAPSHOT;
- bool maybe_snap = flags & LXC_CLONE_MAYBE_SNAPSHOT;
- bool keepbdevtype = flags & LXC_CLONE_KEEPBDEVTYPE;
+ const char *src_no_prefix;
+ struct lxc_storage *new, *orig;
+ bool snap = (flags & LXC_CLONE_SNAPSHOT);
+ bool maybe_snap = (flags & LXC_CLONE_MAYBE_SNAPSHOT);
+ bool keepbdevtype = (flags & LXC_CLONE_KEEPBDEVTYPE);
const char *src = c->lxc_conf->rootfs.path;
const char *oldname = c->name;
const char *oldpath = c->config_path;
- struct rsync_data data = {0};
char cmd_output[MAXPATHLEN] = {0};
+ struct rsync_data data = {0};
if (!src) {
ERROR("No rootfs specified");
return NULL;
}
- orig = storage_init(c->lxc_conf, src, NULL, NULL);
+ orig = storage_init(c->lxc_conf);
if (!orig) {
- ERROR("Failed to detect storage driver for \"%s\"", src);
+ ERROR("Failed to detect storage driver for \"%s\"", oldname);
return NULL;
}
/* get new bdev type */
new = storage_get(bdevtype);
if (!new) {
- ERROR("Failed to initialize \"%s\" storage driver",
+ ERROR("Failed to initialize %s storage driver",
bdevtype ? bdevtype : orig->type);
goto on_error_put_orig;
}
- TRACE("Initialized \"%s\" storage driver", new->type);
+ TRACE("Initialized %s storage driver", new->type);
/* create new paths */
ret = new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
* snapshot directory under "<lxcpath>/<name>/snaps/" we don't need to
* record a dependency. If we would restore would also fail.
*/
- if ((!strcmp(new->type, "overlay") ||
- !strcmp(new->type, "overlayfs")) &&
+ if ((strcmp(new->type, "overlay") == 0 ||
+ strcmp(new->type, "overlayfs") == 0) &&
ret == LXC_CLONE_SNAPSHOT)
*needs_rdep = false;
/* btrfs */
if (!strcmp(orig->type, "btrfs") && !strcmp(new->type, "btrfs")) {
- bool bret = false;
+ bool bret;
+
if (snap || btrfs_same_fs(orig->dest, new->dest) == 0)
bret = new->ops->snapshot(c->lxc_conf, orig, new, 0);
else
/* lvm */
if (!strcmp(orig->type, "lvm") && !strcmp(new->type, "lvm")) {
- bool bret = false;
+ bool bret;
+
if (snap)
- bret = new->ops->snapshot(c->lxc_conf, orig,
- new, newsize);
+ bret = new->ops->snapshot(c->lxc_conf, orig, new, newsize);
else
bret = new->ops->copy(c->lxc_conf, orig, new, newsize);
if (!bret)
/* zfs */
if (!strcmp(orig->type, "zfs") && !strcmp(new->type, "zfs")) {
- bool bret = false;
+ bool bret;
if (snap)
- bret = new->ops->snapshot(c->lxc_conf, orig, new,
- newsize);
+ bret = new->ops->snapshot(c->lxc_conf, orig, new, newsize);
else
bret = new->ops->copy(c->lxc_conf, orig, new, newsize);
if (!bret)
struct lxc_storage *storage_create(const char *dest, const char *type,
const char *cname, struct bdev_specs *specs)
{
+ int ret;
struct lxc_storage *bdev;
char *best_options[] = {"btrfs", "zfs", "lvm", "dir", "rbd", NULL};
if (!type)
return do_storage_create(dest, "dir", cname, specs);
- if (strcmp(type, "best") == 0) {
+ ret = strcmp(type, "best");
+ if (ret == 0) {
int i;
/* Try for the best backing store type, according to our
* opinionated preferences.
*/
for (i = 0; best_options[i]; i++) {
- bdev = do_storage_create(dest, best_options[i], cname,
- specs);
+ bdev = do_storage_create(dest, best_options[i], cname, specs);
if (bdev)
return bdev;
}
}
/* -B lvm,dir */
- if (strchr(type, ',') != NULL) {
- char *dup = alloca(strlen(type) + 1), *saveptr = NULL, *token;
+ if (strchr(type, ',')) {
+ char *dup, *token;
+ char *saveptr = NULL;
+
+ dup = alloca(strlen(type) + 1);
strcpy(dup, type);
for (token = strtok_r(dup, ",", &saveptr); token;
token = strtok_r(NULL, ",", &saveptr)) {
- if ((bdev = do_storage_create(dest, token, cname, specs)))
+ bdev = do_storage_create(dest, token, cname, specs);
+ if (bdev)
return bdev;
}
}
struct lxc_storage *r;
bool ret = false;
- r = storage_init(conf, conf->rootfs.path, conf->rootfs.mount, NULL);
+ r = storage_init(conf);
if (!r)
return ret;
- if (r->ops->destroy(r) == 0)
+ ret = r->ops->destroy(r);
+ if (ret == 0)
ret = true;
storage_put(r);
return ret;
}
-struct lxc_storage *storage_init(struct lxc_conf *conf, const char *src,
- const char *dst, const char *mntopts)
+struct lxc_storage *storage_init(struct lxc_conf *conf)
{
struct lxc_storage *bdev;
const struct lxc_storage_type *q;
+ const char *src = conf->rootfs.path;
+ const char *dst = conf->rootfs.mount;
+ const char *mntopts = conf->rootfs.options;
BUILD_BUG_ON(LXC_STORAGE_INTERNAL_OVERLAY_RESTORE <= LXC_CLONE_MAXFLAGS);
- if (!src)
- src = conf->rootfs.path;
-
if (!src)
return NULL;
- q = storage_query(conf, src);
+ q = storage_query(conf);
if (!q)
return NULL;
return NULL;
memset(bdev, 0, sizeof(struct lxc_storage));
+
bdev->ops = q->ops;
bdev->type = q->name;
+
if (mntopts)
bdev->mntopts = strdup(mntopts);
+
if (src)
bdev->src = strdup(src);
+
if (dst)
bdev->dest = strdup(dst);
+
if (strcmp(bdev->type, "nbd") == 0)
bdev->nbd_idx = conf->nbd_idx;
- if (!strcmp(bdev->type, "aufs"))
+ if (strcmp(bdev->type, "aufs") == 0)
WARN("The \"aufs\" driver will is deprecated and will soon be "
"removed. For similar functionality see the \"overlay\" "
"storage driver");
return bdev;
}
-bool storage_is_dir(struct lxc_conf *conf, const char *path)
+bool storage_is_dir(struct lxc_conf *conf)
{
struct lxc_storage *orig;
+ char *type = conf->rootfs.bdev_type;
bool bret = false;
- orig = storage_init(conf, path, NULL, NULL);
+ if (type)
+ return (strcmp(type, "dir") == 0);
+
+ orig = storage_init(conf);
if (!orig)
return bret;
if (ret == 0 && S_ISBLK(st.st_mode))
return true;
- q = storage_query(conf, conf->rootfs.path);
+ q = storage_query(conf);
if (!q)
return false;
return false;
}
-char *lxc_storage_get_path(char *src, const char *prefix)
+const char *lxc_storage_get_path(char *src, const char *prefix)
{
size_t prefix_len;
int flags;
};
-extern bool storage_is_dir(struct lxc_conf *conf, const char *path);
+/**
+ * storage_is_dir : Check whether the roots is a directory. This function will
+ * trust the config file. If the config file key
+ * lxc.rootfs.path is set to <storage type>:<container path>
+ * the confile parser will have split this into <storage type>
+ * and <container path> and set the <bdev_type> member in the
+ * lxc_rootfs struct to <storage type> and the <path> member
+ * will be set to a clean <container path> without the <storage
+ * type> prefix. This is the new, clean way of handling storage
+ * type specifications. If the <storage type> prefix is not
+ * detected liblxc will try to detect the storage type.
+ */
+extern bool storage_is_dir(struct lxc_conf *conf);
extern bool storage_can_backup(struct lxc_conf *conf);
-/* Instantiate a lxc_storage object. The src is used to determine which blockdev
- * type this should be. The dst and data are optional, and will be used in case
- * of mount/umount.
- *
- * The source will be "dir:/var/lib/lxc/c1" or "lvm:/dev/lxc/c1". For other
- * backing stores, this will allow additional options. In particular,
- * "overlayfs:/var/lib/lxc/canonical/rootfs:/var/lib/lxc/c1/delta" will mean use
- * /var/lib/lxc/canonical/rootfs as lower dir, and /var/lib/lxc/c1/delta as the
- * upper, writeable layer.
- */
-extern struct lxc_storage *storage_init(struct lxc_conf *conf, const char *src,
- const char *dst, const char *data);
+extern struct lxc_storage *storage_init(struct lxc_conf *conf);
-extern struct lxc_storage *storage_copy(struct lxc_container *c0,
+extern struct lxc_storage *storage_copy(struct lxc_container *c,
const char *cname, const char *lxcpath,
const char *bdevtype, int flags,
const char *bdevdata, uint64_t newsize,
struct bdev_specs *specs);
extern void storage_put(struct lxc_storage *bdev);
extern bool storage_destroy(struct lxc_conf *conf);
-
-extern int storage_destroy_wrapper(void *data);
extern bool rootfs_is_blockdev(struct lxc_conf *conf);
-extern char *lxc_storage_get_path(char *src, const char *prefix);
+extern const char *lxc_storage_get_path(char *src, const char *prefix);
#endif /* #define __LXC_STORAGE_H */
int blk_getsize(struct lxc_storage *bdev, uint64_t *size)
{
int fd, ret;
- char *src;
+ const char *src;
src = lxc_storage_get_path(bdev->src, bdev->type);
fd = open(src, O_RDONLY);
*/
int detect_fs(struct lxc_storage *bdev, char *type, int len)
{
- int p[2], ret;
+ int ret;
+ int p[2];
size_t linelen;
pid_t pid;
FILE *f;
- char *sp1, *sp2, *sp3, *srcdev, *line = NULL;
+ char *sp1, *sp2, *sp3;
+ const char *l, *srcdev;
+ char devpath[MAXPATHLEN];
+ char *line = NULL;
if (!bdev || !bdev->src || !bdev->dest)
return -1;
exit(1);
}
- /* if symlink, get the real dev name */
- char devpath[MAXPATHLEN];
- char *l = linkderef(srcdev, devpath);
+ l = linkderef(srcdev, devpath);
if (!l)
exit(1);
f = fopen("/proc/self/mounts", "r");
return 1;
}
-char *linkderef(char *path, char *dest)
+const char *linkderef(const char *path, char *dest)
{
struct stat sbuf;
ssize_t ret;
extern int mount_unknown_fs(const char *rootfs, const char *target,
const char *options);
extern int find_fstype_cb(char *buffer, void *data);
-extern char *linkderef(char *path, char *dest);
+extern const char *linkderef(const char *path, char *dest);
extern bool unpriv_snap_allowed(struct lxc_storage *b, const char *t, bool snap,
bool maybesnap);
extern bool is_valid_storage_type(const char *type);
{
int ret;
size_t oldlen, newlen, totallen;
- char *mntdata, *src, *tmp;
+ char *mntdata, *tmp;
+ const char *src;
unsigned long mntflags;
char cmd_output[MAXPATHLEN] = {0};
char cmd_output[MAXPATHLEN], option[MAXPATHLEN];
struct rsync_data data = {0, 0};
struct zfs_args cmd_args = {0};
- char *argv[] = {"zfs", /* 0 */
- "create", /* 1 */
- "-o", "", /* 2, 3 */
- "-o", "canmount=noauto", /* 4, 5 */
- "-p", /* 6 */
- "", /* 7 */
- NULL};
+ const char *argv[] = {"zfs", /* 0 */
+ "create", /* 1 */
+ "-o", "", /* 2, 3 */
+ "-o", "canmount=noauto", /* 4, 5 */
+ "-p", /* 6 */
+ "", /* 7 */
+ NULL};
/* mountpoint */
ret = snprintf(option, MAXPATHLEN, "mountpoint=%s", new->dest);
{
int ret;
size_t snapshot_len, len;
- char *orig_src, *tmp, *snap_name, *snapshot;
+ char *tmp, *snap_name, *snapshot;
+ const char *orig_src;
struct zfs_args cmd_args = {0};
char cmd_output[MAXPATHLEN] = {0}, option[MAXPATHLEN];
const char *lxcpath, int snap, uint64_t newsize,
struct lxc_conf *conf)
{
- char *dataset, *orig_src, *tmp;
int ret;
+ char *dataset, *tmp;
+ const char *orig_src;
size_t dataset_len, len;
char cmd_output[MAXPATHLEN] = {0};
int zfs_destroy(struct lxc_storage *orig)
{
int ret;
- char *dataset, *src, *tmp;
+ char *dataset, *tmp;
+ const char *src;
bool found;
char *parent_snapshot = NULL;
struct zfs_args cmd_args = {0};
size_t len;
struct zfs_args cmd_args = {0};
char cmd_output[MAXPATHLEN], option[MAXPATHLEN];
- char *argv[] = {"zfs", /* 0 */
- "create", /* 1 */
- "-o", "", /* 2, 3 */
- "-o", "canmount=noauto", /* 4, 5 */
- "-p", /* 6 */
- "", /* 7 */
- NULL};
+ const char *argv[] = {"zfs", /* 0 */
+ "create", /* 1 */
+ "-o", "", /* 2, 3 */
+ "-o", "canmount=noauto", /* 4, 5 */
+ "-p", /* 6 */
+ "", /* 7 */
+ NULL};
if (!specs || !specs->zfs.zfsroot)
zfsroot = lxc_global_config_value("lxc.bdev.zfs.root");
*/
extern bool btrfs_try_remove_subvol(const char *path);
-static int _recursive_rmdir(char *dirname, dev_t pdev,
+static int _recursive_rmdir(const char *dirname, dev_t pdev,
const char *exclude, int level, bool onedev)
{
struct dirent *direntp;
}
/* returns 0 on success, -1 if there were any failures */
-extern int lxc_rmdir_onedev(char *path, const char *exclude)
+extern int lxc_rmdir_onedev(const char *path, const char *exclude)
{
struct stat mystat;
bool onedev = true;
- if (is_native_overlayfs(path)) {
+ if (is_native_overlayfs(path))
onedev = false;
- }
if (lstat(path, &mystat) < 0) {
if (errno == ENOENT)
return 0;
+
ERROR("Failed to stat %s", path);
return -1;
}
#define LXC_IDMAPLEN 4096
/* returns 1 on success, 0 if there were any failures */
-extern int lxc_rmdir_onedev(char *path, const char *exclude);
+extern int lxc_rmdir_onedev(const char *path, const char *exclude);
extern int get_u16(unsigned short *val, const char *arg, int base);
extern int mkdir_p(const char *dir, mode_t mode);
extern char *get_rundir(void);