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