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