};
static const struct bdev_type bdevs[] = {
+ { .name = "dir", .ops = &dir_ops, },
{ .name = "zfs", .ops = &zfs_ops, },
{ .name = "lvm", .ops = &lvm_ops, },
{ .name = "rbd", .ops = &rbd_ops, },
{ .name = "btrfs", .ops = &btrfs_ops, },
- { .name = "dir", .ops = &dir_ops, },
{ .name = "aufs", .ops = &aufs_ops, },
{ .name = "overlayfs", .ops = &ovl_ops, },
{ .name = "loop", .ops = &loop_ops, },
static const struct bdev_type *get_bdev_by_name(const char *name)
{
- size_t i;
+ size_t i, cmplen;
- for (i = 0; i < numbdevs; i++) {
- if (strcmp(bdevs[i].name, name) == 0)
- return &bdevs[i];
- }
+ cmplen = strcspn(name, ":");
+ if (cmplen == 0)
+ return NULL;
- ERROR("Backing store %s unknown but not caught earlier\n", name);
- return NULL;
+ for (i = 0; i < numbdevs; i++)
+ if (strncmp(bdevs[i].name, name, cmplen) == 0)
+ break;
+
+ if (i == numbdevs)
+ return NULL;
+
+ DEBUG("Detected rootfs type \"%s\"", bdevs[i].name);
+ return &bdevs[i];
}
static const struct bdev_type *bdev_query(struct lxc_conf *conf,
const char *src)
{
size_t i;
+ const struct bdev_type *bdev;
- if (conf->rootfs.bdev_type) {
- DEBUG("config file specified rootfs type \"%s\"",
- conf->rootfs.bdev_type);
- return get_bdev_by_name(conf->rootfs.bdev_type);
- }
+ bdev = get_bdev_by_name(src);
+ if (bdev)
+ return bdev;
- for (i = 0; i < numbdevs; i++) {
- int r;
- r = bdevs[i].ops->detect(src);
- if (r)
+ for (i = 0; i < numbdevs; i++)
+ if (bdevs[i].ops->detect(src))
break;
- }
if (i == numbdevs)
return NULL;
- DEBUG("detected rootfs type \"%s\"", bdevs[i].name);
-
+ DEBUG("Detected rootfs type \"%s\"", bdevs[i].name);
return &bdevs[i];
}
int aufs_detect(const char *path)
{
- if (strncmp(path, "aufs:", 5) == 0)
- return 1; // take their word for it
+ if (!strncmp(path, "aufs:", 5))
+ return 1;
+
return 0;
}
struct stat st;
int ret;
+ if (!strncmp(path, "btrfs:", 6))
+ return 1;
+
if (!is_btrfs_fs(path))
return 0;
- // and make sure it's a subvolume.
+ /* make sure it's a subvolume */
ret = stat(path, &st);
if (ret < 0)
return 0;
int dir_detect(const char *path)
{
- if (strncmp(path, "dir:", 4) == 0)
- return 1; // take their word for it
+ if (!strncmp(path, "dir:", 4))
+ return 1;
+
if (is_dir(path))
return 1;
return 0;
int ret;
struct stat s;
- if (strncmp(path, "loop:", 5) == 0)
+ if (!strncmp(path, "loop:", 5))
return 1;
ret = stat(path, &s);
int ret;
struct stat statbuf;
- if (strncmp(path, "lvm:", 4) == 0)
- return 1; // take their word for it
+ if (!strncmp(path, "lvm:", 4))
+ return 1;
ret = stat(path, &statbuf);
if (ret != 0)
int nbd_detect(const char *path)
{
- if (strncmp(path, "nbd:", 4) == 0)
+ if (!strncmp(path, "nbd:", 4))
return 1;
+
return 0;
}
int ovl_detect(const char *path)
{
- if (strncmp(path, "overlayfs:", 10) == 0)
- return 1; // take their word for it
+ if (!strncmp(path, "overlayfs:", 10))
+ return 1;
+
+ if (!strncmp(path, "overlay:", 8))
+ return 1;
+
return 0;
}
int rbd_detect(const char *path)
{
- if ( memcmp(path, "/dev/rbd/", 9) == 0)
+ if (!strncmp(path, "rbd:", 4))
return 1;
+
+ if (!strncmp(path, "/dev/rbd/", 9))
+ return 1;
+
return 0;
}
int zfs_detect(const char *path)
{
+ if (!strncmp(path, "zfs:", 4))
+ return 1;
+
char *output = malloc(LXC_LOG_BUFFER_SIZE);
if (!output) {
{ "lxc.mount", set_config_fstab, get_config_fstab, clr_config_fstab, },
{ "lxc.rootfs.mount", set_config_rootfs_mount, get_config_rootfs_mount, clr_config_rootfs_mount, },
{ "lxc.rootfs.options", set_config_rootfs_options, get_config_rootfs_options, clr_config_rootfs_options, },
+
+ /* REMOVE IN LXC 3.0
+ legacy rootfs.backend key
+ */
{ "lxc.rootfs.backend", set_config_rootfs_backend, get_config_rootfs_backend, clr_config_rootfs_backend, },
+
{ "lxc.rootfs", set_config_rootfs, get_config_rootfs, clr_config_rootfs, },
/* REMOVE IN LXC 3.0
static int set_config_rootfs_backend(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
- if (lxc_config_value_empty(value)) {
- free(lxc_conf->rootfs.bdev_type);
- lxc_conf->rootfs.bdev_type = NULL;
- return 0;
- }
-
- if (!is_valid_bdev_type(value)) {
- ERROR("Bad rootfs.backend: '%s'", value);
- return -1;
- }
-
- return set_config_string_item(&lxc_conf->rootfs.bdev_type, value);
+ return 0;
}
static int set_config_uts_name(const char *key, const char *value,
static int get_config_rootfs_backend(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
- return lxc_get_conf_str(retv, inlen, c->rootfs.bdev_type);
+ return 0;
}
static int get_config_uts_name(const char *key, char *retv, int inlen,
static inline int clr_config_rootfs_backend(const char *key, struct lxc_conf *c,
void *data)
{
- free(c->rootfs.bdev_type);
- c->rootfs.bdev_type = NULL;
return 0;
}
* it returns a mounted bdev on success, NULL on error.
*/
static struct bdev *do_bdev_create(struct lxc_container *c, const char *type,
- struct bdev_specs *specs)
+ struct bdev_specs *specs)
{
char *dest;
size_t len;
int ret;
/* rootfs.path or lxcpath/lxcname/rootfs */
- if (c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) == 0) {
+ if (c->lxc_conf->rootfs.path && !access(c->lxc_conf->rootfs.path, F_OK)) {
const char *rpath = c->lxc_conf->rootfs.path;
len = strlen(rpath) + 1;
dest = alloca(len);
return NULL;
}
- do_lxcapi_set_config_item(c, "lxc.rootfs", bdev->src);
- do_lxcapi_set_config_item(c, "lxc.rootfs.backend", bdev->type);
-
- /* if we are not root, chown the rootfs dir to root in the
- * target uidmap */
+ if (!c->set_config_item(c, "lxc.rootfs", bdev->src)) {
+ ERROR("Failed to set config item \"lxc.rootfs\" to \"%s\"",
+ bdev->src);
+ return NULL;
+ }
+ /* If we are not root, chown the rootfs dir to root in the
+ * target uidmap.
+ */
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);
/* Set new rootfs. */
free(c->lxc_conf->rootfs.path);
c->lxc_conf->rootfs.path = strdup(bdev->src);
-
- /* Set new bdev type. */
- free(c->lxc_conf->rootfs.bdev_type);
- c->lxc_conf->rootfs.bdev_type = strdup(bdev->type);
bdev_put(bdev);
if (!c->lxc_conf->rootfs.path) {
ERROR("Out of memory while setting storage path.");
return -1;
}
- if (!c->lxc_conf->rootfs.bdev_type) {
- ERROR("Out of memory while setting rootfs backend.");
- return -1;
- }
/* Append a new lxc.rootfs entry to the unexpanded config. */
clear_unexp_config_line(c->lxc_conf, "lxc.rootfs", false);
/* Append a new lxc.rootfs.backend entry to the unexpanded config. */
clear_unexp_config_line(c->lxc_conf, "lxc.rootfs.backend", false);
- if (!do_append_unexp_config_line(c->lxc_conf, "lxc.rootfs.backend",
- c->lxc_conf->rootfs.bdev_type)) {
- ERROR("Error saving new rootfs backend to cloned config.");
- return -1;
- }
if (flags & LXC_CLONE_SNAPSHOT)
copy_rdepends(c, c0);