]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/storage/storage.c
rename am_unpriv to am_host_unpriv
[mirror_lxc.git] / src / lxc / storage / storage.c
CommitLineData
9be53773
SH
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
250b1eec 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
9be53773
SH
22 */
23
9be53773 24#define _GNU_SOURCE
38683db4 25#include <dirent.h>
9be53773 26#include <errno.h>
38683db4
CB
27#include <fcntl.h>
28#include <grp.h>
29#include <inttypes.h>
9be53773 30#include <libgen.h>
38683db4
CB
31#include <sched.h>
32#include <stdint.h>
33#include <stdio.h>
34#include <string.h>
35#include <unistd.h>
38683db4 36#include <sys/mount.h>
76a26f55 37#include <sys/prctl.h>
38683db4
CB
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <sys/wait.h>
f2363e38 41
28d832c4
CB
42#include "aufs.h"
43#include "btrfs.h"
9be53773 44#include "conf.h"
3188197d 45#include "config.h"
28d832c4 46#include "dir.h"
9be53773 47#include "error.h"
38683db4 48#include "log.h"
28d832c4
CB
49#include "loop.h"
50#include "lvm.h"
38683db4 51#include "lxc.h"
e9df7e1a 52#include "lxclock.h"
28d832c4 53#include "nbd.h"
38683db4 54#include "namespace.h"
28d832c4 55#include "overlay.h"
38683db4 56#include "parse.h"
28d832c4
CB
57#include "rbd.h"
58#include "rsync.h"
59#include "storage.h"
f2d5a09d 60#include "storage_utils.h"
38683db4 61#include "utils.h"
28d832c4 62#include "zfs.h"
9be53773 63
bff13ba2 64#ifndef BLKGETSIZE64
eab15c1e 65#define BLKGETSIZE64 _IOR(0x12, 114, size_t)
bff13ba2
SG
66#endif
67
28d832c4 68lxc_log_define(storage, lxc);
9be53773 69
00f0a1f8 70/* aufs */
10bc1861 71static const struct lxc_storage_ops aufs_ops = {
493de765
CB
72 .detect = &aufs_detect,
73 .mount = &aufs_mount,
74 .umount = &aufs_umount,
75 .clone_paths = &aufs_clonepaths,
76 .destroy = &aufs_destroy,
77 .create = &aufs_create,
3ef1df7c
CB
78 .copy = NULL,
79 .snapshot = NULL,
493de765
CB
80 .can_snapshot = true,
81 .can_backup = true,
00f0a1f8
CB
82};
83
2b9cbd53 84/* btrfs */
10bc1861 85static const struct lxc_storage_ops btrfs_ops = {
493de765
CB
86 .detect = &btrfs_detect,
87 .mount = &btrfs_mount,
88 .umount = &btrfs_umount,
89 .clone_paths = &btrfs_clonepaths,
90 .destroy = &btrfs_destroy,
91 .create = &btrfs_create,
3ef1df7c
CB
92 .copy = &btrfs_create_clone,
93 .snapshot = &btrfs_create_snapshot,
493de765
CB
94 .can_snapshot = true,
95 .can_backup = true,
2b9cbd53
CB
96};
97
304b4cf3 98/* dir */
10bc1861 99static const struct lxc_storage_ops dir_ops = {
493de765
CB
100 .detect = &dir_detect,
101 .mount = &dir_mount,
102 .umount = &dir_umount,
103 .clone_paths = &dir_clonepaths,
104 .destroy = &dir_destroy,
105 .create = &dir_create,
3ef1df7c
CB
106 .copy = NULL,
107 .snapshot = NULL,
493de765
CB
108 .can_snapshot = false,
109 .can_backup = true,
9d983015
CB
110};
111
304b4cf3 112/* loop */
10bc1861 113static const struct lxc_storage_ops loop_ops = {
493de765
CB
114 .detect = &loop_detect,
115 .mount = &loop_mount,
116 .umount = &loop_umount,
117 .clone_paths = &loop_clonepaths,
118 .destroy = &loop_destroy,
119 .create = &loop_create,
3ef1df7c
CB
120 .copy = NULL,
121 .snapshot = NULL,
493de765
CB
122 .can_snapshot = false,
123 .can_backup = true,
304b4cf3
CB
124};
125
2b9cbd53 126/* lvm */
10bc1861 127static const struct lxc_storage_ops lvm_ops = {
493de765
CB
128 .detect = &lvm_detect,
129 .mount = &lvm_mount,
130 .umount = &lvm_umount,
131 .clone_paths = &lvm_clonepaths,
132 .destroy = &lvm_destroy,
133 .create = &lvm_create,
3ef1df7c
CB
134 .copy = &lvm_create_clone,
135 .snapshot = &lvm_create_snapshot,
493de765
CB
136 .can_snapshot = true,
137 .can_backup = false,
2b9cbd53
CB
138};
139
bf76c012 140/* nbd */
10bc1861 141const struct lxc_storage_ops nbd_ops = {
493de765
CB
142 .detect = &nbd_detect,
143 .mount = &nbd_mount,
144 .umount = &nbd_umount,
145 .clone_paths = &nbd_clonepaths,
146 .destroy = &nbd_destroy,
147 .create = &nbd_create,
3ef1df7c
CB
148 .copy = NULL,
149 .snapshot = NULL,
493de765
CB
150 .can_snapshot = true,
151 .can_backup = false,
bf76c012
CB
152};
153
2b9cbd53 154/* overlay */
10bc1861 155static const struct lxc_storage_ops ovl_ops = {
493de765
CB
156 .detect = &ovl_detect,
157 .mount = &ovl_mount,
158 .umount = &ovl_umount,
159 .clone_paths = &ovl_clonepaths,
160 .destroy = &ovl_destroy,
161 .create = &ovl_create,
3ef1df7c
CB
162 .copy = NULL,
163 .snapshot = NULL,
493de765
CB
164 .can_snapshot = true,
165 .can_backup = true,
2b9cbd53
CB
166};
167
3ceb2820 168/* rbd */
10bc1861 169static const struct lxc_storage_ops rbd_ops = {
493de765
CB
170 .detect = &rbd_detect,
171 .mount = &rbd_mount,
172 .umount = &rbd_umount,
173 .clone_paths = &rbd_clonepaths,
174 .destroy = &rbd_destroy,
175 .create = &rbd_create,
3ef1df7c
CB
176 .copy = NULL,
177 .snapshot = NULL,
493de765
CB
178 .can_snapshot = false,
179 .can_backup = false,
3ceb2820
CB
180};
181
2b9cbd53 182/* zfs */
10bc1861 183static const struct lxc_storage_ops zfs_ops = {
493de765
CB
184 .detect = &zfs_detect,
185 .mount = &zfs_mount,
186 .umount = &zfs_umount,
187 .clone_paths = &zfs_clonepaths,
188 .destroy = &zfs_destroy,
189 .create = &zfs_create,
3ef1df7c
CB
190 .copy = &zfs_copy,
191 .snapshot = &zfs_snapshot,
493de765
CB
192 .can_snapshot = true,
193 .can_backup = true,
2b9cbd53
CB
194};
195
10bc1861 196struct lxc_storage_type {
cdb4e53a 197 const char *name;
10bc1861 198 const struct lxc_storage_ops *ops;
cdb4e53a
CB
199};
200
10bc1861 201static const struct lxc_storage_type bdevs[] = {
f7ac4459 202 { .name = "dir", .ops = &dir_ops, },
493de765
CB
203 { .name = "zfs", .ops = &zfs_ops, },
204 { .name = "lvm", .ops = &lvm_ops, },
205 { .name = "rbd", .ops = &rbd_ops, },
206 { .name = "btrfs", .ops = &btrfs_ops, },
493de765 207 { .name = "aufs", .ops = &aufs_ops, },
ba115175 208 { .name = "overlay", .ops = &ovl_ops, },
493de765
CB
209 { .name = "overlayfs", .ops = &ovl_ops, },
210 { .name = "loop", .ops = &loop_ops, },
211 { .name = "nbd", .ops = &nbd_ops, },
cdb4e53a
CB
212};
213
10bc1861 214static const size_t numbdevs = sizeof(bdevs) / sizeof(struct lxc_storage_type);
cdb4e53a 215
8a388ed4 216static const struct lxc_storage_type *get_storage_by_name(const char *path,
63c9ffa0 217 const char *type)
38683db4 218{
63c9ffa0 219 int ret;
f2d5a09d 220 size_t i, cmplen;
38683db4 221
63c9ffa0
CB
222 if (type)
223 cmplen = strlen(type);
224 else
8a388ed4 225 cmplen = strcspn(path, ":");
f2d5a09d 226 if (cmplen == 0)
38683db4
CB
227 return NULL;
228
63c9ffa0
CB
229 for (i = 0; i < numbdevs; i++) {
230 if (type)
231 ret = strncmp(bdevs[i].name, type, cmplen);
232 else
8a388ed4 233 ret = strncmp(bdevs[i].name, path, cmplen);
63c9ffa0 234 if (ret == 0)
f2d5a09d 235 break;
63c9ffa0 236 }
38683db4 237
f2d5a09d
CB
238 if (i == numbdevs)
239 return NULL;
240
241 DEBUG("Detected rootfs type \"%s\"", bdevs[i].name);
242 return &bdevs[i];
38683db4
CB
243}
244
8a388ed4 245static const struct lxc_storage_type *storage_query(struct lxc_conf *conf)
9be53773 246{
f2d5a09d 247 size_t i;
10bc1861 248 const struct lxc_storage_type *bdev;
8a388ed4
CB
249 const char *path = conf->rootfs.path;
250 const char *type = conf->rootfs.bdev_type;
eddaaafd 251
8a388ed4 252 bdev = get_storage_by_name(path, type);
f2d5a09d
CB
253 if (bdev)
254 return bdev;
493de765 255
f2d5a09d 256 for (i = 0; i < numbdevs; i++)
8a388ed4 257 if (bdevs[i].ops->detect(path))
f2d5a09d 258 break;
493de765 259
f2d5a09d
CB
260 if (i == numbdevs)
261 return NULL;
493de765 262
f2d5a09d
CB
263 DEBUG("Detected rootfs type \"%s\"", bdevs[i].name);
264 return &bdevs[i];
265}
266
10bc1861 267struct lxc_storage *storage_get(const char *type)
f2d5a09d
CB
268{
269 size_t i;
10bc1861 270 struct lxc_storage *bdev;
f2d5a09d 271
09f6f8c4 272 for (i = 0; i < numbdevs; i++)
f2d5a09d
CB
273 if (strcmp(bdevs[i].name, type) == 0)
274 break;
f2d5a09d
CB
275
276 if (i == numbdevs)
277 return NULL;
278
10bc1861 279 bdev = malloc(sizeof(struct lxc_storage));
f2d5a09d
CB
280 if (!bdev)
281 return NULL;
282
10bc1861 283 memset(bdev, 0, sizeof(struct lxc_storage));
f2d5a09d
CB
284 bdev->ops = bdevs[i].ops;
285 bdev->type = bdevs[i].name;
286
09f6f8c4 287 if (strcmp(bdev->type, "aufs") == 0)
56050adc
CB
288 WARN("The \"aufs\" driver will is deprecated and will soon be "
289 "removed. For similar functionality see the \"overlay\" "
290 "storage driver");
291
f2d5a09d
CB
292 return bdev;
293}
294
10bc1861
CB
295static struct lxc_storage *do_storage_create(const char *dest, const char *type,
296 const char *cname,
297 struct bdev_specs *specs)
f2d5a09d 298{
09f6f8c4 299 int ret;
10bc1861 300 struct lxc_storage *bdev;
f2d5a09d 301
5e78e16a
CB
302 if (!type)
303 type = "dir";
304
10bc1861 305 bdev = storage_get(type);
f2d5a09d
CB
306 if (!bdev)
307 return NULL;
493de765 308
09f6f8c4
CB
309 ret = bdev->ops->create(bdev, dest, cname, specs);
310 if (ret < 0) {
10bc1861 311 storage_put(bdev);
f2d5a09d
CB
312 return NULL;
313 }
314
315 return bdev;
cdb4e53a 316}
9be53773 317
10bc1861 318bool storage_can_backup(struct lxc_conf *conf)
cdb4e53a 319{
cdb4e53a 320 bool ret;
8a388ed4 321 struct lxc_storage *bdev;
d659597e 322
8a388ed4 323 bdev = storage_init(conf);
cdb4e53a
CB
324 if (!bdev)
325 return false;
493de765 326
cdb4e53a 327 ret = bdev->ops->can_backup;
10bc1861 328 storage_put(bdev);
9be53773
SH
329 return ret;
330}
331
10bc1861 332/* If we're not snaphotting, then storage_copy becomes a simple case of mount
cdb4e53a 333 * the original, mount the new, and rsync the contents.
9be53773 334 */
07db51a2 335struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
10bc1861
CB
336 const char *lxcpath, const char *bdevtype,
337 int flags, const char *bdevdata,
07db51a2 338 uint64_t newsize, bool *needs_rdep)
9be53773 339{
cdb4e53a 340 int ret;
41dc7155 341 const char *src_no_prefix;
06d0056c
CB
342 struct lxc_storage *new, *orig;
343 bool snap = (flags & LXC_CLONE_SNAPSHOT);
344 bool maybe_snap = (flags & LXC_CLONE_MAYBE_SNAPSHOT);
345 bool keepbdevtype = (flags & LXC_CLONE_KEEPBDEVTYPE);
07db51a2
CB
346 const char *src = c->lxc_conf->rootfs.path;
347 const char *oldname = c->name;
348 const char *oldpath = c->config_path;
07db51a2 349 char cmd_output[MAXPATHLEN] = {0};
06d0056c 350 struct rsync_data data = {0};
9be53773 351
45b4bb96
CB
352 if (!src) {
353 ERROR("No rootfs specified");
354 return NULL;
355 }
356
6f748a97
CB
357 /* If the container name doesn't show up in the rootfs path, then we
358 * don't know how to come up with a new name.
cdb4e53a 359 */
3324c255 360 if (!strstr(src, oldname)) {
6f748a97
CB
361 ERROR("Original rootfs path \"%s\" does not include container "
362 "name \"%s\"", src, oldname);
cdb4e53a
CB
363 return NULL;
364 }
9be53773 365
8a388ed4 366 orig = storage_init(c->lxc_conf);
cdb4e53a 367 if (!orig) {
06d0056c 368 ERROR("Failed to detect storage driver for \"%s\"", oldname);
cdb4e53a
CB
369 return NULL;
370 }
9be53773 371
cdb4e53a
CB
372 if (!orig->dest) {
373 int ret;
374 size_t len;
375 struct stat sb;
9be53773 376
cdb4e53a
CB
377 len = strlen(oldpath) + strlen(oldname) + strlen("/rootfs") + 2;
378 orig->dest = malloc(len);
379 if (!orig->dest) {
3324c255 380 ERROR("Failed to allocate memory");
07db51a2 381 goto on_error_put_orig;
cdb4e53a 382 }
493de765 383
cdb4e53a
CB
384 ret = snprintf(orig->dest, len, "%s/%s/rootfs", oldpath, oldname);
385 if (ret < 0 || (size_t)ret >= len) {
3324c255 386 ERROR("Failed to create string");
07db51a2 387 goto on_error_put_orig;
cdb4e53a 388 }
493de765 389
6f748a97
CB
390 ret = stat(orig->dest, &sb);
391 if (ret < 0 && errno == ENOENT) {
392 ret = mkdir_p(orig->dest, 0755);
393 if (ret < 0)
eee1a9d7 394 WARN("Failed to create directory \"%s\"", orig->dest);
6f748a97 395 }
cdb4e53a 396 }
9be53773 397
3324c255
CB
398 /* Special case for snapshot. If the caller requested maybe_snapshot and
399 * keepbdevtype and the backing store is directory, then proceed with a
400 * a copy clone rather than returning error.
cdb4e53a
CB
401 */
402 if (maybe_snap && keepbdevtype && !bdevtype && !orig->ops->can_snapshot)
403 snap = false;
404
6f748a97 405 /* If newtype is NULL and snapshot is set, then use overlay. */
70e95c8d 406 if (!bdevtype && !keepbdevtype && snap && !strcmp(orig->type, "dir"))
ba115175 407 bdevtype = "overlay";
cdb4e53a 408
5384e99d 409 if (am_host_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) {
ba115175
CB
410 ERROR("Unsupported snapshot type \"%s\" for unprivileged users",
411 bdevtype ? bdevtype : "(null)");
07db51a2 412 goto on_error_put_orig;
a17b1e65
SG
413 }
414
07db51a2 415 *needs_rdep = false;
70e95c8d
CB
416 if (bdevtype) {
417 if (snap && !strcmp(orig->type, "lvm") &&
418 !lvm_is_thin_volume(orig->src))
419 *needs_rdep = true;
420 else if (!strcmp(bdevtype, "overlay") ||
421 !strcmp(bdevtype, "overlayfs"))
422 *needs_rdep = true;
423 } else {
424 if (!snap && strcmp(oldpath, lxcpath))
425 bdevtype = "dir";
426 else
427 bdevtype = orig->type;
9be53773 428
70e95c8d
CB
429 if (!strcmp(bdevtype, "overlay") ||
430 !strcmp(bdevtype, "overlayfs"))
431 *needs_rdep = true;
432 }
b196516b
CB
433
434 /* get new bdev type */
10bc1861 435 new = storage_get(bdevtype);
cdb4e53a 436 if (!new) {
06d0056c 437 ERROR("Failed to initialize %s storage driver",
493de765 438 bdevtype ? bdevtype : orig->type);
07db51a2 439 goto on_error_put_orig;
cdb4e53a 440 }
06d0056c 441 TRACE("Initialized %s storage driver", new->type);
a17b1e65 442
b196516b 443 /* create new paths */
6f748a97 444 ret = new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
07db51a2 445 snap, newsize, c->lxc_conf);
6f748a97
CB
446 if (ret < 0) {
447 ERROR("Failed creating new paths for clone of \"%s\"", src);
07db51a2 448 goto on_error_put_new;
cdb4e53a 449 }
9be53773 450
70e95c8d
CB
451 /* When we create an overlay snapshot of an overlay container in the
452 * snapshot directory under "<lxcpath>/<name>/snaps/" we don't need to
453 * record a dependency. If we would restore would also fail.
454 */
06d0056c
CB
455 if ((strcmp(new->type, "overlay") == 0 ||
456 strcmp(new->type, "overlayfs") == 0) &&
70e95c8d
CB
457 ret == LXC_CLONE_SNAPSHOT)
458 *needs_rdep = false;
459
6f748a97 460 /* btrfs */
b196516b 461 if (!strcmp(orig->type, "btrfs") && !strcmp(new->type, "btrfs")) {
06d0056c
CB
462 bool bret;
463
b196516b 464 if (snap || btrfs_same_fs(orig->dest, new->dest) == 0)
07db51a2 465 bret = new->ops->snapshot(c->lxc_conf, orig, new, 0);
b196516b 466 else
07db51a2 467 bret = new->ops->copy(c->lxc_conf, orig, new, 0);
b196516b 468 if (!bret)
07db51a2
CB
469 goto on_error_put_new;
470
471 goto on_success;
b196516b
CB
472 }
473
6f748a97 474 /* lvm */
d91e13d8 475 if (!strcmp(orig->type, "lvm") && !strcmp(new->type, "lvm")) {
06d0056c
CB
476 bool bret;
477
d91e13d8 478 if (snap)
06d0056c 479 bret = new->ops->snapshot(c->lxc_conf, orig, new, newsize);
d91e13d8 480 else
07db51a2 481 bret = new->ops->copy(c->lxc_conf, orig, new, newsize);
3ef1df7c 482 if (!bret)
07db51a2
CB
483 goto on_error_put_new;
484
485 goto on_success;
3ef1df7c
CB
486 }
487
488 /* zfs */
489 if (!strcmp(orig->type, "zfs") && !strcmp(new->type, "zfs")) {
06d0056c 490 bool bret;
3ef1df7c
CB
491
492 if (snap)
06d0056c 493 bret = new->ops->snapshot(c->lxc_conf, orig, new, newsize);
3ef1df7c 494 else
07db51a2 495 bret = new->ops->copy(c->lxc_conf, orig, new, newsize);
d91e13d8 496 if (!bret)
07db51a2
CB
497 goto on_error_put_new;
498
499 goto on_success;
d91e13d8
CB
500 }
501
7a9e0f35 502 if (strcmp(bdevtype, "btrfs")) {
6f748a97 503 if (!strcmp(new->type, "overlay") || !strcmp(new->type, "overlayfs"))
7a9e0f35
CB
504 src_no_prefix = ovl_get_lower(new->src);
505 else
506 src_no_prefix = lxc_storage_get_path(new->src, new->type);
507
5384e99d 508 if (am_host_unpriv()) {
07db51a2 509 ret = chown_mapped_root(src_no_prefix, c->lxc_conf);
6f748a97
CB
510 if (ret < 0)
511 WARN("Failed to chown \"%s\"", new->src);
512 }
7a9e0f35 513 }
9be53773 514
cdb4e53a 515 if (snap)
07db51a2 516 goto on_success;
9be53773 517
6f748a97 518 /* rsync the contents from source to target */
db3ac7ba
CB
519 data.orig = orig;
520 data.new = new;
5384e99d 521 if (am_host_unpriv())
5c05427a
CB
522 ret = userns_exec_full(c->lxc_conf,
523 lxc_storage_rsync_exec_wrapper, &data,
524 "lxc_storage_rsync_exec_wrapper");
07db51a2 525 else
db3ac7ba 526 ret = run_command(cmd_output, sizeof(cmd_output),
17a367d8 527 lxc_storage_rsync_exec_wrapper, (void *)&data);
07db51a2
CB
528 if (ret < 0) {
529 ERROR("Failed to rsync from \"%s\" into \"%s\"%s%s", orig->dest,
530 new->dest,
531 cmd_output[0] != '\0' ? ": " : "",
532 cmd_output[0] != '\0' ? cmd_output : "");
533 goto on_error_put_new;
9be53773
SH
534 }
535
07db51a2 536on_success:
10bc1861 537 storage_put(orig);
07db51a2 538
db3ac7ba 539 return new;
cdb4e53a 540
07db51a2 541on_error_put_new:
10bc1861 542 storage_put(new);
07db51a2
CB
543
544on_error_put_orig:
545 storage_put(orig);
546
cdb4e53a
CB
547 return NULL;
548}
549
10bc1861 550/* Create a backing store for a container.
cdb4e53a
CB
551 * If successful, return a struct bdev *, with the bdev mounted and ready
552 * for use. Before completing, the caller will need to call the
10bc1861 553 * umount operation and storage_put().
cdb4e53a
CB
554 * @dest: the mountpoint (i.e. /var/lib/lxc/$name/rootfs)
555 * @type: the bdevtype (dir, btrfs, zfs, rbd, etc)
556 * @cname: the container name
557 * @specs: details about the backing store to create, like fstype
558 */
10bc1861
CB
559struct lxc_storage *storage_create(const char *dest, const char *type,
560 const char *cname, struct bdev_specs *specs)
9be53773 561{
e9e29a33 562 int ret;
10bc1861 563 struct lxc_storage *bdev;
cdb4e53a 564 char *best_options[] = {"btrfs", "zfs", "lvm", "dir", "rbd", NULL};
9be53773 565
cdb4e53a 566 if (!type)
10bc1861 567 return do_storage_create(dest, "dir", cname, specs);
cdb4e53a 568
e9e29a33
CB
569 ret = strcmp(type, "best");
570 if (ret == 0) {
cdb4e53a 571 int i;
10bc1861
CB
572 /* Try for the best backing store type, according to our
573 * opinionated preferences.
574 */
cdb4e53a 575 for (i = 0; best_options[i]; i++) {
e9e29a33 576 bdev = do_storage_create(dest, best_options[i], cname, specs);
10bc1861 577 if (bdev)
cdb4e53a
CB
578 return bdev;
579 }
493de765 580
10bc1861 581 return NULL;
9be53773 582 }
9be53773 583
10bc1861 584 /* -B lvm,dir */
e9e29a33
CB
585 if (strchr(type, ',')) {
586 char *dup, *token;
587 char *saveptr = NULL;
588
589 dup = alloca(strlen(type) + 1);
cdb4e53a
CB
590 strcpy(dup, type);
591 for (token = strtok_r(dup, ",", &saveptr); token;
493de765 592 token = strtok_r(NULL, ",", &saveptr)) {
e9e29a33
CB
593 bdev = do_storage_create(dest, token, cname, specs);
594 if (bdev)
cdb4e53a
CB
595 return bdev;
596 }
597 }
598
10bc1861 599 return do_storage_create(dest, type, cname, specs);
9be53773
SH
600}
601
10bc1861 602bool storage_destroy(struct lxc_conf *conf)
9be53773 603{
10bc1861 604 struct lxc_storage *r;
cdb4e53a 605 bool ret = false;
ed05aac8 606 int destroy_rv = 0;
9be53773 607
8a388ed4 608 r = storage_init(conf);
cdb4e53a
CB
609 if (!r)
610 return ret;
611
ed05aac8
MM
612 destroy_rv = r->ops->destroy(r);
613 if (destroy_rv == 0)
cdb4e53a 614 ret = true;
cdb4e53a 615
10bc1861 616 storage_put(r);
cdb4e53a
CB
617 return ret;
618}
619
8a388ed4 620struct lxc_storage *storage_init(struct lxc_conf *conf)
cdb4e53a 621{
10bc1861
CB
622 struct lxc_storage *bdev;
623 const struct lxc_storage_type *q;
8a388ed4
CB
624 const char *src = conf->rootfs.path;
625 const char *dst = conf->rootfs.mount;
626 const char *mntopts = conf->rootfs.options;
cdb4e53a 627
17a367d8
CB
628 BUILD_BUG_ON(LXC_STORAGE_INTERNAL_OVERLAY_RESTORE <= LXC_CLONE_MAXFLAGS);
629
cdb4e53a 630 if (!src)
9be53773 631 return NULL;
cdb4e53a 632
8a388ed4 633 q = storage_query(conf);
cdb4e53a 634 if (!q)
9be53773 635 return NULL;
cdb4e53a 636
10bc1861 637 bdev = malloc(sizeof(struct lxc_storage));
cdb4e53a 638 if (!bdev)
9be53773 639 return NULL;
493de765 640
10bc1861 641 memset(bdev, 0, sizeof(struct lxc_storage));
8a388ed4 642
cdb4e53a
CB
643 bdev->ops = q->ops;
644 bdev->type = q->name;
8a388ed4 645
cdb4e53a
CB
646 if (mntopts)
647 bdev->mntopts = strdup(mntopts);
8a388ed4 648
cdb4e53a
CB
649 if (src)
650 bdev->src = strdup(src);
8a388ed4 651
cdb4e53a
CB
652 if (dst)
653 bdev->dest = strdup(dst);
8a388ed4 654
cdb4e53a
CB
655 if (strcmp(bdev->type, "nbd") == 0)
656 bdev->nbd_idx = conf->nbd_idx;
657
8a388ed4 658 if (strcmp(bdev->type, "aufs") == 0)
56050adc
CB
659 WARN("The \"aufs\" driver will is deprecated and will soon be "
660 "removed. For similar functionality see the \"overlay\" "
661 "storage driver");
662
cdb4e53a
CB
663 return bdev;
664}
665
068aa488 666bool storage_is_dir(struct lxc_conf *conf)
cdb4e53a 667{
10bc1861 668 struct lxc_storage *orig;
068aa488 669 char *type = conf->rootfs.bdev_type;
10bc1861
CB
670 bool bret = false;
671
068aa488
CB
672 if (type)
673 return (strcmp(type, "dir") == 0);
674
8a388ed4 675 orig = storage_init(conf);
cdb4e53a 676 if (!orig)
10bc1861
CB
677 return bret;
678
cdb4e53a 679 if (strcmp(orig->type, "dir") == 0)
10bc1861
CB
680 bret = true;
681
682 storage_put(orig);
683 return bret;
cdb4e53a
CB
684}
685
10bc1861 686void storage_put(struct lxc_storage *bdev)
cdb4e53a
CB
687{
688 free(bdev->mntopts);
689 free(bdev->src);
690 free(bdev->dest);
691 free(bdev);
692}
693
cdb4e53a
CB
694bool rootfs_is_blockdev(struct lxc_conf *conf)
695{
10bc1861 696 const struct lxc_storage_type *q;
cdb4e53a
CB
697 struct stat st;
698 int ret;
699
700 if (!conf->rootfs.path || strcmp(conf->rootfs.path, "/") == 0 ||
493de765 701 strlen(conf->rootfs.path) == 0)
cdb4e53a
CB
702 return false;
703
704 ret = stat(conf->rootfs.path, &st);
705 if (ret == 0 && S_ISBLK(st.st_mode))
706 return true;
493de765 707
8a388ed4 708 q = storage_query(conf);
cdb4e53a
CB
709 if (!q)
710 return false;
493de765 711
cdb4e53a 712 if (strcmp(q->name, "lvm") == 0 ||
493de765 713 strcmp(q->name, "loop") == 0 ||
f83dd99e
CB
714 strcmp(q->name, "nbd") == 0 ||
715 strcmp(q->name, "rbd") == 0 ||
716 strcmp(q->name, "zfs") == 0)
cdb4e53a 717 return true;
493de765 718
cdb4e53a
CB
719 return false;
720}
4f25fd38 721
41dc7155 722const char *lxc_storage_get_path(char *src, const char *prefix)
4f25fd38
CB
723{
724 size_t prefix_len;
725
726 prefix_len = strlen(prefix);
727 if (!strncmp(src, prefix, prefix_len) && (*(src + prefix_len) == ':'))
728 return (src + prefix_len + 1);
729
730 return src;
731}