2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "lxccontainer.h"
37 #include "storage_utils.h"
40 lxc_log_define(overlay
, lxc
);
42 static char *ovl_name
;
43 static char *ovl_version
[] = {"overlay", "overlayfs"};
45 static char *ovl_detect_name(void);
46 static int ovl_do_rsync(const char *src
, const char *dest
,
47 struct lxc_conf
*conf
);
48 static int ovl_remount_on_enodev(const char *lower
, const char *target
,
49 const char *name
, unsigned long mountflags
,
52 int ovl_clonepaths(struct lxc_storage
*orig
, struct lxc_storage
*new, const char *oldname
,
53 const char *cname
, const char *oldpath
, const char *lxcpath
,
54 int snap
, uint64_t newsize
, struct lxc_conf
*conf
)
60 ERROR("The overlay storage driver can only be used for "
65 if (!orig
->src
|| !orig
->dest
)
68 new->dest
= must_make_path(lxcpath
, cname
, "rootfs", NULL
);
70 ret
= mkdir_p(new->dest
, 0755);
71 if (ret
< 0 && errno
!= EEXIST
) {
72 SYSERROR("Failed to create directory \"%s\"", new->dest
);
77 ret
= chown_mapped_root(new->dest
, conf
);
79 WARN("Failed to update ownership of %s", new->dest
);
82 if (strcmp(orig
->type
, "dir") == 0) {
83 char *delta
, *lastslash
;
85 int ret
, len
, lastslashidx
;
87 /* If we have "/var/lib/lxc/c2/rootfs" then delta will be
88 * "/var/lib/lxc/c2/delta0".
90 lastslash
= strrchr(new->dest
, '/');
92 ERROR("Failed to detect \"/\" in string \"%s\"",
97 if (strlen(lastslash
) < (sizeof("/rootfs") - 1)) {
98 ERROR("Failed to detect \"/rootfs\" in string \"%s\"",
104 lastslashidx
= lastslash
- new->dest
;
106 delta
= malloc(lastslashidx
+ 7);
108 ERROR("Failed to allocate memory");
112 memcpy(delta
, new->dest
, lastslashidx
+ 1);
113 memcpy(delta
+ lastslashidx
, "delta0", sizeof("delta0") - 1);
114 delta
[lastslashidx
+ sizeof("delta0") - 1] = '\0';
116 ret
= mkdir(delta
, 0755);
117 if (ret
< 0 && errno
!= EEXIST
) {
118 SYSERROR("Failed to create directory \"%s\"", delta
);
124 ret
= chown_mapped_root(delta
, conf
);
126 WARN("Failed to update ownership of %s", delta
);
129 /* Make workdir for overlayfs.v22 or higher:
130 * The workdir will be
131 * /var/lib/lxc/c2/olwork
132 * and is used to prepare files before they are atomically
133 * switched to the overlay destination. Workdirs need to be on
134 * the same filesystem as the upperdir so it's OK for it to be
137 work
= malloc(lastslashidx
+ 7);
139 ERROR("Failed to allocate memory");
144 memcpy(work
, new->dest
, lastslashidx
+ 1);
145 memcpy(work
+ lastslashidx
, "olwork", sizeof("olwork") - 1);
146 work
[lastslashidx
+ sizeof("olwork") - 1] = '\0';
148 ret
= mkdir(work
, 0755);
150 SYSERROR("Failed to create directory \"%s\"", work
);
157 ret
= chown_mapped_root(work
, conf
);
159 WARN("Failed to update ownership of %s", work
);
163 /* strlen("overlay:") = 8
173 src
= lxc_storage_get_path(orig
->src
, orig
->type
);
174 len
= 8 + strlen(delta
) + 1 + strlen(src
) + 1;
175 new->src
= malloc(len
);
177 ERROR("Failed to allocate memory");
182 ret
= snprintf(new->src
, len
, "overlay:%s:%s", src
, delta
);
184 if (ret
< 0 || (size_t)ret
>= len
) {
185 ERROR("Failed to create string");
188 } else if (!strcmp(orig
->type
, "overlayfs") ||
189 !strcmp(orig
->type
, "overlay")) {
190 char *clean_old_path
, *clean_new_path
;
191 char *lastslash
, *ndelta
, *nsrc
, *odelta
, *osrc
, *s1
, *s2
, *s3
,
193 int ret
, lastslashidx
;
194 size_t len
, name_len
;
196 osrc
= strdup(orig
->src
);
198 ERROR("Failed to duplicate string \"%s\"", orig
->src
);
203 if (strncmp(osrc
, "overlay:", 8) == 0)
205 else if (strncmp(osrc
, "overlayfs:", 10) == 0)
208 odelta
= strchr(nsrc
, ':');
210 ERROR("Failed to find \":\" in \"%s\"", nsrc
);
217 ndelta
= must_make_path(lxcpath
, cname
, "delta0", NULL
);
219 ret
= mkdir(ndelta
, 0755);
220 if (ret
< 0 && errno
!= EEXIST
) {
221 SYSERROR("Failed to create directory \"%s\"", ndelta
);
228 ret
= chown_mapped_root(ndelta
, conf
);
230 WARN("Failed to update ownership of %s",
234 /* Make workdir for overlayfs.v22 or higher (See the comment
237 lastslash
= strrchr(ndelta
, '/');
239 ERROR("Failed to detect \"/\" in \"%s\"", ndelta
);
245 lastslashidx
= lastslash
- ndelta
;
247 work
= malloc(lastslashidx
+ 7);
251 ERROR("Failed to allocate memory");
255 memcpy(work
, ndelta
, lastslashidx
+ 1);
256 memcpy(work
+ lastslashidx
, "olwork", sizeof("olwork") - 1);
257 work
[lastslashidx
+ sizeof("olwork") - 1] = '\0';
259 ret
= mkdir(work
, 0755);
260 if (ret
< 0 && errno
!= EEXIST
) {
261 SYSERROR("Failed to create directory \"%s\"", ndelta
);
269 ret
= chown_mapped_root(work
, conf
);
271 WARN("Failed to update ownership of %s", work
);
275 /* strlen("overlay:") = 8
285 len
= 8 + strlen(ndelta
) + 1 + strlen(nsrc
) + 1;
286 new->src
= malloc(len
);
290 ERROR("Failed to allocate memory");
293 ret
= snprintf(new->src
, len
, "overlay:%s:%s", nsrc
, ndelta
);
294 if (ret
< 0 || (size_t)ret
>= len
) {
295 ERROR("Failed to create string");
301 ret
= ovl_do_rsync(odelta
, ndelta
, conf
);
307 /* When we create an overlay snapshot of an overlay container in
308 * the snapshot directory under "<lxcpath>/<name>/snaps/" we
309 * don't need to record a dependency. If we would restore would
312 clean_old_path
= lxc_deslashify(oldpath
);
316 clean_new_path
= lxc_deslashify(lxcpath
);
317 if (!clean_new_path
) {
318 free(clean_old_path
);
322 s1
= strrchr(clean_old_path
, '/');
324 ERROR("Failed to detect \"/\" in string \"%s\"", clean_old_path
);
325 free(clean_old_path
);
326 free(clean_new_path
);
330 s2
= strrchr(clean_new_path
, '/');
332 ERROR("Failed to detect \"/\" in string \"%s\"", clean_new_path
);
333 free(clean_old_path
);
334 free(clean_new_path
);
338 if (!strncmp(s1
, "/snaps", sizeof("/snaps") - 1)) {
342 } else if (!strncmp(s2
, "/snaps", sizeof("/snaps") - 1)) {
345 s3
= (char *)oldname
;
347 free(clean_old_path
);
348 free(clean_new_path
);
353 if (!strncmp(s1
, s2
, len
)) {
356 tmp
= (char *)(s2
+ len
+ 1);
358 free(clean_old_path
);
359 free(clean_new_path
);
363 name_len
= strlen(s3
);
364 if (strncmp(s3
, tmp
, name_len
)) {
365 free(clean_old_path
);
366 free(clean_new_path
);
370 free(clean_old_path
);
371 free(clean_new_path
);
372 return LXC_CLONE_SNAPSHOT
;
375 free(clean_old_path
);
376 free(clean_new_path
);
379 ERROR("overlay clone of %s container is not yet supported",
381 /* Note, supporting this will require ovl_mount supporting
382 * mounting of the underlay. No big deal, just needs to be done.
390 /* To say "lxc-create -t ubuntu -n o1 -B overlay" means you want
391 * "<lxcpath>/<lxcname>/rootfs" to have the created container, while all changes
392 * after starting the container are written to "<lxcpath>/<lxcname>/delta0".
394 int ovl_create(struct lxc_storage
*bdev
, const char *dest
, const char *n
,
395 struct bdev_specs
*specs
)
402 if (len
< 8 || strcmp(dest
+ len
- 7, "/rootfs")) {
403 ERROR("Failed to detect \"/rootfs\" in \"%s\"", dest
);
407 bdev
->dest
= strdup(dest
);
409 ERROR("Failed to duplicate string \"%s\"", dest
);
413 delta
= malloc(len
+ 1);
415 ERROR("Failed to allocate memory");
419 memcpy(delta
, dest
, len
);
420 memcpy(delta
+ len
- 6, "delta0", sizeof("delta0") - 1);
421 delta
[len
+ sizeof("delta0")] = '\0';
423 ret
= mkdir_p(delta
, 0755);
425 SYSERROR("Failed to create directory \"%s\"", delta
);
430 /* overlay:lower:upper */
431 newlen
= (2 * len
) + strlen("overlay:") + 2;
432 bdev
->src
= malloc(newlen
);
434 ERROR("Failed to allocate memory");
439 ret
= snprintf(bdev
->src
, newlen
, "overlay:%s:%s", dest
, delta
);
440 if (ret
< 0 || (size_t)ret
>= newlen
) {
441 ERROR("Failed to create string");
446 ret
= mkdir_p(bdev
->dest
, 0755);
448 SYSERROR("Failed to create directory \"%s\"", bdev
->dest
);
457 int ovl_destroy(struct lxc_storage
*orig
)
459 char *upper
= orig
->src
;
461 /* For an overlay container the rootfs is considered immutable
462 * and cannot be removed when restoring from a snapshot.
464 if (orig
->flags
& LXC_STORAGE_INTERNAL_OVERLAY_RESTORE
)
467 if (strncmp(upper
, "overlay:", 8) == 0)
469 else if (strncmp(upper
, "overlayfs:", 10) == 0)
472 upper
= strchr(upper
, ':');
477 return lxc_rmdir_onedev(upper
, NULL
);
480 bool ovl_detect(const char *path
)
482 if (!strncmp(path
, "overlay:", 8))
485 if (!strncmp(path
, "overlayfs:", 10))
491 int ovl_mount(struct lxc_storage
*bdev
)
493 char *tmp
, *options
, *dup
, *lower
, *upper
;
494 char *options_work
, *work
, *lastslash
;
497 unsigned long mntflags
;
501 if (strcmp(bdev
->type
, "overlay") && strcmp(bdev
->type
, "overlayfs"))
504 if (!bdev
->src
|| !bdev
->dest
)
508 ovl_name
= ovl_detect_name();
510 /* Separately mount it first:
511 * mount -t overlay * -o upperdir=${upper},lowerdir=${lower} lower dest
513 dup
= strdup(bdev
->src
);
515 ERROR("Failed to allocate memory");
521 if (strncmp(dup
, "overlay:", 8) == 0)
523 else if (strncmp(dup
, "overlayfs:", 10) == 0)
528 /* support multiple lower layers */
529 while ((tmp
= strstr(upper
, ":/"))) {
535 if (upper
== lower
) {
542 /* if delta doesn't yet exist, create it */
543 ret
= mkdir_p(upper
, 0755);
544 if (ret
< 0 && errno
!= EEXIST
) {
545 SYSERROR("Failed to create directory \"%s\"", upper
);
550 /* overlayfs.v22 or higher needs workdir option:
552 * /var/lib/lxc/c2/delta0
554 * /var/lib/lxc/c2/olwork
556 lastslash
= strrchr(upper
, '/');
558 ERROR("Failed to detect \"/\" in string \"%s\"", upper
);
564 lastslashidx
= lastslash
- upper
;
566 work
= malloc(lastslashidx
+ 7);
568 ERROR("Failed to allocate memory");
573 memcpy(work
, upper
, lastslashidx
+ 1);
574 memcpy(work
+ lastslashidx
, "olwork", sizeof("olwork") - 1);
575 work
[lastslashidx
+ sizeof("olwork") - 1] = '\0';
577 ret
= parse_mntopts(bdev
->mntopts
, &mntflags
, &mntdata
);
579 ERROR("Failed to parse mount options");
586 ret
= mkdir_p(work
, 0755);
587 if (ret
< 0 && errno
!= EEXIST
) {
588 SYSERROR("Failed to create directory \"%s\"", work
);
597 * We should check whether bdev->src is a blockdev but for now only
598 * support overlays of a basic directory
602 len
= strlen(lower
) + strlen(upper
) +
603 strlen("upperdir=,lowerdir=,") + strlen(mntdata
) + 1;
604 options
= alloca(len
);
605 ret
= snprintf(options
, len
, "upperdir=%s,lowerdir=%s,%s",
606 upper
, lower
, mntdata
);
608 len2
= strlen(lower
) + strlen(upper
) + strlen(work
) +
609 strlen("upperdir=,lowerdir=,workdir=") +
611 options_work
= alloca(len2
);
612 ret2
= snprintf(options
, len2
,
613 "upperdir=%s,lowerdir=%s,workdir=%s,%s", upper
,
614 lower
, work
, mntdata
);
616 len
= strlen(lower
) + strlen(upper
) +
617 strlen("upperdir=,lowerdir=") + 1;
618 options
= alloca(len
);
619 ret
= snprintf(options
, len
, "upperdir=%s,lowerdir=%s", upper
,
622 len2
= strlen(lower
) + strlen(upper
) + strlen(work
) +
623 strlen("upperdir=,lowerdir=,workdir=") + 1;
624 options_work
= alloca(len2
);
625 ret2
= snprintf(options_work
, len2
,
626 "upperdir=%s,lowerdir=%s,workdir=%s", upper
,
630 if (ret
< 0 || ret
>= len
|| ret2
< 0 || ret2
>= len2
) {
631 ERROR("Failed to create string");
638 /* Assume we need a workdir as we are on a overlay version >= v22. */
639 ret
= ovl_remount_on_enodev(lower
, bdev
->dest
, ovl_name
,
640 MS_MGC_VAL
| mntflags
, options_work
);
642 INFO("Failed to mount \"%s\" on \"%s\" with options \"%s\". "
643 "Retrying without workdir: %s",
644 lower
, bdev
->dest
, options_work
, strerror(errno
));
646 /* Assume we cannot use a workdir as we are on a version <= v21.
648 ret
= ovl_remount_on_enodev(lower
, bdev
->dest
, ovl_name
,
649 MS_MGC_VAL
| mntflags
, options
);
651 SYSERROR("Failed to mount \"%s\" on \"%s\" with "
652 "options \"%s\": %s",
653 lower
, bdev
->dest
, options
, strerror(errno
));
655 INFO("Mounted \"%s\" on \"%s\" with options \"%s\"",
656 lower
, bdev
->dest
, options
);
658 INFO("Mounted \"%s\" on \"%s\" with options \"%s\"", lower
,
659 bdev
->dest
, options_work
);
667 int ovl_umount(struct lxc_storage
*bdev
)
671 if (strcmp(bdev
->type
, "overlay") && strcmp(bdev
->type
, "overlayfs"))
674 if (!bdev
->src
|| !bdev
->dest
)
677 ret
= umount(bdev
->dest
);
679 SYSERROR("Failed to unmount \"%s\"", bdev
->dest
);
681 TRACE("Unmounted \"%s\"", bdev
->dest
);
686 const char *ovl_get_lower(const char *rootfs_path
)
688 const char *s1
= rootfs_path
;
690 if (strncmp(rootfs_path
, "overlay:", 8) == 0)
692 else if (strncmp(rootfs_path
, "overlayfs:", 10) == 0)
695 s1
= strstr(s1
, ":/");
703 char *ovl_get_rootfs(const char *rootfs_path
, size_t *rootfslen
)
705 char *rootfsdir
= NULL
;
710 if (!rootfs_path
|| !rootfslen
)
713 s1
= strdup(rootfs_path
);
718 if (strncmp(rootfs_path
, "overlay:", 8) == 0)
720 else if (strncmp(rootfs_path
, "overlayfs:", 10) == 0)
723 s3
= strstr(s2
, ":/");
727 rootfsdir
= strdup(s2
);
732 *rootfslen
= strlen(rootfsdir
);
737 int ovl_mkdir(const struct mntent
*mntent
, const struct lxc_rootfs
*rootfs
,
738 const char *lxc_name
, const char *lxc_path
)
740 char lxcpath
[MAXPATHLEN
];
743 size_t arrlen
, i
, len
, rootfslen
;
746 char *rootfs_dir
= NULL
, *rootfs_path
= NULL
, *upperdir
= NULL
,
749 /* When rootfs == NULL we have a container without a rootfs. */
750 if (rootfs
&& rootfs
->path
)
751 rootfs_path
= rootfs
->path
;
753 opts
= lxc_string_split(mntent
->mnt_opts
, ',');
755 arrlen
= lxc_array_len((void **)opts
);
759 for (i
= 0; i
< arrlen
; i
++) {
760 if (strstr(opts
[i
], "upperdir=") &&
761 (strlen(opts
[i
]) > (len
= strlen("upperdir="))))
762 upperdir
= opts
[i
] + len
;
763 else if (strstr(opts
[i
], "workdir=") &&
764 (strlen(opts
[i
]) > (len
= strlen("workdir="))))
765 workdir
= opts
[i
] + len
;
769 ret
= snprintf(lxcpath
, MAXPATHLEN
, "%s/%s", lxc_path
, lxc_name
);
770 if (ret
< 0 || ret
>= MAXPATHLEN
)
773 rootfs_dir
= ovl_get_rootfs(rootfs_path
, &rootfslen
);
777 dirlen
= strlen(lxcpath
);
781 * We neither allow users to create upperdirs and workdirs outside the
782 * containerdir nor inside the rootfs. The latter might be debatable.
783 * When we have a container without a rootfs we skip the checks.
788 ret
= mkdir_p(upperdir
, 0755);
789 else if (!strncmp(upperdir
, lxcpath
, dirlen
) &&
790 strncmp(upperdir
, rootfs_dir
, rootfslen
))
791 ret
= mkdir_p(upperdir
, 0755);
793 WARN("Failed to create directory \"%s\": %s", upperdir
,
800 ret
= mkdir_p(workdir
, 0755);
801 else if (!strncmp(workdir
, lxcpath
, dirlen
) &&
802 strncmp(workdir
, rootfs_dir
, rootfslen
))
803 ret
= mkdir_p(workdir
, 0755);
805 WARN("Failed to create directory \"%s\": %s", workdir
,
813 lxc_free_array((void **)opts
, free
);
817 /* To be called from lxcapi_clone() in lxccontainer.c: When we clone a container
818 * with overlay lxc.mount.entry entries we need to update absolute paths for
819 * upper- and workdir. This update is done in two locations:
820 * lxc_conf->unexpanded_config and lxc_conf->mount_list. Both updates are done
821 * independent of each other since lxc_conf->mountlist may contain more mount
822 * entries (e.g. from other included files) than lxc_conf->unexpanded_config.
824 int ovl_update_abs_paths(struct lxc_conf
*lxc_conf
, const char *lxc_path
,
825 const char *lxc_name
, const char *newpath
,
828 char new_upper
[MAXPATHLEN
], new_work
[MAXPATHLEN
], old_upper
[MAXPATHLEN
],
829 old_work
[MAXPATHLEN
];
831 struct lxc_list
*iterator
;
832 char *cleanpath
= NULL
;
835 const char *ovl_dirs
[] = {"br", "upperdir", "workdir"};
837 cleanpath
= strdup(newpath
);
841 remove_trailing_slashes(cleanpath
);
844 * We have to update lxc_conf->unexpanded_config separately from
845 * lxc_conf->mount_list.
847 for (i
= 0; i
< sizeof(ovl_dirs
) / sizeof(ovl_dirs
[0]); i
++) {
848 if (!clone_update_unexp_ovl_paths(lxc_conf
, lxc_path
, newpath
,
855 snprintf(old_work
, MAXPATHLEN
, "workdir=%s/%s", lxc_path
, lxc_name
);
856 if (ret
< 0 || ret
>= MAXPATHLEN
)
860 snprintf(new_work
, MAXPATHLEN
, "workdir=%s/%s", cleanpath
, newname
);
861 if (ret
< 0 || ret
>= MAXPATHLEN
)
864 lxc_list_for_each(iterator
, &lxc_conf
->mount_list
) {
865 char *mnt_entry
= NULL
, *new_mnt_entry
= NULL
, *tmp
= NULL
,
866 *tmp_mnt_entry
= NULL
;
868 mnt_entry
= iterator
->elem
;
870 if (strstr(mnt_entry
, "overlay"))
872 else if (strstr(mnt_entry
, "aufs"))
878 ret
= snprintf(old_upper
, MAXPATHLEN
, "%s=%s/%s", tmp
, lxc_path
,
880 if (ret
< 0 || ret
>= MAXPATHLEN
)
883 ret
= snprintf(new_upper
, MAXPATHLEN
, "%s=%s/%s", tmp
,
885 if (ret
< 0 || ret
>= MAXPATHLEN
)
888 if (strstr(mnt_entry
, old_upper
)) {
890 lxc_string_replace(old_upper
, new_upper
, mnt_entry
);
893 if (strstr(mnt_entry
, old_work
)) {
895 new_mnt_entry
= lxc_string_replace(
896 old_work
, new_work
, tmp_mnt_entry
);
898 new_mnt_entry
= lxc_string_replace(
899 old_work
, new_work
, mnt_entry
);
903 free(iterator
->elem
);
904 iterator
->elem
= strdup(new_mnt_entry
);
905 } else if (tmp_mnt_entry
) {
906 free(iterator
->elem
);
907 iterator
->elem
= strdup(tmp_mnt_entry
);
920 static int ovl_remount_on_enodev(const char *lower
, const char *target
,
921 const char *name
, unsigned long mountflags
,
925 ret
= mount(lower
, target
, ovl_name
, MS_MGC_VAL
| mountflags
, options
);
926 if (ret
< 0 && errno
== ENODEV
) /* Try other module name. */
927 ret
= mount(lower
, target
,
928 ovl_name
== ovl_version
[0] ? ovl_version
[1]
930 MS_MGC_VAL
| mountflags
, options
);
934 static char *ovl_detect_name(void)
937 char *v
= ovl_version
[0];
941 f
= fopen("/proc/filesystems", "r");
945 while (getline(&line
, &len
, f
) != -1) {
946 if (strcmp(line
, "nodev\toverlayfs\n") == 0) {
957 static int ovl_do_rsync(const char *src
, const char *dest
,
958 struct lxc_conf
*conf
)
961 struct rsync_data_char rdata
= {0};
962 char cmd_output
[MAXPATHLEN
] = {0};
964 rdata
.src
= (char *)src
;
965 rdata
.dest
= (char *)dest
;
967 ret
= userns_exec_full(conf
, lxc_rsync_exec_wrapper
, &rdata
,
968 "lxc_rsync_exec_wrapper");
970 ret
= run_command(cmd_output
, sizeof(cmd_output
),
971 lxc_rsync_exec_wrapper
, (void *)&rdata
);
973 ERROR("Failed to rsync from \"%s\" into \"%s\"%s%s", src
, dest
,
974 cmd_output
[0] != '\0' ? ": " : "",
975 cmd_output
[0] != '\0' ? cmd_output
: "");