]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/storage/loop.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #define __STDC_FORMAT_MACROS
10 #include <linux/loop.h>
15 #include <sys/types.h>
21 #include "memory_utils.h"
23 #include "storage_utils.h"
26 lxc_log_define(loop
, lxc
);
28 static int do_loop_create(const char *path
, uint64_t size
, const char *fstype
);
31 * No idea what the original blockdev will be called, but the copy will be
32 * called $lxcpath/$lxcname/rootdev
34 int loop_clonepaths(struct lxc_storage
*orig
, struct lxc_storage
*new,
35 const char *oldname
, const char *cname
, const char *oldpath
,
36 const char *lxcpath
, int snap
, uint64_t newsize
,
37 struct lxc_conf
*conf
)
39 __do_free
char *srcdev
= NULL
;
40 uint64_t size
= newsize
;
42 char fstype
[100] = "ext4";
45 ERROR("The loop storage driver does not support snapshots");
49 if (!orig
->dest
|| !orig
->src
)
52 len
= strlen(lxcpath
) + strlen(cname
) + strlen("rootdev") + 3;
53 srcdev
= must_realloc(NULL
, len
);
54 ret
= snprintf(srcdev
, len
, "%s/%s/rootdev", lxcpath
, cname
);
55 if (ret
< 0 || ret
>= len
) {
56 ERROR("Failed to create string");
60 new->src
= malloc(len
+ 5);
62 ERROR("Failed to allocate memory");
66 ret
= snprintf(new->src
, (len
+ 5), "loop:%s", srcdev
);
67 if (ret
< 0 || ret
>= (len
+ 5)) {
68 ERROR("Failed to create string");
72 new->dest
= malloc(len
);
74 ERROR("Failed to allocate memory");
78 ret
= snprintf(new->dest
, len
, "%s/%s/rootfs", lxcpath
, cname
);
79 if (ret
< 0 || ret
>= len
) {
80 ERROR("Failed to create string");
84 /* It's tempting to say: if orig->src == loopback and !newsize, then
85 * copy the loopback file. However, we'd have to make sure to correctly
86 * keep holes! So punt for now.
88 if (is_blktype(orig
)) {
90 if (!newsize
&& blk_getsize(orig
, &size
) < 0) {
91 ERROR("Failed to detect size of loop file \"%s\"",
96 /* detect filesystem */
97 if (detect_fs(orig
, fstype
, 100) < 0) {
98 INFO("Failed to detect filesystem type for \"%s\"", orig
->src
);
101 } else if (!newsize
) {
102 size
= DEFAULT_FS_SIZE
;
105 ret
= do_loop_create(srcdev
, size
, fstype
);
107 ERROR("Failed to create loop storage volume \"%s\" with "
108 "filesystem \"%s\" and size \"%" PRIu64
"\"",
109 srcdev
, fstype
, size
);
116 int loop_create(struct lxc_storage
*bdev
, const char *dest
, const char *n
,
117 struct bdev_specs
*specs
, const struct lxc_conf
*conf
)
119 __do_free
char *srcdev
= NULL
;
127 /* <dest> is passed in as <lxcpath>/<lxcname>/rootfs, <srcdev> will
128 * be <lxcpath>/<lxcname>/rootdev, and <src> will be "loop:<srcdev>".
130 len
= strlen(dest
) + 2;
131 srcdev
= must_realloc(NULL
, len
);
133 ret
= snprintf(srcdev
, len
, "%s", dest
);
134 if (ret
< 0 || ret
>= len
) {
135 ERROR("Failed to create string");
139 ret
= sprintf(srcdev
+ len
- 4, "dev");
141 ERROR("Failed to create string");
145 bdev
->src
= malloc(len
+ 5);
147 ERROR("Failed to allocate memory");
151 ret
= snprintf(bdev
->src
, len
+ 5, "loop:%s", srcdev
);
152 if (ret
< 0 || ret
>= len
+ 5) {
153 ERROR("Failed to create string");
159 sz
= DEFAULT_FS_SIZE
;
161 fstype
= specs
->fstype
;
163 fstype
= DEFAULT_FSTYPE
;
165 bdev
->dest
= strdup(dest
);
167 ERROR("Failed to duplicate string \"%s\"", dest
);
171 ret
= mkdir_p(bdev
->dest
, 0755);
173 ERROR("Failed creating directory \"%s\"", bdev
->dest
);
178 ret
= do_loop_create(srcdev
, sz
, fstype
);
180 ERROR("Failed to create loop storage volume \"%s\" with "
181 "filesystem \"%s\" and size \"%" PRIu64
"\"",
189 int loop_destroy(struct lxc_storage
*orig
) {
193 if (strncmp(orig
->src
, "loop:", 5) == 0)
199 bool loop_detect(const char *path
)
204 if (!strncmp(path
, "loop:", 5))
207 ret
= stat(path
, &s
);
211 if (__S_ISTYPE(s
.st_mode
, S_IFREG
))
217 int loop_mount(struct lxc_storage
*bdev
)
220 char loname
[PATH_MAX
];
223 if (strcmp(bdev
->type
, "loop"))
226 if (!bdev
->src
|| !bdev
->dest
)
230 src
= lxc_storage_get_path(bdev
->src
, bdev
->type
);
232 loopfd
= lxc_prepare_loop_dev(src
, loname
, LO_FLAGS_AUTOCLEAR
);
234 ERROR("Failed to prepare loop device for loop file \"%s\"", src
);
237 DEBUG("Prepared loop device \"%s\"", loname
);
239 ret
= mount_unknown_fs(loname
, bdev
->dest
, bdev
->mntopts
);
241 ERROR("Failed to mount rootfs \"%s\" on \"%s\" via loop device \"%s\"",
242 bdev
->src
, bdev
->dest
, loname
);
248 DEBUG("Mounted rootfs \"%s\" on \"%s\" via loop device \"%s\"",
249 bdev
->src
, bdev
->dest
, loname
);
254 int loop_umount(struct lxc_storage
*bdev
)
256 int ret
, saved_errno
;
258 if (strcmp(bdev
->type
, "loop"))
261 if (!bdev
->src
|| !bdev
->dest
)
264 ret
= umount(bdev
->dest
);
266 if (bdev
->lofd
>= 0) {
273 SYSERROR("Failed to umount \"%s\"", bdev
->dest
);
280 static int do_loop_create(const char *path
, uint64_t size
, const char *fstype
)
284 char cmd_output
[PATH_MAX
];
285 const char *cmd_args
[2] = {fstype
, path
};
287 /* create the new loopback file */
288 fd
= creat(path
, S_IRUSR
| S_IWUSR
);
290 SYSERROR("Failed to create new loop file \"%s\"", path
);
294 ret_size
= lseek(fd
, size
, SEEK_SET
);
296 SYSERROR("Failed to seek to set new loop file size for loop "
297 "file \"%s\"", path
);
302 ret
= write(fd
, "1", 1);
304 SYSERROR("Failed creating new loop file \"%s\"", path
);
311 SYSERROR("Failed to create new loop file \"%s\"", path
);
315 /* Create an fs in the loopback file. */
316 ret
= run_command(cmd_output
, sizeof(cmd_output
), do_mkfs_exec_wrapper
,
319 ERROR("Failed to create new filesystem \"%s\" for loop file "
320 "\"%s\": %s", fstype
, path
, cmd_output
);