]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/storage/overlay.c
overlay: correctly handle dependency tracking
[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);
10bc1861 46static int ovl_do_rsync(struct lxc_storage *orig, struct lxc_storage *new,
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);
38683db4
CB
295 free(osrc);
296 free(ndelta);
241978fa 297 if (ret < 0 || (size_t)ret >= len) {
ba115175
CB
298 ERROR("Failed to create string");
299 return -1;
241978fa 300 }
38683db4 301
70e95c8d
CB
302 ret = ovl_do_rsync(orig, new, conf);
303 if (ret < 0)
304 return -1;
305
306 /* When we create an overlay snapshot of an overlay container in
307 * the snapshot directory under "<lxcpath>/<name>/snaps/" we
308 * don't need to record a dependency. If we would restore would
309 * also fail.
310 */
311 clean_old_path = lxc_deslashify(oldpath);
312 if (!clean_old_path)
313 return -1;
314
315 clean_new_path = lxc_deslashify(lxcpath);
316 if (!clean_new_path) {
317 free(clean_old_path);
318 return -1;
319 }
320
321 s1 = strrchr(clean_old_path, '/');
322 if (!s1) {
323 ERROR("Failed to detect \"/\" in string \"%s\"", s1);
324 free(clean_old_path);
325 free(clean_new_path);
326 return -1;
327 }
328
329 s2 = strrchr(clean_new_path, '/');
330 if (!s2) {
331 ERROR("Failed to detect \"/\" in string \"%s\"", s2);
332 free(clean_old_path);
333 free(clean_new_path);
334 return -1;
335 }
336
337 if (!strncmp(s1, "/snaps", sizeof("/snaps") - 1)) {
338 s1 = clean_new_path;
339 s2 = clean_old_path;
340 s3 = (char *)cname;
341 name_len = strlen(cname);
342 len = strlen(clean_new_path);
343 } else if (!strncmp(s2, "/snaps", sizeof("/snaps") - 1)) {
344 s1 = clean_old_path;
345 s2 = clean_new_path;
346 s3 = (char *)oldname;
347 name_len = strlen(oldname);
348 len = strlen(clean_old_path);
349 } else {
350 free(clean_old_path);
351 free(clean_new_path);
352 return 0;
353 }
354
355 if (!strncmp(s1, s2, len)) {
356 char *tmp;
357
358 tmp = (char *)(s2 + len + 1);
359 if (*tmp == '\0') {
360 free(clean_old_path);
361 free(clean_new_path);
362 return 0;
363 }
364
365 name_len = strlen(s3);
366 if (strncmp(s3, tmp, name_len)) {
367 free(clean_old_path);
368 free(clean_new_path);
369 return 0;
370 }
371
372 tmp += name_len + 1;
373 if (*tmp == '\0') {
374 free(clean_old_path);
375 free(clean_new_path);
376 return 0;
377 }
378
379 if (!strncmp(tmp, "snaps", sizeof("snaps") - 1)) {
380 free(clean_old_path);
381 free(clean_new_path);
382 return LXC_CLONE_SNAPSHOT;
383 }
384 }
385
386 free(clean_old_path);
387 free(clean_new_path);
388 return 0;
38683db4 389 } else {
ba115175 390 ERROR("overlay clone of %s container is not yet supported",
5c484f79 391 orig->type);
241978fa 392 /* Note, supporting this will require ovl_mount supporting
5c484f79
CB
393 * mounting of the underlay. No big deal, just needs to be done.
394 */
38683db4
CB
395 return -1;
396 }
397
398 return 0;
399}
400
241978fa
CB
401/* To say "lxc-create -t ubuntu -n o1 -B overlay" means you want
402 * "<lxcpath>/<lxcname>/rootfs" to have the created container, while all changes
403 * after starting the container are written to "<lxcpath>/<lxcname>/delta0".
38683db4 404 */
10bc1861 405int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n,
241978fa 406 struct bdev_specs *specs)
38683db4
CB
407{
408 char *delta;
241978fa
CB
409 int ret;
410 size_t len, newlen;
38683db4 411
241978fa
CB
412 len = strlen(dest);
413 if (len < 8 || strcmp(dest + len - 7, "/rootfs")) {
414 ERROR("Failed to detect \"/rootfs\" in \"%s\"", dest);
38683db4 415 return -1;
241978fa 416 }
38683db4 417
241978fa
CB
418 bdev->dest = strdup(dest);
419 if (!bdev->dest) {
420 ERROR("Failed to duplicate string \"%s\"", dest);
38683db4
CB
421 return -1;
422 }
423
241978fa
CB
424 delta = malloc(len + 1);
425 if (!delta) {
426 ERROR("Failed to allocate memory");
427 return -1;
428 }
429
430 strncpy(delta, dest, len);
431 strncpy(delta + len - 6, "delta0", sizeof("delta0") - 1);
432 delta[len + sizeof("delta0")] = '\0';
38683db4 433
241978fa
CB
434 ret = mkdir_p(delta, 0755);
435 if (ret < 0) {
436 SYSERROR("Failed to create directory \"%s\"", delta);
437 free(delta);
38683db4
CB
438 return -1;
439 }
440
241978fa 441 /* overlay:lower:upper */
ba115175 442 newlen = (2 * len) + strlen("overlay:") + 2;
38683db4
CB
443 bdev->src = malloc(newlen);
444 if (!bdev->src) {
241978fa
CB
445 ERROR("Failed to allocate memory");
446 free(delta);
38683db4
CB
447 return -1;
448 }
241978fa 449
ba115175 450 ret = snprintf(bdev->src, newlen, "overlay:%s:%s", dest, delta);
241978fa
CB
451 if (ret < 0 || (size_t)ret >= newlen) {
452 ERROR("Failed to create string");
453 free(delta);
38683db4 454 return -1;
241978fa 455 }
38683db4 456
241978fa
CB
457 ret = mkdir_p(bdev->dest, 0755);
458 if (ret < 0) {
459 SYSERROR("Failed to create directory \"%s\"", bdev->dest);
460 free(delta);
38683db4
CB
461 return -1;
462 }
463
241978fa 464 free(delta);
38683db4
CB
465 return 0;
466}
467
10bc1861 468int ovl_destroy(struct lxc_storage *orig)
5c484f79 469{
241978fa 470 bool ovl;
ba115175 471 char *upper = orig->src;
5c484f79 472
241978fa 473 ovl = !strncmp(upper, "overlay:", 8);
ba115175 474 if (!ovl && strncmp(upper, "overlayfs:", 10))
5c484f79 475 return -22;
ba115175 476
241978fa
CB
477 if (ovl)
478 upper += 8;
479 else
480 upper += 10;
ba115175
CB
481
482 upper = strchr(upper, ':');
5c484f79
CB
483 if (!upper)
484 return -22;
485 upper++;
ba115175 486
5c484f79
CB
487 return lxc_rmdir_onedev(upper, NULL);
488}
489
3d2ae1e2 490bool ovl_detect(const char *path)
5c484f79 491{
f7ac4459 492 if (!strncmp(path, "overlayfs:", 10))
3d2ae1e2 493 return true;
f7ac4459
CB
494
495 if (!strncmp(path, "overlay:", 8))
3d2ae1e2 496 return true;
f7ac4459 497
3d2ae1e2 498 return false;
5c484f79
CB
499}
500
10bc1861 501int ovl_mount(struct lxc_storage *bdev)
5c484f79 502{
9208af16 503 char *tmp, *options, *dup, *lower, *upper;
5c484f79
CB
504 char *options_work, *work, *lastslash;
505 int lastslashidx;
241978fa 506 size_t len, len2;
5c484f79
CB
507 unsigned long mntflags;
508 char *mntdata;
509 int ret, ret2;
510
ba115175 511 if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
5c484f79 512 return -22;
ba115175 513
5c484f79
CB
514 if (!bdev->src || !bdev->dest)
515 return -22;
516
517 if (!ovl_name)
518 ovl_name = ovl_detect_name();
519
241978fa
CB
520 /* Separately mount it first:
521 * mount -t overlay * -o upperdir=${upper},lowerdir=${lower} lower dest
5c484f79 522 */
241978fa
CB
523 dup = strdup(bdev->src);
524 if (!dup) {
525 ERROR("Failed to allocate memory");
526 return -1;
527 }
528
9208af16 529 /* support multiple lower layers */
241978fa
CB
530 lower = strstr(dup, ":/");
531 if (!lower) {
532 ERROR("Failed to detect \":/\" in string \"%s\"", dup);
533 free(dup);
534 return -22;
535 }
536
9208af16
CB
537 lower++;
538 upper = lower;
539 while ((tmp = strstr(++upper, ":/"))) {
540 upper = tmp;
541 }
241978fa
CB
542
543 upper--;
544 if (upper == lower) {
545 free(dup);
5c484f79 546 return -22;
241978fa 547 }
5c484f79
CB
548 *upper = '\0';
549 upper++;
550
241978fa
CB
551 /* if delta doesn't yet exist, create it */
552 ret = mkdir_p(upper, 0755) < 0;
553 if (ret < 0 && errno != EEXIST) {
554 SYSERROR("Failed to create directory \"%s\"", upper);
555 free(dup);
5c484f79 556 return -22;
241978fa 557 }
5c484f79 558
241978fa 559 /* overlayfs.v22 or higher needs workdir option:
5c484f79
CB
560 * if upper is
561 * /var/lib/lxc/c2/delta0
562 * then workdir is
563 * /var/lib/lxc/c2/olwork
564 */
565 lastslash = strrchr(upper, '/');
241978fa
CB
566 if (!lastslash) {
567 ERROR("Failed to detect \"/\" in string \"%s\"", upper);
568 free(dup);
5c484f79 569 return -22;
241978fa
CB
570 }
571
5c484f79
CB
572 lastslash++;
573 lastslashidx = lastslash - upper;
574
241978fa
CB
575 work = malloc(lastslashidx + 7);
576 if (!work) {
577 ERROR("Failed to allocate memory");
578 free(dup);
579 return -22;
580 }
5c484f79 581
241978fa
CB
582 strncpy(work, upper, lastslashidx + 1);
583 strncpy(work + lastslashidx, "olwork", sizeof("olwork") - 1);
584 work[lastslashidx + sizeof("olwork")] = '\0';
585
586 ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata);
587 if (ret < 0) {
588 ERROR("Failed to parse mount options");
5c484f79 589 free(mntdata);
241978fa
CB
590 free(dup);
591 free(work);
5c484f79
CB
592 return -22;
593 }
594
241978fa
CB
595 ret = mkdir_p(work, 0755);
596 if (ret < 0 && errno != EEXIST) {
597 SYSERROR("Failed to create directory \"%s\"", work);
5c484f79 598 free(mntdata);
241978fa
CB
599 free(dup);
600 free(work);
5c484f79
CB
601 return -22;
602 }
603
604 /*
605 * TODO:
606 * We should check whether bdev->src is a blockdev but for now only
607 * support overlays of a basic directory
608 */
609
610 if (mntdata) {
241978fa
CB
611 len = strlen(lower) + strlen(upper) +
612 strlen("upperdir=,lowerdir=,") + strlen(mntdata) + 1;
5c484f79 613 options = alloca(len);
241978fa
CB
614 ret = snprintf(options, len, "upperdir=%s,lowerdir=%s,%s",
615 upper, lower, mntdata);
5c484f79 616
241978fa
CB
617 len2 = strlen(lower) + strlen(upper) + strlen(work) +
618 strlen("upperdir=,lowerdir=,workdir=") +
619 strlen(mntdata) + 1;
5c484f79 620 options_work = alloca(len2);
241978fa
CB
621 ret2 = snprintf(options, len2,
622 "upperdir=%s,lowerdir=%s,workdir=%s,%s", upper,
623 lower, work, mntdata);
5c484f79 624 } else {
241978fa
CB
625 len = strlen(lower) + strlen(upper) +
626 strlen("upperdir=,lowerdir=") + 1;
5c484f79 627 options = alloca(len);
241978fa
CB
628 ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper,
629 lower);
5c484f79 630
241978fa
CB
631 len2 = strlen(lower) + strlen(upper) + strlen(work) +
632 strlen("upperdir=,lowerdir=,workdir=") + 1;
5c484f79 633 options_work = alloca(len2);
241978fa
CB
634 ret2 = snprintf(options_work, len2,
635 "upperdir=%s,lowerdir=%s,workdir=%s", upper,
636 lower, work);
5c484f79
CB
637 }
638
639 if (ret < 0 || ret >= len || ret2 < 0 || ret2 >= len2) {
241978fa 640 ERROR("Failed to create string");
5c484f79 641 free(mntdata);
241978fa
CB
642 free(dup);
643 free(work);
5c484f79
CB
644 return -1;
645 }
646
241978fa 647 /* Assume we need a workdir as we are on a overlay version >= v22. */
88232d3f
CB
648 ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
649 MS_MGC_VAL | mntflags, options_work);
5c484f79 650 if (ret < 0) {
241978fa
CB
651 INFO("Failed to mount \"%s\" on \"%s\" with options \"%s\". "
652 "Retrying without workdir: %s",
88232d3f 653 lower, bdev->dest, options_work, strerror(errno));
5c484f79 654
241978fa
CB
655 /* Assume we cannot use a workdir as we are on a version <= v21.
656 */
88232d3f 657 ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
241978fa 658 MS_MGC_VAL | mntflags, options);
5c484f79 659 if (ret < 0)
241978fa
CB
660 SYSERROR("Failed to mount \"%s\" on \"%s\" with "
661 "options \"%s\": %s",
662 lower, bdev->dest, options, strerror(errno));
5c484f79 663 else
241978fa 664 INFO("Mounted \"%s\" on \"%s\" with options \"%s\"",
88232d3f 665 lower, bdev->dest, options);
5c484f79 666 } else {
241978fa 667 INFO("Mounted \"%s\" on \"%s\" with options \"%s\"", lower,
88232d3f 668 bdev->dest, options_work);
5c484f79 669 }
241978fa
CB
670
671 free(dup);
672 free(work);
5c484f79
CB
673 return ret;
674}
675
10bc1861 676int ovl_umount(struct lxc_storage *bdev)
5c484f79 677{
241978fa
CB
678 int ret;
679
ba115175 680 if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
5c484f79 681 return -22;
ba115175 682
5c484f79
CB
683 if (!bdev->src || !bdev->dest)
684 return -22;
ba115175 685
241978fa
CB
686 ret = umount(bdev->dest);
687 if (ret < 0)
688 SYSERROR("Failed to unmount \"%s\"", bdev->dest);
689 else
690 TRACE("Unmounted \"%s\"", bdev->dest);
691
692 return ret;
5c484f79
CB
693}
694
ba115175
CB
695char *ovl_get_lower(const char *rootfs_path)
696{
697 char *s1;
241978fa 698
ba115175
CB
699 s1 = strstr(rootfs_path, ":/");
700 if (!s1)
701 return NULL;
702 s1++;
703
704 s1 = strstr(s1, ":/");
705 if (!s1)
706 return NULL;
707 s1++;
708
709 return s1;
710}
711
5c484f79
CB
712char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen)
713{
714 char *rootfsdir = NULL;
715 char *s1 = NULL;
716 char *s2 = NULL;
717 char *s3 = NULL;
718
719 if (!rootfs_path || !rootfslen)
720 return NULL;
721
722 s1 = strdup(rootfs_path);
723 if (!s1)
724 return NULL;
725
241978fa
CB
726 s2 = strstr(s1, ":/");
727 if (s2) {
5c484f79
CB
728 s2 = s2 + 1;
729 if ((s3 = strstr(s2, ":/")))
730 *s3 = '\0';
731 rootfsdir = strdup(s2);
732 if (!rootfsdir) {
733 free(s1);
734 return NULL;
735 }
736 }
737
738 if (!rootfsdir)
739 rootfsdir = s1;
740 else
741 free(s1);
742
743 *rootfslen = strlen(rootfsdir);
744
745 return rootfsdir;
746}
747
748int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
749 const char *lxc_name, const char *lxc_path)
750{
751 char lxcpath[MAXPATHLEN];
241978fa
CB
752 char **opts;
753 int ret;
754 size_t arrlen, dirlen, i, len, rootfslen;
5c484f79 755 int fret = -1;
241978fa
CB
756 char *rootfs_dir = NULL, *rootfs_path = NULL, *upperdir = NULL,
757 *workdir = NULL;
5c484f79 758
9769034f
CB
759 /* When rootfs == NULL we have a container without a rootfs. */
760 if (rootfs && rootfs->path)
761 rootfs_path = rootfs->path;
5c484f79
CB
762
763 opts = lxc_string_split(mntent->mnt_opts, ',');
764 if (opts)
765 arrlen = lxc_array_len((void **)opts);
766 else
767 goto err;
768
769 for (i = 0; i < arrlen; i++) {
241978fa
CB
770 if (strstr(opts[i], "upperdir=") &&
771 (strlen(opts[i]) > (len = strlen("upperdir="))))
5c484f79 772 upperdir = opts[i] + len;
241978fa
CB
773 else if (strstr(opts[i], "workdir=") &&
774 (strlen(opts[i]) > (len = strlen("workdir="))))
5c484f79
CB
775 workdir = opts[i] + len;
776 }
777
9769034f 778 if (rootfs_path) {
241978fa
CB
779 ret =
780 snprintf(lxcpath, MAXPATHLEN, "%s/%s", lxc_path, lxc_name);
9769034f
CB
781 if (ret < 0 || ret >= MAXPATHLEN)
782 goto err;
5c484f79 783
241978fa
CB
784 rootfs_dir = ovl_get_rootfs(rootfs_path, &rootfslen);
785 if (!rootfs_dir)
9769034f 786 goto err;
5c484f79 787
9769034f
CB
788 dirlen = strlen(lxcpath);
789 }
5c484f79
CB
790
791 /*
792 * We neither allow users to create upperdirs and workdirs outside the
793 * containerdir nor inside the rootfs. The latter might be debatable.
9769034f 794 * When we have a container without a rootfs we skip the checks.
5c484f79 795 */
9769034f
CB
796 ret = 0;
797 if (upperdir) {
798 if (!rootfs_path)
799 ret = mkdir_p(upperdir, 0755);
241978fa
CB
800 else if (!strncmp(upperdir, lxcpath, dirlen) &&
801 strncmp(upperdir, rootfs_dir, rootfslen))
9769034f
CB
802 ret = mkdir_p(upperdir, 0755);
803 if (ret < 0)
241978fa
CB
804 WARN("Failed to create directory \"%s\": %s", upperdir,
805 strerror(errno));
9769034f
CB
806 }
807
808 ret = 0;
809 if (workdir) {
810 if (!rootfs_path)
811 ret = mkdir_p(workdir, 0755);
241978fa
CB
812 else if (!strncmp(workdir, lxcpath, dirlen) &&
813 strncmp(workdir, rootfs_dir, rootfslen))
9769034f
CB
814 ret = mkdir_p(workdir, 0755);
815 if (ret < 0)
241978fa
CB
816 WARN("Failed to create directory \"%s\": %s", workdir,
817 strerror(errno));
9769034f 818 }
5c484f79
CB
819
820 fret = 0;
821
822err:
241978fa 823 free(rootfs_dir);
5c484f79
CB
824 lxc_free_array((void **)opts, free);
825 return fret;
826}
827
241978fa 828/* To be called from lxcapi_clone() in lxccontainer.c: When we clone a container
38683db4
CB
829 * with overlay lxc.mount.entry entries we need to update absolute paths for
830 * upper- and workdir. This update is done in two locations:
831 * lxc_conf->unexpanded_config and lxc_conf->mount_list. Both updates are done
241978fa
CB
832 * independent of each other since lxc_conf->mountlist may contain more mount
833 * entries (e.g. from other included files) than lxc_conf->unexpanded_config.
38683db4 834 */
83e79752
CB
835int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
836 const char *lxc_name, const char *newpath,
837 const char *newname)
38683db4 838{
241978fa
CB
839 char new_upper[MAXPATHLEN], new_work[MAXPATHLEN], old_upper[MAXPATHLEN],
840 old_work[MAXPATHLEN];
84760c11 841 size_t i;
241978fa
CB
842 struct lxc_list *iterator;
843 char *cleanpath = NULL;
38683db4
CB
844 int fret = -1;
845 int ret = 0;
38683db4
CB
846 const char *ovl_dirs[] = {"br", "upperdir", "workdir"};
847
848 cleanpath = strdup(newpath);
849 if (!cleanpath)
850 goto err;
851
852 remove_trailing_slashes(cleanpath);
853
5c484f79
CB
854 /*
855 * We have to update lxc_conf->unexpanded_config separately from
856 * lxc_conf->mount_list.
857 */
38683db4
CB
858 for (i = 0; i < sizeof(ovl_dirs) / sizeof(ovl_dirs[0]); i++) {
859 if (!clone_update_unexp_ovl_paths(lxc_conf, lxc_path, newpath,
860 lxc_name, newname,
861 ovl_dirs[i]))
862 goto err;
863 }
864
241978fa
CB
865 ret =
866 snprintf(old_work, MAXPATHLEN, "workdir=%s/%s", lxc_path, lxc_name);
38683db4
CB
867 if (ret < 0 || ret >= MAXPATHLEN)
868 goto err;
869
241978fa
CB
870 ret =
871 snprintf(new_work, MAXPATHLEN, "workdir=%s/%s", cleanpath, newname);
38683db4
CB
872 if (ret < 0 || ret >= MAXPATHLEN)
873 goto err;
874
875 lxc_list_for_each(iterator, &lxc_conf->mount_list) {
241978fa
CB
876 char *mnt_entry = NULL, *new_mnt_entry = NULL, *tmp = NULL,
877 *tmp_mnt_entry = NULL;
878
38683db4
CB
879 mnt_entry = iterator->elem;
880
881 if (strstr(mnt_entry, "overlay"))
882 tmp = "upperdir";
883 else if (strstr(mnt_entry, "aufs"))
884 tmp = "br";
885
886 if (!tmp)
887 continue;
888
241978fa
CB
889 ret = snprintf(old_upper, MAXPATHLEN, "%s=%s/%s", tmp, lxc_path,
890 lxc_name);
38683db4
CB
891 if (ret < 0 || ret >= MAXPATHLEN)
892 goto err;
893
241978fa
CB
894 ret = snprintf(new_upper, MAXPATHLEN, "%s=%s/%s", tmp,
895 cleanpath, newname);
38683db4
CB
896 if (ret < 0 || ret >= MAXPATHLEN)
897 goto err;
898
899 if (strstr(mnt_entry, old_upper)) {
241978fa
CB
900 tmp_mnt_entry =
901 lxc_string_replace(old_upper, new_upper, mnt_entry);
38683db4
CB
902 }
903
904 if (strstr(mnt_entry, old_work)) {
905 if (tmp_mnt_entry)
241978fa
CB
906 new_mnt_entry = lxc_string_replace(
907 old_work, new_work, tmp_mnt_entry);
38683db4 908 else
241978fa
CB
909 new_mnt_entry = lxc_string_replace(
910 old_work, new_work, mnt_entry);
38683db4
CB
911 }
912
913 if (new_mnt_entry) {
914 free(iterator->elem);
915 iterator->elem = strdup(new_mnt_entry);
916 } else if (tmp_mnt_entry) {
917 free(iterator->elem);
918 iterator->elem = strdup(tmp_mnt_entry);
919 }
920
921 free(new_mnt_entry);
922 free(tmp_mnt_entry);
923 }
924
925 fret = 0;
926err:
927 free(cleanpath);
928 return fret;
929}
930
88232d3f
CB
931static int ovl_remount_on_enodev(const char *lower, const char *target,
932 const char *name, unsigned long mountflags,
933 const void *options)
934{
241978fa
CB
935 int ret;
936 ret = mount(lower, target, ovl_name, MS_MGC_VAL | mountflags, options);
937 if (ret < 0 && errno == ENODEV) /* Try other module name. */
88232d3f
CB
938 ret = mount(lower, target,
939 ovl_name == ovl_version[0] ? ovl_version[1]
940 : ovl_version[0],
941 MS_MGC_VAL | mountflags, options);
241978fa 942 return ret;
5c484f79
CB
943}
944
945static char *ovl_detect_name(void)
946{
241978fa 947 FILE *f;
88232d3f 948 char *v = ovl_version[0];
5c484f79
CB
949 char *line = NULL;
950 size_t len = 0;
241978fa
CB
951
952 f = fopen("/proc/filesystems", "r");
5c484f79
CB
953 if (!f)
954 return v;
955
956 while (getline(&line, &len, f) != -1) {
88232d3f
CB
957 if (strcmp(line, "nodev\toverlayfs\n") == 0) {
958 v = ovl_version[1];
5c484f79
CB
959 break;
960 }
961 }
962
963 fclose(f);
964 free(line);
965 return v;
966}
967
10bc1861 968static int ovl_do_rsync(struct lxc_storage *orig, struct lxc_storage *new,
241978fa 969 struct lxc_conf *conf)
5c484f79
CB
970{
971 int ret = -1;
241978fa
CB
972 struct rsync_data rdata = {0, 0};
973 char cmd_output[MAXPATHLEN] = {0};
5c484f79
CB
974
975 rdata.orig = orig;
976 rdata.new = new;
241978fa
CB
977 if (am_unpriv()) {
978 ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &rdata,
979 "lxc_rsync_exec_wrapper");
980 if (ret < 0)
981 ERROR("Failed to rsync from \"%s\" into \"%s\"",
982 orig->dest, new->dest);
983 } else {
984 ret = run_command(cmd_output, sizeof(cmd_output),
985 lxc_rsync_exec_wrapper, (void *)&rdata);
986 if (ret < 0)
987 ERROR("Failed to rsync from \"%s\" into \"%s\": %s",
988 orig->dest, new->dest, cmd_output);
989 }
5c484f79
CB
990
991 return ret;
992}