]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/storage/overlay.c
Merge pull request #3842 from brauner/2021-05-14.fixes
[mirror_lxc.git] / src / lxc / storage / overlay.c
CommitLineData
cc73685d 1/* SPDX-License-Identifier: LGPL-2.1+ */
38683db4 2
d38dd64a
CB
3#ifndef _GNU_SOURCE
4#define _GNU_SOURCE 1
5#endif
38683db4
CB
6#include <errno.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
38683db4 11#include "conf.h"
d38dd64a 12#include "config.h"
38683db4
CB
13#include "confile.h"
14#include "log.h"
15#include "lxccontainer.h"
6333c915 16#include "macro.h"
e2c6671d 17#include "memory_utils.h"
28d832c4
CB
18#include "overlay.h"
19#include "rsync.h"
20#include "storage.h"
ba115175 21#include "storage_utils.h"
38683db4
CB
22#include "utils.h"
23
10bc1861 24lxc_log_define(overlay, lxc);
38683db4 25
5c484f79 26static char *ovl_name;
88232d3f 27static char *ovl_version[] = {"overlay", "overlayfs"};
5c484f79 28
5c484f79 29static char *ovl_detect_name(void);
17a367d8 30static int ovl_do_rsync(const char *src, const char *dest,
3188197d 31 struct lxc_conf *conf);
88232d3f
CB
32static int ovl_remount_on_enodev(const char *lower, const char *target,
33 const char *name, unsigned long mountflags,
34 const void *options);
38683db4 35
10bc1861 36int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char *oldname,
83e79752
CB
37 const char *cname, const char *oldpath, const char *lxcpath,
38 int snap, uint64_t newsize, struct lxc_conf *conf)
38683db4 39{
241978fa 40 int ret;
41dc7155 41 const char *src;
4d463f62 42
38683db4 43 if (!snap) {
241978fa
CB
44 ERROR("The overlay storage driver can only be used for "
45 "snapshots");
38683db4
CB
46 return -22;
47 }
48
49 if (!orig->src || !orig->dest)
50 return -1;
51
241978fa 52 new->dest = must_make_path(lxcpath, cname, "rootfs", NULL);
ba115175 53
241978fa
CB
54 ret = mkdir_p(new->dest, 0755);
55 if (ret < 0 && errno != EEXIST) {
56 SYSERROR("Failed to create directory \"%s\"", new->dest);
38683db4 57 return -1;
241978fa 58 }
38683db4 59
facdf925 60 if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
241978fa
CB
61 ret = chown_mapped_root(new->dest, conf);
62 if (ret < 0)
63 WARN("Failed to update ownership of %s", new->dest);
64 }
38683db4
CB
65
66 if (strcmp(orig->type, "dir") == 0) {
facdf925
CB
67 __do_free char *delta = NULL, *work = NULL;
68 int len;
38683db4 69
facdf925 70 delta = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL);
38683db4 71
facdf925
CB
72 ret = mkdir_p(delta, 0755);
73 if (ret < 0 && errno != EEXIST)
74 return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", delta);
241978fa 75
facdf925
CB
76 /*
77 * Make workdir for overlayfs.v22 or higher:
5c484f79 78 * The workdir will be
facdf925 79 * /var/lib/lxc/c2/LXC_OVERLAY_WORK_PATH
5c484f79
CB
80 * and is used to prepare files before they are atomically
81 * switched to the overlay destination. Workdirs need to be on
82 * the same filesystem as the upperdir so it's OK for it to be
83 * empty.
84 */
facdf925 85 work = must_make_path(lxcpath, cname, LXC_OVERLAY_WORK_PATH, NULL);
241978fa 86
facdf925
CB
87 ret = mkdir_p(work, 0755);
88 if (ret < 0 && errno != EEXIST)
89 return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", work);
241978fa 90
facdf925
CB
91 if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
92 __do_free char *lxc_overlay_delta_dir = NULL,
93 *lxc_overlay_private_dir = NULL;
94
95 lxc_overlay_private_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_PRIVATE_DIR, NULL);
96 ret = chown_mapped_root(lxc_overlay_private_dir, conf);
97 if (ret < 0)
98 WARN("Failed to update ownership of %s", lxc_overlay_private_dir);
99
100 lxc_overlay_delta_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL);
101 ret = chown_mapped_root(lxc_overlay_delta_dir, conf);
102 if (ret < 0)
103 WARN("Failed to update ownership of %s", lxc_overlay_delta_dir);
241978fa 104
241978fa
CB
105 ret = chown_mapped_root(work, conf);
106 if (ret < 0)
107 WARN("Failed to update ownership of %s", work);
108 }
38683db4 109
4d463f62 110 src = lxc_storage_get_path(orig->src, orig->type);
facdf925
CB
111 len = STRLITERALLEN("overlay") + STRLITERALLEN(":") +
112 strlen(src) + STRLITERALLEN(":") + strlen(delta) + 1;
113
38683db4 114 new->src = malloc(len);
facdf925
CB
115 if (!new->src)
116 return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory");
241978fa 117
ba115175 118 ret = snprintf(new->src, len, "overlay:%s:%s", src, delta);
facdf925
CB
119 if (ret < 0 || (size_t)ret >= len)
120 return log_error_errno(-EIO, EIO, "Failed to create string");
241978fa
CB
121 } else if (!strcmp(orig->type, "overlayfs") ||
122 !strcmp(orig->type, "overlay")) {
facdf925
CB
123 __do_free char *clean_old_path = NULL, *clean_new_path = NULL,
124 *ndelta = NULL, *osrc = NULL, *work = NULL;
125 char *nsrc, *odelta, *s1, *s2, *s3;
70e95c8d 126 size_t len, name_len;
ba115175
CB
127
128 osrc = strdup(orig->src);
facdf925
CB
129 if (!osrc)
130 return log_error_errno(-22, ENOMEM, "Failed to duplicate string \"%s\"", orig->src);
ba115175 131
09f6f8c4 132 nsrc = osrc;
facdf925
CB
133 if (strncmp(osrc, "overlay:", STRLITERALLEN("overlay:")) == 0)
134 nsrc += STRLITERALLEN("overlay:");
135 else if (strncmp(osrc, "overlayfs:", STRLITERALLEN("overlayfs:")) == 0)
136 nsrc += STRLITERALLEN("overlayfs:");
ba115175
CB
137
138 odelta = strchr(nsrc, ':');
facdf925
CB
139 if (!odelta)
140 return log_error_errno(-22, ENOENT, "Failed to find \":\" in \"%s\"", nsrc);
ba115175 141
38683db4
CB
142 *odelta = '\0';
143 odelta++;
facdf925 144 ndelta = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL);
ba115175 145
facdf925
CB
146 ret = mkdir_p(ndelta, 0755);
147 if (ret < 0 && errno != EEXIST)
148 return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", ndelta);
38683db4 149
241978fa
CB
150 /* Make workdir for overlayfs.v22 or higher (See the comment
151 * further up.).
5c484f79 152 */
facdf925
CB
153 work = must_make_path(lxcpath, cname, LXC_OVERLAY_WORK_PATH, NULL);
154 ret = mkdir_p(work, 0755);
155 if (ret < 0 && errno != EEXIST)
156 return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", ndelta);
241978fa 157
facdf925
CB
158 if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
159 __do_free char *lxc_overlay_delta_dir = NULL,
160 *lxc_overlay_private_dir = NULL;
241978fa 161
facdf925
CB
162 lxc_overlay_private_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_PRIVATE_DIR, NULL);
163 ret = chown_mapped_root(lxc_overlay_private_dir, conf);
164 if (ret < 0)
165 WARN("Failed to update ownership of %s", lxc_overlay_private_dir);
166
167 lxc_overlay_delta_dir = must_make_path(lxcpath, cname, LXC_OVERLAY_DELTA_PATH, NULL);
168 ret = chown_mapped_root(lxc_overlay_delta_dir, conf);
169 if (ret < 0)
170 WARN("Failed to update ownership of %s", lxc_overlay_delta_dir);
ba115175 171
241978fa
CB
172 ret = chown_mapped_root(work, conf);
173 if (ret < 0)
174 WARN("Failed to update ownership of %s", work);
175 }
38683db4 176
facdf925 177 len = STRLITERALLEN("overlay") + STRLITERALLEN(":") + strlen(nsrc) + STRLITERALLEN(":") + strlen(ndelta) + 1;
38683db4 178 new->src = malloc(len);
facdf925
CB
179 if (!new->src)
180 return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory");
181
ba115175 182 ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta);
facdf925
CB
183 if (ret < 0 || (size_t)ret >= len)
184 return log_error_errno(-EIO, EIO, "Failed to create string");
38683db4 185
17a367d8 186 ret = ovl_do_rsync(odelta, ndelta, conf);
70e95c8d
CB
187 if (ret < 0)
188 return -1;
189
190 /* When we create an overlay snapshot of an overlay container in
191 * the snapshot directory under "<lxcpath>/<name>/snaps/" we
192 * don't need to record a dependency. If we would restore would
193 * also fail.
194 */
28e54be1 195 clean_old_path = path_simplify(oldpath);
70e95c8d 196 if (!clean_old_path)
facdf925 197 return log_error_errno(-ENOMEM, ENOMEM, "Failed to create clean path for \"%s\"", oldpath);
70e95c8d 198
28e54be1 199 clean_new_path = path_simplify(lxcpath);
facdf925
CB
200 if (!clean_new_path)
201 return log_error_errno(-ENOMEM, ENOMEM, "Failed to create clean path for \"%s\"", lxcpath);
70e95c8d
CB
202
203 s1 = strrchr(clean_old_path, '/');
facdf925
CB
204 if (!s1)
205 return log_error_errno(-ENOENT, ENOENT, "Failed to detect \"/\" in string \"%s\"", clean_old_path);
70e95c8d
CB
206
207 s2 = strrchr(clean_new_path, '/');
facdf925
CB
208 if (!s2)
209 return log_error_errno(-ENOENT, ENOENT, "Failed to detect \"/\" in string \"%s\"", clean_new_path);
70e95c8d 210
6333c915 211 if (!strncmp(s1, "/snaps", STRLITERALLEN("/snaps"))) {
70e95c8d
CB
212 s1 = clean_new_path;
213 s2 = clean_old_path;
214 s3 = (char *)cname;
6333c915 215 } else if (!strncmp(s2, "/snaps", STRLITERALLEN("/snaps"))) {
70e95c8d
CB
216 s1 = clean_old_path;
217 s2 = clean_new_path;
218 s3 = (char *)oldname;
70e95c8d 219 } else {
70e95c8d
CB
220 return 0;
221 }
222
7f022483 223 len = strlen(s1);
70e95c8d
CB
224 if (!strncmp(s1, s2, len)) {
225 char *tmp;
226
227 tmp = (char *)(s2 + len + 1);
facdf925 228 if (*tmp == '\0')
70e95c8d 229 return 0;
70e95c8d
CB
230
231 name_len = strlen(s3);
facdf925 232 if (strncmp(s3, tmp, name_len))
70e95c8d 233 return 0;
70e95c8d 234
7f022483 235 return LXC_CLONE_SNAPSHOT;
70e95c8d
CB
236 }
237
70e95c8d 238 return 0;
38683db4 239 } else {
facdf925
CB
240 /*
241 * Note, supporting this will require ovl_mount supporting
5c484f79
CB
242 * mounting of the underlay. No big deal, just needs to be done.
243 */
facdf925 244 return log_error_errno(-EINVAL, EINVAL, "overlay clone of %s container is not yet supported", orig->type);
38683db4
CB
245 }
246
247 return 0;
248}
249
241978fa
CB
250/* To say "lxc-create -t ubuntu -n o1 -B overlay" means you want
251 * "<lxcpath>/<lxcname>/rootfs" to have the created container, while all changes
facdf925 252 * after starting the container are written to "<lxcpath>/<lxcname>/LXC_OVERLAY_DELTA_PATH".
38683db4 253 */
10bc1861 254int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n,
facdf925 255 struct bdev_specs *specs, const struct lxc_conf *conf)
38683db4 256{
facdf925 257 __do_free char *delta = NULL, *tmp = NULL;
241978fa 258 int ret;
facdf925 259 size_t len;
38683db4 260
241978fa 261 len = strlen(dest);
facdf925
CB
262 if (len < 8 || strcmp(dest + len - STRLITERALLEN("/rootfs"), "/rootfs"))
263 return log_error_errno(-ENOENT, ENOENT, "Failed to detect \"/rootfs\" in \"%s\"", dest);
38683db4 264
241978fa 265 bdev->dest = strdup(dest);
facdf925
CB
266 if (!bdev->dest)
267 return log_error_errno(-ENOMEM, ENOMEM, "Failed to duplicate string \"%s\"", dest);
38683db4 268
facdf925
CB
269 tmp = strndup(dest, len - STRLITERALLEN("/rootfs"));
270 if (!tmp)
271 return log_error_errno(-ENOMEM, ENOMEM, "Failed to duplicate string \"%s\"", dest);
272
273 delta = must_make_path(tmp, LXC_OVERLAY_DELTA_PATH, NULL);
38683db4 274
241978fa 275 ret = mkdir_p(delta, 0755);
facdf925
CB
276 if (ret < 0 && errno != EEXIST)
277 return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", delta);
278
279 if (am_guest_unpriv() || !lxc_list_empty(&conf->id_map)) {
280 __do_free char *lxc_overlay_private_dir = NULL;
281
282 lxc_overlay_private_dir = must_make_path(tmp, LXC_OVERLAY_PRIVATE_DIR, NULL);
283 ret = chown_mapped_root(lxc_overlay_private_dir, conf);
284 if (ret < 0)
285 WARN("Failed to update ownership of %s", lxc_overlay_private_dir);
286
287 ret = chown_mapped_root(delta, conf);
288 if (ret < 0)
289 WARN("Failed to update ownership of %s", delta);
38683db4
CB
290 }
291
241978fa 292 /* overlay:lower:upper */
facdf925
CB
293 len = STRLITERALLEN("overlay") + STRLITERALLEN(":") + len + STRLITERALLEN(":") + strlen(delta) + 1;
294 bdev->src = malloc(len);
295 if (!bdev->src)
296 return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory");
241978fa 297
facdf925
CB
298 ret = snprintf(bdev->src, len, "overlay:%s:%s", dest, delta);
299 if (ret < 0 || (size_t)ret >= len)
300 return log_error_errno(-EIO, EIO, "Failed to create rootfs path");
38683db4 301
241978fa 302 ret = mkdir_p(bdev->dest, 0755);
facdf925
CB
303 if (ret < 0 && errno != EEXIST)
304 return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", bdev->dest);
38683db4
CB
305
306 return 0;
307}
308
10bc1861 309int ovl_destroy(struct lxc_storage *orig)
5c484f79 310{
ba115175 311 char *upper = orig->src;
5c484f79 312
17a367d8
CB
313 /* For an overlay container the rootfs is considered immutable
314 * and cannot be removed when restoring from a snapshot.
315 */
316 if (orig->flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)
317 return 0;
318
09f6f8c4 319 if (strncmp(upper, "overlay:", 8) == 0)
241978fa 320 upper += 8;
09f6f8c4 321 else if (strncmp(upper, "overlayfs:", 10) == 0)
241978fa 322 upper += 10;
ba115175
CB
323
324 upper = strchr(upper, ':');
5c484f79
CB
325 if (!upper)
326 return -22;
327 upper++;
ba115175 328
5c484f79
CB
329 return lxc_rmdir_onedev(upper, NULL);
330}
331
3d2ae1e2 332bool ovl_detect(const char *path)
5c484f79 333{
09f6f8c4 334 if (!strncmp(path, "overlay:", 8))
3d2ae1e2 335 return true;
f7ac4459 336
09f6f8c4 337 if (!strncmp(path, "overlayfs:", 10))
3d2ae1e2 338 return true;
f7ac4459 339
3d2ae1e2 340 return false;
5c484f79
CB
341}
342
10bc1861 343int ovl_mount(struct lxc_storage *bdev)
5c484f79 344{
a08bfbe3
CB
345 __do_free char *options = NULL, *options_work = NULL;
346 unsigned long mntflags = 0;
347 char *mntdata = NULL;
e2c6671d
CB
348 char *tmp, *dup, *lower, *upper;
349 char *work, *lastslash;
241978fa 350 size_t len, len2;
5c484f79
CB
351 int ret, ret2;
352
ba115175 353 if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
5c484f79 354 return -22;
ba115175 355
5c484f79
CB
356 if (!bdev->src || !bdev->dest)
357 return -22;
358
359 if (!ovl_name)
360 ovl_name = ovl_detect_name();
361
241978fa
CB
362 /* Separately mount it first:
363 * mount -t overlay * -o upperdir=${upper},lowerdir=${lower} lower dest
5c484f79 364 */
241978fa 365 dup = strdup(bdev->src);
facdf925
CB
366 if (!dup)
367 return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate memory");
09f6f8c4
CB
368 upper = dup;
369 lower = dup;
241978fa 370
facdf925
CB
371 if (strncmp(dup, "overlay:", STRLITERALLEN("overlay:")) == 0)
372 lower += STRLITERALLEN("overlay:");
373 else if (strncmp(dup, "overlayfs:", STRLITERALLEN("overlayfs:")) == 0)
374 lower += STRLITERALLEN("overlayfs:");
09f6f8c4
CB
375 if (upper != lower)
376 upper = lower;
241978fa 377
09f6f8c4
CB
378 /* support multiple lower layers */
379 while ((tmp = strstr(upper, ":/"))) {
380 tmp++;
9208af16
CB
381 upper = tmp;
382 }
241978fa
CB
383
384 upper--;
385 if (upper == lower) {
386 free(dup);
5c484f79 387 return -22;
241978fa 388 }
5c484f79
CB
389 *upper = '\0';
390 upper++;
391
241978fa 392 /* if delta doesn't yet exist, create it */
adcdf4e4 393 ret = mkdir_p(upper, 0755);
241978fa
CB
394 if (ret < 0 && errno != EEXIST) {
395 SYSERROR("Failed to create directory \"%s\"", upper);
396 free(dup);
5c484f79 397 return -22;
241978fa 398 }
5c484f79 399
241978fa 400 /* overlayfs.v22 or higher needs workdir option:
5c484f79 401 * if upper is
facdf925 402 * /var/lib/lxc/c2/LXC_OVERLAY_DELTA_PATH
5c484f79 403 * then workdir is
facdf925 404 * /var/lib/lxc/c2/LXC_OVERLAY_WORK_PATH
5c484f79
CB
405 */
406 lastslash = strrchr(upper, '/');
241978fa
CB
407 if (!lastslash) {
408 ERROR("Failed to detect \"/\" in string \"%s\"", upper);
409 free(dup);
5c484f79 410 return -22;
241978fa
CB
411 }
412
facdf925
CB
413 upper[lastslash - upper] = '\0';
414 work = must_make_path(upper, LXC_OVERLAY_WORK_DIR, NULL);
415 upper[lastslash - upper] = '/';
241978fa
CB
416
417 ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata);
418 if (ret < 0) {
419 ERROR("Failed to parse mount options");
5c484f79 420 free(mntdata);
241978fa
CB
421 free(dup);
422 free(work);
5c484f79
CB
423 return -22;
424 }
425
241978fa
CB
426 ret = mkdir_p(work, 0755);
427 if (ret < 0 && errno != EEXIST) {
428 SYSERROR("Failed to create directory \"%s\"", work);
5c484f79 429 free(mntdata);
241978fa
CB
430 free(dup);
431 free(work);
5c484f79
CB
432 return -22;
433 }
434
435 /*
436 * TODO:
437 * We should check whether bdev->src is a blockdev but for now only
438 * support overlays of a basic directory
439 */
440
441 if (mntdata) {
241978fa
CB
442 len = strlen(lower) + strlen(upper) +
443 strlen("upperdir=,lowerdir=,") + strlen(mntdata) + 1;
e2c6671d 444 options = must_realloc(NULL, len);
241978fa
CB
445 ret = snprintf(options, len, "upperdir=%s,lowerdir=%s,%s",
446 upper, lower, mntdata);
5c484f79 447
241978fa
CB
448 len2 = strlen(lower) + strlen(upper) + strlen(work) +
449 strlen("upperdir=,lowerdir=,workdir=") +
450 strlen(mntdata) + 1;
e2c6671d 451 options_work = must_realloc(NULL, len2);
241978fa
CB
452 ret2 = snprintf(options, len2,
453 "upperdir=%s,lowerdir=%s,workdir=%s,%s", upper,
454 lower, work, mntdata);
5c484f79 455 } else {
241978fa
CB
456 len = strlen(lower) + strlen(upper) +
457 strlen("upperdir=,lowerdir=") + 1;
e2c6671d 458 options = must_realloc(NULL, len);
241978fa
CB
459 ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper,
460 lower);
5c484f79 461
241978fa
CB
462 len2 = strlen(lower) + strlen(upper) + strlen(work) +
463 strlen("upperdir=,lowerdir=,workdir=") + 1;
e2c6671d 464 options_work = must_realloc(NULL, len2);
241978fa
CB
465 ret2 = snprintf(options_work, len2,
466 "upperdir=%s,lowerdir=%s,workdir=%s", upper,
467 lower, work);
5c484f79
CB
468 }
469
470 if (ret < 0 || ret >= len || ret2 < 0 || ret2 >= len2) {
241978fa 471 ERROR("Failed to create string");
5c484f79 472 free(mntdata);
241978fa
CB
473 free(dup);
474 free(work);
5c484f79
CB
475 return -1;
476 }
477
241978fa 478 /* Assume we need a workdir as we are on a overlay version >= v22. */
88232d3f
CB
479 ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
480 MS_MGC_VAL | mntflags, options_work);
5c484f79 481 if (ret < 0) {
7874d81a 482 SYSINFO("Failed to mount \"%s\" on \"%s\" with options \"%s\". "
483 "Retrying without workdir",
484 lower, bdev->dest, options_work);
5c484f79 485
241978fa
CB
486 /* Assume we cannot use a workdir as we are on a version <= v21.
487 */
88232d3f 488 ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
241978fa 489 MS_MGC_VAL | mntflags, options);
5c484f79 490 if (ret < 0)
b5be6a7c 491 SYSERROR("Failed to mount \"%s\" on \"%s\" with options \"%s\"",
492 lower, bdev->dest, options);
5c484f79 493 else
241978fa 494 INFO("Mounted \"%s\" on \"%s\" with options \"%s\"",
88232d3f 495 lower, bdev->dest, options);
5c484f79 496 } else {
241978fa 497 INFO("Mounted \"%s\" on \"%s\" with options \"%s\"", lower,
88232d3f 498 bdev->dest, options_work);
5c484f79 499 }
241978fa
CB
500
501 free(dup);
502 free(work);
5c484f79
CB
503 return ret;
504}
505
10bc1861 506int ovl_umount(struct lxc_storage *bdev)
5c484f79 507{
241978fa
CB
508 int ret;
509
ba115175 510 if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
5c484f79 511 return -22;
ba115175 512
5c484f79
CB
513 if (!bdev->src || !bdev->dest)
514 return -22;
ba115175 515
241978fa
CB
516 ret = umount(bdev->dest);
517 if (ret < 0)
518 SYSERROR("Failed to unmount \"%s\"", bdev->dest);
519 else
520 TRACE("Unmounted \"%s\"", bdev->dest);
521
522 return ret;
5c484f79
CB
523}
524
41dc7155 525const char *ovl_get_lower(const char *rootfs_path)
ba115175 526{
41dc7155 527 const char *s1 = rootfs_path;
241978fa 528
41dc7155
CB
529 if (strncmp(rootfs_path, "overlay:", 8) == 0)
530 s1 += 8;
531 else if (strncmp(rootfs_path, "overlayfs:", 10) == 0)
532 s1 += 10;
ba115175
CB
533
534 s1 = strstr(s1, ":/");
535 if (!s1)
536 return NULL;
537 s1++;
538
539 return s1;
540}
541
5c484f79
CB
542char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen)
543{
544 char *rootfsdir = NULL;
545 char *s1 = NULL;
546 char *s2 = NULL;
547 char *s3 = NULL;
548
549 if (!rootfs_path || !rootfslen)
550 return NULL;
551
552 s1 = strdup(rootfs_path);
553 if (!s1)
554 return NULL;
555
41dc7155
CB
556 s2 = s1;
557 if (strncmp(rootfs_path, "overlay:", 8) == 0)
558 s2 += 8;
559 else if (strncmp(rootfs_path, "overlayfs:", 10) == 0)
560 s2 += 10;
561
562 s3 = strstr(s2, ":/");
563 if (s3)
564 *s3 = '\0';
565
566 rootfsdir = strdup(s2);
a61b4e85 567 free(s1);
5c484f79 568 if (!rootfsdir)
a61b4e85 569 return NULL;
5c484f79
CB
570
571 *rootfslen = strlen(rootfsdir);
572
573 return rootfsdir;
574}
575
576int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
577 const char *lxc_name, const char *lxc_path)
578{
339de297 579 char lxcpath[PATH_MAX];
241978fa
CB
580 char **opts;
581 int ret;
180c477a 582 size_t arrlen, i, len, rootfslen;
5c484f79 583 int fret = -1;
180c477a 584 size_t dirlen = 0;
241978fa
CB
585 char *rootfs_dir = NULL, *rootfs_path = NULL, *upperdir = NULL,
586 *workdir = NULL;
5c484f79 587
9769034f
CB
588 /* When rootfs == NULL we have a container without a rootfs. */
589 if (rootfs && rootfs->path)
590 rootfs_path = rootfs->path;
5c484f79
CB
591
592 opts = lxc_string_split(mntent->mnt_opts, ',');
593 if (opts)
594 arrlen = lxc_array_len((void **)opts);
595 else
596 goto err;
597
598 for (i = 0; i < arrlen; i++) {
241978fa
CB
599 if (strstr(opts[i], "upperdir=") &&
600 (strlen(opts[i]) > (len = strlen("upperdir="))))
5c484f79 601 upperdir = opts[i] + len;
241978fa
CB
602 else if (strstr(opts[i], "workdir=") &&
603 (strlen(opts[i]) > (len = strlen("workdir="))))
5c484f79
CB
604 workdir = opts[i] + len;
605 }
606
9769034f 607 if (rootfs_path) {
339de297
CB
608 ret = snprintf(lxcpath, PATH_MAX, "%s/%s", lxc_path, lxc_name);
609 if (ret < 0 || ret >= PATH_MAX)
9769034f 610 goto err;
5c484f79 611
241978fa
CB
612 rootfs_dir = ovl_get_rootfs(rootfs_path, &rootfslen);
613 if (!rootfs_dir)
9769034f 614 goto err;
5c484f79 615
9769034f
CB
616 dirlen = strlen(lxcpath);
617 }
5c484f79
CB
618
619 /*
620 * We neither allow users to create upperdirs and workdirs outside the
621 * containerdir nor inside the rootfs. The latter might be debatable.
9769034f 622 * When we have a container without a rootfs we skip the checks.
5c484f79 623 */
9769034f
CB
624 ret = 0;
625 if (upperdir) {
626 if (!rootfs_path)
627 ret = mkdir_p(upperdir, 0755);
241978fa
CB
628 else if (!strncmp(upperdir, lxcpath, dirlen) &&
629 strncmp(upperdir, rootfs_dir, rootfslen))
9769034f 630 ret = mkdir_p(upperdir, 0755);
a24c5678 631
9769034f 632 if (ret < 0)
a24c5678 633 SYSWARN("Failed to create directory \"%s\"", upperdir);
9769034f
CB
634 }
635
636 ret = 0;
637 if (workdir) {
638 if (!rootfs_path)
639 ret = mkdir_p(workdir, 0755);
241978fa
CB
640 else if (!strncmp(workdir, lxcpath, dirlen) &&
641 strncmp(workdir, rootfs_dir, rootfslen))
9769034f 642 ret = mkdir_p(workdir, 0755);
a24c5678 643
9769034f 644 if (ret < 0)
a24c5678 645 SYSWARN("Failed to create directory \"%s\"", workdir);
9769034f 646 }
5c484f79
CB
647
648 fret = 0;
649
650err:
241978fa 651 free(rootfs_dir);
5c484f79
CB
652 lxc_free_array((void **)opts, free);
653 return fret;
654}
655
241978fa 656/* To be called from lxcapi_clone() in lxccontainer.c: When we clone a container
38683db4
CB
657 * with overlay lxc.mount.entry entries we need to update absolute paths for
658 * upper- and workdir. This update is done in two locations:
659 * lxc_conf->unexpanded_config and lxc_conf->mount_list. Both updates are done
241978fa
CB
660 * independent of each other since lxc_conf->mountlist may contain more mount
661 * entries (e.g. from other included files) than lxc_conf->unexpanded_config.
38683db4 662 */
83e79752
CB
663int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
664 const char *lxc_name, const char *newpath,
665 const char *newname)
38683db4 666{
339de297
CB
667 char new_upper[PATH_MAX], new_work[PATH_MAX], old_upper[PATH_MAX],
668 old_work[PATH_MAX];
84760c11 669 size_t i;
241978fa
CB
670 struct lxc_list *iterator;
671 char *cleanpath = NULL;
38683db4
CB
672 int fret = -1;
673 int ret = 0;
38683db4
CB
674 const char *ovl_dirs[] = {"br", "upperdir", "workdir"};
675
676 cleanpath = strdup(newpath);
677 if (!cleanpath)
678 goto err;
679
680 remove_trailing_slashes(cleanpath);
681
5c484f79
CB
682 /*
683 * We have to update lxc_conf->unexpanded_config separately from
684 * lxc_conf->mount_list.
685 */
38683db4
CB
686 for (i = 0; i < sizeof(ovl_dirs) / sizeof(ovl_dirs[0]); i++) {
687 if (!clone_update_unexp_ovl_paths(lxc_conf, lxc_path, newpath,
688 lxc_name, newname,
689 ovl_dirs[i]))
690 goto err;
691 }
692
241978fa 693 ret =
339de297
CB
694 snprintf(old_work, PATH_MAX, "workdir=%s/%s", lxc_path, lxc_name);
695 if (ret < 0 || ret >= PATH_MAX)
38683db4
CB
696 goto err;
697
241978fa 698 ret =
339de297
CB
699 snprintf(new_work, PATH_MAX, "workdir=%s/%s", cleanpath, newname);
700 if (ret < 0 || ret >= PATH_MAX)
38683db4
CB
701 goto err;
702
703 lxc_list_for_each(iterator, &lxc_conf->mount_list) {
241978fa
CB
704 char *mnt_entry = NULL, *new_mnt_entry = NULL, *tmp = NULL,
705 *tmp_mnt_entry = NULL;
706
38683db4
CB
707 mnt_entry = iterator->elem;
708
709 if (strstr(mnt_entry, "overlay"))
710 tmp = "upperdir";
38683db4
CB
711 if (!tmp)
712 continue;
713
339de297 714 ret = snprintf(old_upper, PATH_MAX, "%s=%s/%s", tmp, lxc_path,
241978fa 715 lxc_name);
339de297 716 if (ret < 0 || ret >= PATH_MAX)
38683db4
CB
717 goto err;
718
339de297 719 ret = snprintf(new_upper, PATH_MAX, "%s=%s/%s", tmp,
241978fa 720 cleanpath, newname);
339de297 721 if (ret < 0 || ret >= PATH_MAX)
38683db4
CB
722 goto err;
723
724 if (strstr(mnt_entry, old_upper)) {
241978fa
CB
725 tmp_mnt_entry =
726 lxc_string_replace(old_upper, new_upper, mnt_entry);
38683db4
CB
727 }
728
729 if (strstr(mnt_entry, old_work)) {
730 if (tmp_mnt_entry)
241978fa
CB
731 new_mnt_entry = lxc_string_replace(
732 old_work, new_work, tmp_mnt_entry);
38683db4 733 else
241978fa
CB
734 new_mnt_entry = lxc_string_replace(
735 old_work, new_work, mnt_entry);
38683db4
CB
736 }
737
738 if (new_mnt_entry) {
739 free(iterator->elem);
740 iterator->elem = strdup(new_mnt_entry);
741 } else if (tmp_mnt_entry) {
742 free(iterator->elem);
743 iterator->elem = strdup(tmp_mnt_entry);
744 }
745
746 free(new_mnt_entry);
747 free(tmp_mnt_entry);
748 }
749
750 fret = 0;
751err:
752 free(cleanpath);
753 return fret;
754}
755
88232d3f
CB
756static int ovl_remount_on_enodev(const char *lower, const char *target,
757 const char *name, unsigned long mountflags,
758 const void *options)
759{
241978fa
CB
760 int ret;
761 ret = mount(lower, target, ovl_name, MS_MGC_VAL | mountflags, options);
762 if (ret < 0 && errno == ENODEV) /* Try other module name. */
88232d3f
CB
763 ret = mount(lower, target,
764 ovl_name == ovl_version[0] ? ovl_version[1]
765 : ovl_version[0],
766 MS_MGC_VAL | mountflags, options);
241978fa 767 return ret;
5c484f79
CB
768}
769
770static char *ovl_detect_name(void)
771{
241978fa 772 FILE *f;
88232d3f 773 char *v = ovl_version[0];
5c484f79
CB
774 char *line = NULL;
775 size_t len = 0;
241978fa
CB
776
777 f = fopen("/proc/filesystems", "r");
5c484f79
CB
778 if (!f)
779 return v;
780
781 while (getline(&line, &len, f) != -1) {
88232d3f
CB
782 if (strcmp(line, "nodev\toverlayfs\n") == 0) {
783 v = ovl_version[1];
5c484f79
CB
784 break;
785 }
786 }
787
788 fclose(f);
789 free(line);
790 return v;
791}
792
17a367d8 793static int ovl_do_rsync(const char *src, const char *dest,
241978fa 794 struct lxc_conf *conf)
5c484f79
CB
795{
796 int ret = -1;
17a367d8 797 struct rsync_data_char rdata = {0};
339de297 798 char cmd_output[PATH_MAX] = {0};
5c484f79 799
17a367d8
CB
800 rdata.src = (char *)src;
801 rdata.dest = (char *)dest;
e0010464 802 if (am_guest_unpriv())
5c05427a
CB
803 ret = userns_exec_full(conf, lxc_rsync_exec_wrapper, &rdata,
804 "lxc_rsync_exec_wrapper");
17a367d8 805 else
241978fa
CB
806 ret = run_command(cmd_output, sizeof(cmd_output),
807 lxc_rsync_exec_wrapper, (void *)&rdata);
17a367d8
CB
808 if (ret < 0)
809 ERROR("Failed to rsync from \"%s\" into \"%s\"%s%s", src, dest,
810 cmd_output[0] != '\0' ? ": " : "",
811 cmd_output[0] != '\0' ? cmd_output : "");
5c484f79
CB
812
813 return ret;
814}