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