]> git.proxmox.com Git - mirror_lxc.git/commitdiff
overlay: rewrite and simplify
authorChristian Brauner <christian.brauner@ubuntu.com>
Sun, 22 Mar 2020 13:03:03 +0000 (14:03 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Sun, 22 Mar 2020 17:37:38 +0000 (18:37 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
24 files changed:
src/lxc/conf.c
src/lxc/conf.h
src/lxc/list.h
src/lxc/lxccontainer.c
src/lxc/storage/btrfs.c
src/lxc/storage/btrfs.h
src/lxc/storage/dir.c
src/lxc/storage/dir.h
src/lxc/storage/loop.c
src/lxc/storage/loop.h
src/lxc/storage/lvm.c
src/lxc/storage/lvm.h
src/lxc/storage/nbd.c
src/lxc/storage/nbd.h
src/lxc/storage/overlay.c
src/lxc/storage/overlay.h
src/lxc/storage/rbd.c
src/lxc/storage/rbd.h
src/lxc/storage/storage.c
src/lxc/storage/storage.h
src/lxc/storage/storage_utils.h
src/lxc/storage/zfs.c
src/lxc/storage/zfs.h
src/lxc/tools/lxc_copy.c

index 066a600d66929798ff99842aa36296d803616724..2de772511e50754663977eae3fab044afaaf2287 100644 (file)
@@ -2795,8 +2795,8 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
 /* Return the host uid/gid to which the container root is mapped in val.
  * Return true if id was found, false otherwise.
  */
-bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype,
-                      unsigned long *val)
+static bool get_mapped_rootid(const struct lxc_conf *conf, enum idtype idtype,
+                             unsigned long *val)
 {
        unsigned nsid;
        struct id_map *map;
@@ -2820,7 +2820,7 @@ bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype,
        return false;
 }
 
-int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype)
+int mapped_hostid(unsigned id, const struct lxc_conf *conf, enum idtype idtype)
 {
        struct id_map *map;
        struct lxc_list *it;
@@ -2871,7 +2871,7 @@ int chown_mapped_root_exec_wrapper(void *args)
  * root is privileged with respect to hostuid/hostgid X, allowing
  * him to do the chown.
  */
-int chown_mapped_root(const char *path, struct lxc_conf *conf)
+int chown_mapped_root(const char *path, const struct lxc_conf *conf)
 {
        uid_t rootuid, rootgid;
        unsigned long val;
index 5b6fb9a13561e2c79c08786f3009fa2be119a0fb..7f91c9fb97d8cb6bfe3f9a1e3051967cf2a56c65 100644 (file)
@@ -437,9 +437,9 @@ extern int lxc_setup(struct lxc_handler *handler);
 extern int lxc_setup_parent(struct lxc_handler *handler);
 extern int setup_resource_limits(struct lxc_list *limits, pid_t pid);
 extern int find_unmapped_nsid(struct lxc_conf *conf, enum idtype idtype);
-extern int mapped_hostid(unsigned id, struct lxc_conf *conf,
+extern int mapped_hostid(unsigned id, const struct lxc_conf *conf,
                         enum idtype idtype);
-extern int chown_mapped_root(const char *path, struct lxc_conf *conf);
+extern int chown_mapped_root(const char *path, const struct lxc_conf *conf);
 extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
                         const char *fn_name);
 extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *),
index 0356641b8b243688798820c292f5573eb70a55a1..e329b7e0000fb80c85b18ff74af69697d133b54c 100644 (file)
@@ -58,19 +58,19 @@ static inline void lxc_list_add_elem(struct lxc_list *list, void *elem)
 }
 
 /* Retrieve first element of list. */
-static inline void *lxc_list_first_elem(struct lxc_list *list)
+static inline void *lxc_list_first_elem(const struct lxc_list *list)
 {
        return list->next->elem;
 }
 
 /* Retrieve last element of list. */
-static inline void *lxc_list_last_elem(struct lxc_list *list)
+static inline void *lxc_list_last_elem(const struct lxc_list *list)
 {
        return list->prev->elem;
 }
 
 /* Determine if list is empty. */
-static inline int lxc_list_empty(struct lxc_list *list)
+static inline int lxc_list_empty(const struct lxc_list *list)
 {
        return list == list->next;
 }
index b30864bb545d48a0e4aefe5fa8cdd4c5f8de75a8..38439b80b5c59c1750df3249290c52c39e33e5a2 100644 (file)
@@ -1275,7 +1275,7 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c,
        if (ret < 0 || (size_t)ret >= len)
                return NULL;
 
-       bdev = storage_create(dest, type, c->name, specs);
+       bdev = storage_create(dest, type, c->name, specs, c->lxc_conf);
        if (!bdev) {
                ERROR("Failed to create \"%s\" storage", type);
                return NULL;
@@ -1290,8 +1290,7 @@ static struct lxc_storage *do_storage_create(struct lxc_container *c,
        /* If we are not root, chown the rootfs dir to root in the target user
         * namespace.
         */
-       ret = geteuid();
-       if (ret != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) {
+       if (am_guest_unpriv() || !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);
index be66aef77568977fdd888f31849d78fce3d10241..47f2dd3c4ef9e6db1c40ed9b28ed1da5ee823138 100644 (file)
@@ -906,7 +906,7 @@ int btrfs_destroy(struct lxc_storage *orig)
 }
 
 int btrfs_create(struct lxc_storage *bdev, const char *dest, const char *n,
-                struct bdev_specs *specs)
+                struct bdev_specs *specs, const struct lxc_conf *conf)
 {
        int ret;
        size_t len;
index edd7bb0ad2b2b0095db225a9ea0432f2745cae4c..c7f45eb4dc693b0f05f6aceec035888a79b31be3 100644 (file)
@@ -366,8 +366,8 @@ extern int btrfs_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
                            const char *oldname, const char *cname,
                            const char *oldpath, const char *lxcpath, int snap,
                            uint64_t newsize, struct lxc_conf *conf);
-extern int btrfs_create(struct lxc_storage *bdev, const char *dest,
-                       const char *n, struct bdev_specs *specs);
+extern int btrfs_create(struct lxc_storage *bdev, const char *dest, const char *n,
+                       struct bdev_specs *specs, const struct lxc_conf *conf);
 extern int btrfs_destroy(struct lxc_storage *orig);
 extern bool btrfs_detect(const char *path);
 extern int btrfs_mount(struct lxc_storage *bdev);
index 393fb501670e7a559ec40b773925db82b8bb017a..9b3e673b3e189ec3057099dc1cacfeaceb7067b6 100644 (file)
@@ -58,7 +58,7 @@ int dir_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
 }
 
 int dir_create(struct lxc_storage *bdev, const char *dest, const char *n,
-              struct bdev_specs *specs)
+              struct bdev_specs *specs, const struct lxc_conf *conf)
 {
        int ret;
        const char *src;
index c7661f5b0df594453192b3c658d5cae878ee6827..d24a71fb44e0d73f4812c7933271785a1863abd8 100644 (file)
@@ -17,7 +17,7 @@ extern int dir_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
                          const char *oldpath, const char *lxcpath, int snap,
                          uint64_t newsize, struct lxc_conf *conf);
 extern int dir_create(struct lxc_storage *bdev, const char *dest, const char *n,
-                     struct bdev_specs *specs);
+                     struct bdev_specs *specs, const struct lxc_conf *conf);
 extern int dir_destroy(struct lxc_storage *orig);
 extern bool dir_detect(const char *path);
 extern int dir_mount(struct lxc_storage *bdev);
index ad3701cd6016a53151274b2b10214fe4039e7e96..eebc1b67c4e58fe2225b85b5b5d62e74e6e28b40 100644 (file)
@@ -114,7 +114,7 @@ int loop_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
 }
 
 int loop_create(struct lxc_storage *bdev, const char *dest, const char *n,
-               struct bdev_specs *specs)
+               struct bdev_specs *specs, const struct lxc_conf *conf)
 {
        __do_free char *srcdev = NULL;
        const char *fstype;
index b22d34fd1aa5d954c63e75855cb1cab6117492ed..66681db8fe52441a7e2a9648cfd03566b40667fd 100644 (file)
@@ -17,7 +17,7 @@ extern int loop_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
                           const char *oldpath, const char *lxcpath, int snap,
                           uint64_t newsize, struct lxc_conf *conf);
 extern int loop_create(struct lxc_storage *bdev, const char *dest,
-                      const char *n, struct bdev_specs *specs);
+                      const char *n, struct bdev_specs *specs, const struct lxc_conf *conf);
 extern int loop_destroy(struct lxc_storage *orig);
 extern bool loop_detect(const char *path);
 extern int loop_mount(struct lxc_storage *bdev);
index 30e3e697a9bcdf0adb6886f9542225a1efb50cc0..437677cf43ae5d8ae168800043f16884f27d01fb 100644 (file)
@@ -609,7 +609,7 @@ int lvm_destroy(struct lxc_storage *orig)
 }
 
 int lvm_create(struct lxc_storage *bdev, const char *dest, const char *n,
-              struct bdev_specs *specs)
+              struct bdev_specs *specs, const struct lxc_conf *conf)
 {
        const char *vg, *thinpool, *fstype, *lv = n;
        uint64_t sz;
index e4ef0611e0f80f5ca6b7c1bbc77f135e45126e85..7c2fbea6582d4d5eb9825616493ecbd77c3d0560 100644 (file)
@@ -24,7 +24,7 @@ extern int lvm_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
                          uint64_t newsize, struct lxc_conf *conf);
 extern int lvm_destroy(struct lxc_storage *orig);
 extern int lvm_create(struct lxc_storage *bdev, const char *dest, const char *n,
-                     struct bdev_specs *specs);
+                     struct bdev_specs *specs, const struct lxc_conf *conf);
 extern bool lvm_create_clone(struct lxc_conf *conf, struct lxc_storage *orig,
                             struct lxc_storage *new, uint64_t newsize);
 extern bool lvm_create_snapshot(struct lxc_conf *conf, struct lxc_storage *orig,
index 4a4395bf0492171c915948c3ef083866d280c772..ba4207380e9b53a22f8506f08a0d80ec228307bb 100644 (file)
@@ -91,7 +91,7 @@ int nbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
 }
 
 int nbd_create(struct lxc_storage *bdev, const char *dest, const char *n,
-              struct bdev_specs *specs)
+              struct bdev_specs *specs, const struct lxc_conf *conf)
 {
        return -ENOSYS;
 }
index 86f59461f11d8d58cf75d5dd32199dd9e63d2175..b01c486dfc25325f73a01fc9d3c1572cef7ed8f0 100644 (file)
@@ -17,7 +17,7 @@ extern int nbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
                          const char *oldpath, const char *lxcpath, int snap,
                          uint64_t newsize, struct lxc_conf *conf);
 extern int nbd_create(struct lxc_storage *bdev, const char *dest, const char *n,
-                     struct bdev_specs *specs);
+                     struct bdev_specs *specs, const struct lxc_conf *conf);
 extern int nbd_destroy(struct lxc_storage *orig);
 extern bool nbd_detect(const char *path);
 extern int nbd_mount(struct lxc_storage *bdev);
index 2195b76e41dddee65e2cba9502d86fca5c28434b..a18b947fa18a224129c6f9e887e7c34b67c5cab2 100644 (file)
@@ -57,234 +57,133 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
                return -1;
        }
 
-       if (am_guest_unpriv()) {
+       if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
                ret = chown_mapped_root(new->dest, conf);
                if (ret < 0)
                        WARN("Failed to update ownership of %s", new->dest);
        }
 
        if (strcmp(orig->type, "dir") == 0) {
-               char *delta, *lastslash;
-               char *work;
-               int len, lastslashidx;
+               __do_free char *delta = NULL, *work = NULL;
+               int len;
 
-               /* If we have "/var/lib/lxc/c2/rootfs" then delta will be
-                * "/var/lib/lxc/c2/delta0".
-                */
-               lastslash = strrchr(new->dest, '/');
-               if (!lastslash) {
-                       ERROR("Failed to detect \"/\" in string \"%s\"",
-                             new->dest);
-                       return -22;
-               }
-
-               if (strlen(lastslash) < STRLITERALLEN("/rootfs")) {
-                       ERROR("Failed to detect \"/rootfs\" in string \"%s\"",
-                             new->dest);
-                       return -22;
-               }
-
-               lastslash++;
-               lastslashidx = lastslash - new->dest;
-
-               delta = malloc(lastslashidx + 7);
-               if (!delta) {
-                       ERROR("Failed to allocate memory");
-                       return -1;
-               }
-
-               memcpy(delta, new->dest, lastslashidx + 1);
-               memcpy(delta + lastslashidx, "delta0", STRLITERALLEN("delta0"));
-               delta[lastslashidx + STRLITERALLEN("delta0")] = '\0';
-
-               ret = mkdir(delta, 0755);
-               if (ret < 0 && errno != EEXIST) {
-                       SYSERROR("Failed to create directory \"%s\"", delta);
-                       free(delta);
-                       return -1;
-               }
+               delta = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL);
 
-               if (am_guest_unpriv()) {
-                       ret = chown_mapped_root(delta, conf);
-                       if (ret < 0)
-                               WARN("Failed to update ownership of %s", delta);
-               }
+               ret = mkdir_p(delta, 0755);
+               if (ret < 0 && errno != EEXIST)
+                       return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", delta);
 
-               /* Make workdir for overlayfs.v22 or higher:
+               /*
+                * Make workdir for overlayfs.v22 or higher:
                 * The workdir will be
-                *      /var/lib/lxc/c2/olwork
+                *      /var/lib/lxc/c2/LXC_OVERLAY_WORK_PATH
                 * and is used to prepare files before they are atomically
                 * switched to the overlay destination. Workdirs need to be on
                 * the same filesystem as the upperdir so it's OK for it to be
                 * empty.
                 */
-               work = malloc(lastslashidx + 7);
-               if (!work) {
-                       ERROR("Failed to allocate memory");
-                       free(delta);
-                       return -1;
-               }
+               work = must_make_path(lxcpath, cname, LXC_OVERLAY_WORK_PATH, NULL);
 
-               memcpy(work, new->dest, lastslashidx + 1);
-               memcpy(work + lastslashidx, "olwork", STRLITERALLEN("olwork"));
-               work[lastslashidx + STRLITERALLEN("olwork")] = '\0';
+               ret = mkdir_p(work, 0755);
+               if (ret < 0 && errno != EEXIST)
+                       return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", work);
 
-               ret = mkdir(work, 0755);
-               if (ret < 0) {
-                       SYSERROR("Failed to create directory \"%s\"", work);
-                       free(delta);
-                       free(work);
-                       return -1;
-               }
+               if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
+                       __do_free char *lxc_overlay_delta_dir = NULL,
+                                      *lxc_overlay_private_dir = NULL;
+
+                       lxc_overlay_private_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_PRIVATE_DIR, NULL);
+                       ret = chown_mapped_root(lxc_overlay_private_dir, conf);
+                       if (ret < 0)
+                               WARN("Failed to update ownership of %s", lxc_overlay_private_dir);
+
+                       lxc_overlay_delta_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL);
+                       ret = chown_mapped_root(lxc_overlay_delta_dir, conf);
+                       if (ret < 0)
+                               WARN("Failed to update ownership of %s", lxc_overlay_delta_dir);
 
-               if (am_guest_unpriv()) {
                        ret = chown_mapped_root(work, conf);
                        if (ret < 0)
                                WARN("Failed to update ownership of %s", work);
                }
-               free(work);
 
-               /* strlen("overlay:") = 8
-                * +
-                * strlen(delta)
-                * +
-                * :
-                * +
-                * strlen(src)
-                * +
-                * \0
-                */
                src = lxc_storage_get_path(orig->src, orig->type);
-               len = 8 + strlen(delta) + 1 + strlen(src) + 1;
+               len = STRLITERALLEN("overlay") + STRLITERALLEN(":") +
+                     strlen(src) + STRLITERALLEN(":") + strlen(delta) + 1;
+
                new->src = malloc(len);
-               if (!new->src) {
-                       ERROR("Failed to allocate memory");
-                       free(delta);
-                       return -ENOMEM;
-               }
+               if (!new->src)
+                       return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory");
 
                ret = snprintf(new->src, len, "overlay:%s:%s", src, delta);
-               free(delta);
-               if (ret < 0 || (size_t)ret >= len) {
-                       ERROR("Failed to create string");
-                       return -1;
-               }
+               if (ret < 0 || (size_t)ret >= len)
+                       return log_error_errno(-EIO, EIO, "Failed to create string");
        } else if (!strcmp(orig->type, "overlayfs") ||
                   !strcmp(orig->type, "overlay")) {
-               char *clean_old_path, *clean_new_path;
-               char *lastslash, *ndelta, *nsrc, *odelta, *osrc, *s1, *s2, *s3,
-                   *work;
-               int lastslashidx;
+               __do_free char *clean_old_path = NULL, *clean_new_path = NULL,
+                              *ndelta = NULL, *osrc = NULL, *work = NULL;
+               char *nsrc, *odelta, *s1, *s2, *s3;
                size_t len, name_len;
 
                osrc = strdup(orig->src);
-               if (!osrc) {
-                       ERROR("Failed to duplicate string \"%s\"", orig->src);
-                       return -22;
-               }
+               if (!osrc)
+                       return log_error_errno(-22, ENOMEM, "Failed to duplicate string \"%s\"", orig->src);
 
                nsrc = osrc;
-               if (strncmp(osrc, "overlay:", 8) == 0)
-                       nsrc += 8;
-               else if (strncmp(osrc, "overlayfs:", 10) == 0)
-                       nsrc += 10;
+               if (strncmp(osrc, "overlay:", STRLITERALLEN("overlay:")) == 0)
+                       nsrc += STRLITERALLEN("overlay:");
+               else if (strncmp(osrc, "overlayfs:", STRLITERALLEN("overlayfs:")) == 0)
+                       nsrc += STRLITERALLEN("overlayfs:");
 
                odelta = strchr(nsrc, ':');
-               if (!odelta) {
-                       ERROR("Failed to find \":\" in \"%s\"", nsrc);
-                       free(osrc);
-                       return -22;
-               }
+               if (!odelta)
+                       return log_error_errno(-22, ENOENT, "Failed to find \":\" in \"%s\"", nsrc);
 
                *odelta = '\0';
                odelta++;
-               ndelta = must_make_path(lxcpath, cname, "delta0", NULL);
-
-               ret = mkdir(ndelta, 0755);
-               if (ret < 0 && errno != EEXIST) {
-                       SYSERROR("Failed to create directory \"%s\"", ndelta);
-                       free(osrc);
-                       free(ndelta);
-                       return -1;
-               }
+               ndelta = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL);
 
-               if (am_guest_unpriv()) {
-                       ret = chown_mapped_root(ndelta, conf);
-                       if (ret < 0)
-                               WARN("Failed to update ownership of %s",
-                                    ndelta);
-               }
+               ret = mkdir_p(ndelta, 0755);
+               if (ret < 0 && errno != EEXIST)
+                       return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", ndelta);
 
                /* Make workdir for overlayfs.v22 or higher (See the comment
                 * further up.).
                 */
-               lastslash = strrchr(ndelta, '/');
-               if (!lastslash) {
-                       ERROR("Failed to detect \"/\" in \"%s\"", ndelta);
-                       free(osrc);
-                       free(ndelta);
-                       return -1;
-               }
-               lastslash++;
-               lastslashidx = lastslash - ndelta;
-
-               work = malloc(lastslashidx + 7);
-               if (!work) {
-                       free(osrc);
-                       free(ndelta);
-                       ERROR("Failed to allocate memory");
-                       return -1;
-               }
+               work = must_make_path(lxcpath, cname, LXC_OVERLAY_WORK_PATH, NULL);
+               ret = mkdir_p(work, 0755);
+               if (ret < 0 && errno != EEXIST)
+                       return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", ndelta);
 
-               memcpy(work, ndelta, lastslashidx + 1);
-               memcpy(work + lastslashidx, "olwork", STRLITERALLEN("olwork"));
-               work[lastslashidx + STRLITERALLEN("olwork")] = '\0';
+               if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
+                       __do_free char *lxc_overlay_delta_dir = NULL,
+                                      *lxc_overlay_private_dir = NULL;
 
-               ret = mkdir(work, 0755);
-               if (ret < 0 && errno != EEXIST) {
-                       SYSERROR("Failed to create directory \"%s\"", ndelta);
-                       free(osrc);
-                       free(ndelta);
-                       free(work);
-                       return -1;
-               }
+                       lxc_overlay_private_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_PRIVATE_DIR, NULL);
+                       ret = chown_mapped_root(lxc_overlay_private_dir, conf);
+                       if (ret < 0)
+                               WARN("Failed to update ownership of %s", lxc_overlay_private_dir);
+
+                       lxc_overlay_delta_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL);
+                       ret = chown_mapped_root(lxc_overlay_delta_dir, conf);
+                       if (ret < 0)
+                               WARN("Failed to update ownership of %s", lxc_overlay_delta_dir);
 
-               if (am_guest_unpriv()) {
                        ret = chown_mapped_root(work, conf);
                        if (ret < 0)
                                WARN("Failed to update ownership of %s", work);
                }
-               free(work);
 
-               /* strlen("overlay:") = 8
-                * +
-                * strlen(delta)
-                * +
-                * :
-                * +
-                * strlen(src)
-                * +
-                * \0
-                */
-               len = 8 + strlen(ndelta) + 1 + strlen(nsrc) + 1;
+               len = STRLITERALLEN("overlay") + STRLITERALLEN(":") + strlen(nsrc) + STRLITERALLEN(":") + strlen(ndelta) + 1;
                new->src = malloc(len);
-               if (!new->src) {
-                       free(osrc);
-                       free(ndelta);
-                       ERROR("Failed to allocate memory");
-                       return -ENOMEM;
-               }
+               if (!new->src)
+                       return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory");
+
                ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta);
-               if (ret < 0 || (size_t)ret >= len) {
-                       ERROR("Failed to create string");
-                       free(osrc);
-                       free(ndelta);
-                       return -1;
-               }
+               if (ret < 0 || (size_t)ret >= len)
+                       return log_error_errno(-EIO, EIO, "Failed to create string");
 
                ret = ovl_do_rsync(odelta, ndelta, conf);
-               free(osrc);
-               free(ndelta);
                if (ret < 0)
                        return -1;
 
@@ -295,29 +194,19 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
                 */
                clean_old_path = lxc_deslashify(oldpath);
                if (!clean_old_path)
-                       return -1;
+                       return log_error_errno(-ENOMEM, ENOMEM, "Failed to create clean path for \"%s\"", oldpath);
 
                clean_new_path = lxc_deslashify(lxcpath);
-               if (!clean_new_path) {
-                       free(clean_old_path);
-                       return -1;
-               }
+               if (!clean_new_path)
+                       return log_error_errno(-ENOMEM, ENOMEM, "Failed to create clean path for \"%s\"", lxcpath);
 
                s1 = strrchr(clean_old_path, '/');
-               if (!s1) {
-                       ERROR("Failed to detect \"/\" in string \"%s\"", clean_old_path);
-                       free(clean_old_path);
-                       free(clean_new_path);
-                       return -1;
-               }
+               if (!s1)
+                       return log_error_errno(-ENOENT, ENOENT, "Failed to detect \"/\" in string \"%s\"", clean_old_path);
 
                s2 = strrchr(clean_new_path, '/');
-               if (!s2) {
-                       ERROR("Failed to detect \"/\" in string \"%s\"", clean_new_path);
-                       free(clean_old_path);
-                       free(clean_new_path);
-                       return -1;
-               }
+               if (!s2)
+                       return log_error_errno(-ENOENT, ENOENT, "Failed to detect \"/\" in string \"%s\"", clean_new_path);
 
                if (!strncmp(s1, "/snaps", STRLITERALLEN("/snaps"))) {
                        s1 = clean_new_path;
@@ -328,8 +217,6 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
                        s2 = clean_new_path;
                        s3 = (char *)oldname;
                } else {
-                       free(clean_old_path);
-                       free(clean_new_path);
                        return 0;
                }
 
@@ -338,34 +225,23 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
                        char *tmp;
 
                        tmp = (char *)(s2 + len + 1);
-                       if (*tmp == '\0') {
-                               free(clean_old_path);
-                               free(clean_new_path);
+                       if (*tmp == '\0')
                                return 0;
-                       }
 
                        name_len = strlen(s3);
-                       if (strncmp(s3, tmp, name_len)) {
-                               free(clean_old_path);
-                               free(clean_new_path);
+                       if (strncmp(s3, tmp, name_len))
                                return 0;
-                       }
 
-                       free(clean_old_path);
-                       free(clean_new_path);
                        return LXC_CLONE_SNAPSHOT;
                }
 
-               free(clean_old_path);
-               free(clean_new_path);
                return 0;
        } else {
-               ERROR("overlay clone of %s container is not yet supported",
-                     orig->type);
-               /* Note, supporting this will require ovl_mount supporting
+               /*
+                * Note, supporting this will require ovl_mount supporting
                 * mounting of the underlay. No big deal, just needs to be done.
                 */
-               return -1;
+               return log_error_errno(-EINVAL, EINVAL, "overlay clone of %s container is not yet supported", orig->type);
        }
 
        return 0;
@@ -373,65 +249,60 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
 
 /* To say "lxc-create -t ubuntu -n o1 -B overlay" means you want
  * "<lxcpath>/<lxcname>/rootfs" to have the created container, while all changes
- * after starting the container are written to "<lxcpath>/<lxcname>/delta0".
+ * after starting the container are written to "<lxcpath>/<lxcname>/LXC_OVERLAY_DELTA_PATH".
  */
 int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n,
-              struct bdev_specs *specs)
+              struct bdev_specs *specs, const struct lxc_conf *conf)
 {
-       char *delta;
+       __do_free char *delta = NULL, *tmp = NULL;
        int ret;
-       size_t len, newlen;
+       size_t len;
 
        len = strlen(dest);
-       if (len < 8 || strcmp(dest + len - 7, "/rootfs")) {
-               ERROR("Failed to detect \"/rootfs\" in \"%s\"", dest);
-               return -1;
-       }
+       if (len < 8 || strcmp(dest + len - STRLITERALLEN("/rootfs"), "/rootfs"))
+               return log_error_errno(-ENOENT, ENOENT, "Failed to detect \"/rootfs\" in \"%s\"", dest);
 
        bdev->dest = strdup(dest);
-       if (!bdev->dest) {
-               ERROR("Failed to duplicate string \"%s\"", dest);
-               return -1;
-       }
+       if (!bdev->dest)
+               return log_error_errno(-ENOMEM, ENOMEM, "Failed to duplicate string \"%s\"", dest);
 
-       delta = strdup(dest);
-       if (!delta) {
-               ERROR("Failed to allocate memory");
-               return -1;
-       }
-       memcpy(delta + len - 6, "delta0", STRLITERALLEN("delta0"));
+       tmp = strndup(dest, len - STRLITERALLEN("/rootfs"));
+       if (!tmp)
+               return log_error_errno(-ENOMEM, ENOMEM, "Failed to duplicate string \"%s\"", dest);
+
+       delta = must_make_path(tmp, LXC_OVERLAY_DELTA_PATH, NULL);
 
        ret = mkdir_p(delta, 0755);
-       if (ret < 0) {
-               SYSERROR("Failed to create directory \"%s\"", delta);
-               free(delta);
-               return -1;
+       if (ret < 0 && errno != EEXIST)
+               return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", delta);
+
+       if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
+               __do_free char *lxc_overlay_private_dir = NULL;
+
+               lxc_overlay_private_dir = must_make_path(tmp, LXC_OVERLAY_PRIVATE_DIR, NULL);
+               ret = chown_mapped_root(lxc_overlay_private_dir, conf);
+               if (ret < 0)
+                       WARN("Failed to update ownership of %s", lxc_overlay_private_dir);
+
+               ret = chown_mapped_root(delta, conf);
+               if (ret < 0)
+                       WARN("Failed to update ownership of %s", delta);
        }
 
        /* overlay:lower:upper */
-       newlen = (2 * len) + strlen("overlay:") + 2;
-       bdev->src = malloc(newlen);
-       if (!bdev->src) {
-               ERROR("Failed to allocate memory");
-               free(delta);
-               return -1;
-       }
+       len = STRLITERALLEN("overlay") + STRLITERALLEN(":") + len + STRLITERALLEN(":") + strlen(delta) + 1;
+       bdev->src = malloc(len);
+       if (!bdev->src)
+               return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory");
 
-       ret = snprintf(bdev->src, newlen, "overlay:%s:%s", dest, delta);
-       if (ret < 0 || (size_t)ret >= newlen) {
-               ERROR("Failed to create string");
-               free(delta);
-               return -1;
-       }
+       ret = snprintf(bdev->src, len, "overlay:%s:%s", dest, delta);
+       if (ret < 0 || (size_t)ret >= len)
+               return log_error_errno(-EIO, EIO, "Failed to create rootfs path");
 
        ret = mkdir_p(bdev->dest, 0755);
-       if (ret < 0) {
-               SYSERROR("Failed to create directory \"%s\"", bdev->dest);
-               free(delta);
-               return -1;
-       }
+       if (ret < 0 && errno != EEXIST)
+               return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", bdev->dest);
 
-       free(delta);
        return 0;
 }
 
@@ -475,7 +346,6 @@ int ovl_mount(struct lxc_storage *bdev)
                                                         *options_work = NULL;
        char *tmp, *dup, *lower, *upper;
        char *work, *lastslash;
-       int lastslashidx;
        size_t len, len2;
        unsigned long mntflags;
        char *mntdata;
@@ -494,17 +364,15 @@ int ovl_mount(struct lxc_storage *bdev)
         * mount -t overlay * -o upperdir=${upper},lowerdir=${lower} lower dest
         */
        dup = strdup(bdev->src);
-       if (!dup) {
-               ERROR("Failed to allocate memory");
-               return -1;
-       }
+       if (!dup)
+               return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory");
        upper = dup;
        lower = dup;
 
-       if (strncmp(dup, "overlay:", 8) == 0)
-               lower += 8;
-       else if (strncmp(dup, "overlayfs:", 10) == 0)
-               lower += 10;
+       if (strncmp(dup, "overlay:", STRLITERALLEN("overlay:")) == 0)
+               lower += STRLITERALLEN("overlay:");
+       else if (strncmp(dup, "overlayfs:", STRLITERALLEN("overlayfs:")) == 0)
+               lower += STRLITERALLEN("overlayfs:");
        if (upper != lower)
                upper = lower;
 
@@ -532,9 +400,9 @@ int ovl_mount(struct lxc_storage *bdev)
 
        /* overlayfs.v22 or higher needs workdir option:
         * if upper is
-        *      /var/lib/lxc/c2/delta0
+        *      /var/lib/lxc/c2/LXC_OVERLAY_DELTA_PATH
         * then workdir is
-        *      /var/lib/lxc/c2/olwork
+        *      /var/lib/lxc/c2/LXC_OVERLAY_WORK_PATH
         */
        lastslash = strrchr(upper, '/');
        if (!lastslash) {
@@ -543,19 +411,9 @@ int ovl_mount(struct lxc_storage *bdev)
                return -22;
        }
 
-       lastslash++;
-       lastslashidx = lastslash - upper;
-
-       work = malloc(lastslashidx + 7);
-       if (!work) {
-               ERROR("Failed to allocate memory");
-               free(dup);
-               return -22;
-       }
-
-       memcpy(work, upper, lastslashidx + 1);
-       memcpy(work + lastslashidx, "olwork", STRLITERALLEN("olwork"));
-       work[lastslashidx + STRLITERALLEN("olwork")] = '\0';
+       upper[lastslash - upper] = '\0';
+       work = must_make_path(upper, LXC_OVERLAY_WORK_DIR, NULL);
+       upper[lastslash - upper] = '/';
 
        ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata);
        if (ret < 0) {
index b8349b63d25dae574a669d0787421d4785c84481..b64406b0c805e23af4aa8f79bd49fe92bf9cc960 100644 (file)
@@ -25,7 +25,7 @@ extern int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
                          const char *oldpath, const char *lxcpath, int snap,
                          uint64_t newsize, struct lxc_conf *conf);
 extern int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n,
-                     struct bdev_specs *specs);
+                     struct bdev_specs *specs, const struct lxc_conf *conf);
 extern int ovl_destroy(struct lxc_storage *orig);
 extern bool ovl_detect(const char *path);
 extern int ovl_mount(struct lxc_storage *bdev);
index 6402dc775c200c68c21f49f7637a40936f4a9b6b..e7ba8930c942a521397b5fbacafe4752f0db92a4 100644 (file)
@@ -77,7 +77,7 @@ int rbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
 }
 
 int rbd_create(struct lxc_storage *bdev, const char *dest, const char *n,
-              struct bdev_specs *specs)
+              struct bdev_specs *specs, const struct lxc_conf *conf)
 {
        const char *rbdpool, *fstype;
        uint64_t size;
index 1537bf269efa3a52a9e7a28030a57b598c169ed8..f051c2ad0a75fd4fa658138b61acc480a05b95c1 100644 (file)
@@ -17,7 +17,7 @@ extern int rbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
                          const char *oldpath, const char *lxcpath, int snap,
                          uint64_t newsize, struct lxc_conf *conf);
 extern int rbd_create(struct lxc_storage *bdev, const char *dest, const char *n,
-                     struct bdev_specs *specs);
+                     struct bdev_specs *specs, const struct lxc_conf *conf);
 extern int rbd_destroy(struct lxc_storage *orig);
 extern bool rbd_detect(const char *path);
 extern int rbd_mount(struct lxc_storage *bdev);
index c05d1294a88cf1e8963921249ba45fba892f8c0a..3f1b713f6aaa571b75890ad205c1c95da58fefe8 100644 (file)
@@ -259,7 +259,8 @@ struct lxc_storage *storage_get(const char *type)
 
 static struct lxc_storage *do_storage_create(const char *dest, const char *type,
                                             const char *cname,
-                                            struct bdev_specs *specs)
+                                            struct bdev_specs *specs,
+                                            const struct lxc_conf *conf)
 {
        int ret;
        struct lxc_storage *bdev;
@@ -271,7 +272,7 @@ static struct lxc_storage *do_storage_create(const char *dest, const char *type,
        if (!bdev)
                return NULL;
 
-       ret = bdev->ops->create(bdev, dest, cname, specs);
+       ret = bdev->ops->create(bdev, dest, cname, specs, conf);
        if (ret < 0) {
                storage_put(bdev);
                return NULL;
@@ -521,14 +522,15 @@ on_error_put_orig:
  * @specs: details about the backing store to create, like fstype
  */
 struct lxc_storage *storage_create(const char *dest, const char *type,
-                                  const char *cname, struct bdev_specs *specs)
+                                  const char *cname, struct bdev_specs *specs,
+                                  const struct lxc_conf *conf)
 {
        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);
+               return do_storage_create(dest, "dir", cname, specs, conf);
 
        ret = strcmp(type, "best");
        if (ret == 0) {
@@ -537,7 +539,7 @@ struct lxc_storage *storage_create(const char *dest, const char *type,
                 * 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, conf);
                        if (bdev)
                                return bdev;
                }
@@ -552,13 +554,13 @@ struct lxc_storage *storage_create(const char *dest, const char *type,
 
                dup = must_copy_string(type);
                lxc_iterate_parts(token, dup, ",") {
-                       bdev = do_storage_create(dest, token, cname, specs);
+                       bdev = do_storage_create(dest, token, cname, specs, conf);
                        if (bdev)
                                return bdev;
                }
        }
 
-       return do_storage_create(dest, type, cname, specs);
+       return do_storage_create(dest, type, cname, specs, conf);
 }
 
 bool storage_destroy(struct lxc_conf *conf)
index acf35e4e91074f0b3f5bcc9f5fe9c1bbdf078606..59ec5a9892eea1c2a0bd642f8e480ed1fdccc70c 100644 (file)
@@ -54,7 +54,7 @@ struct lxc_storage_ops {
        int (*umount)(struct lxc_storage *bdev);
        int (*destroy)(struct lxc_storage *bdev);
        int (*create)(struct lxc_storage *bdev, const char *dest, const char *n,
-                     struct bdev_specs *specs);
+                     struct bdev_specs *specs, const struct lxc_conf *conf);
        /* given original mount, rename the paths for cloned container */
        int (*clone_paths)(struct lxc_storage *orig, struct lxc_storage *new,
                           const char *oldname, const char *cname,
@@ -111,7 +111,8 @@ extern struct lxc_storage *storage_copy(struct lxc_container *c,
                                        bool *needs_rdep);
 extern struct lxc_storage *storage_create(const char *dest, const char *type,
                                          const char *cname,
-                                         struct bdev_specs *specs);
+                                         struct bdev_specs *specs,
+                                         const struct lxc_conf *conf);
 extern void storage_put(struct lxc_storage *bdev);
 extern bool storage_destroy(struct lxc_conf *conf);
 extern bool rootfs_is_blockdev(struct lxc_conf *conf);
index 356ff95d8206614dff6fcd04e04b7cbf25043c6a..81c1e2bfec1a47a4892252aa70f718c70e58452b 100644 (file)
@@ -5,9 +5,19 @@
 
 #include <stdbool.h>
 #include <stdint.h>
+#include <string.h>
 #include <stdio.h>
 
 #include "conf.h"
+#include "macro.h"
+
+#define LXC_OVERLAY_PRIVATE_DIR "overlay"
+#define LXC_OVERLAY_DELTA_DIR "delta"
+#define LXC_OVERLAY_WORK_DIR "work"
+#define LXC_OVERLAY_DELTA_PATH LXC_OVERLAY_PRIVATE_DIR "/" LXC_OVERLAY_DELTA_DIR
+#define LXC_OVERLAY_WORK_PATH LXC_OVERLAY_PRIVATE_DIR "/" LXC_OVERLAY_WORK_DIR
+#define LXC_OVERLAY_PATH_LEN \
+       (STRLITERALLEN(LXC_OVERLAY_PRIVATE_DIR) + STRLITERALLEN("/") + 256 + 1)
 
 struct lxc_storage;
 struct lxc_conf;
index 7438dd3fb2ea1b1d866924b382ea2fa6349d456e..d745f2e3924945f4ccbf9edc8736fc42bcd444a7 100644 (file)
@@ -684,7 +684,7 @@ int zfs_destroy(struct lxc_storage *orig)
 }
 
 int zfs_create(struct lxc_storage *bdev, const char *dest, const char *n,
-              struct bdev_specs *specs)
+              struct bdev_specs *specs, const struct lxc_conf *conf)
 {
        const char *zfsroot;
        int ret;
index 855898c37913c2fe867ed3dc6902214c3a524331..bacbcb242b5400ac2d413900a8c85d91df7adc43 100644 (file)
@@ -18,7 +18,7 @@ extern int zfs_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
                          const char *oldpath, const char *lxcpath, int snap,
                          uint64_t newsize, struct lxc_conf *conf);
 extern int zfs_create(struct lxc_storage *bdev, const char *dest, const char *n,
-                     struct bdev_specs *specs);
+                     struct bdev_specs *specs, const struct lxc_conf *conf);
 extern int zfs_destroy(struct lxc_storage *orig);
 extern bool zfs_detect(const char *path);
 extern int zfs_mount(struct lxc_storage *bdev);
index 8d06a8a935fe7a077b763e2c5e933c75de933662..2180321b89a659b89ce45e493d5d59ae3f8fbf7e 100644 (file)
@@ -772,9 +772,11 @@ static char *mount_tmpfs(const char *oldname, const char *newname,
                goto err_close;
 
        if (!arg->keepname) {
-               ret = fprintf(fp, "mkdir -p %s/%s/delta0/etc\n"
-                                 "echo %s > %s/%s/delta0/etc/hostname\n",
-                             path, newname, newname, path, newname);
+               ret = fprintf(fp,
+                             "mkdir -p %s/%s/%s/etc\n"
+                             "echo %s > %s/%s/%s/etc/hostname\n",
+                             path, newname, LXC_OVERLAY_DELTA_PATH, newname,
+                             path, newname, LXC_OVERLAY_DELTA_PATH);
                if (ret < 0)
                        goto err_close;
        }