]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/storage/loop.c
storage: s/MAXPATHLEN/PATH_MAX/g
[mirror_lxc.git] / src / lxc / storage / loop.c
CommitLineData
304b4cf3
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
d38dd64a
CB
24#ifndef _GNU_SOURCE
25#define _GNU_SOURCE 1
26#endif
cd5f5e48 27#define __STDC_FORMAT_MACROS
304b4cf3 28#include <dirent.h>
cd5f5e48
CB
29#include <errno.h>
30#include <inttypes.h>
31#include <linux/loop.h>
304b4cf3
CB
32#include <stdint.h>
33#include <stdlib.h>
34#include <string.h>
7e009d52 35#include <sys/stat.h>
304b4cf3 36#include <sys/types.h>
d38dd64a 37#include <unistd.h>
304b4cf3 38
d38dd64a 39#include "config.h"
304b4cf3 40#include "log.h"
28d832c4
CB
41#include "loop.h"
42#include "storage.h"
f2d5a09d 43#include "storage_utils.h"
304b4cf3
CB
44#include "utils.h"
45
10bc1861 46lxc_log_define(loop, lxc);
304b4cf3
CB
47
48static int do_loop_create(const char *path, uint64_t size, const char *fstype);
304b4cf3
CB
49
50/*
51 * No idea what the original blockdev will be called, but the copy will be
52 * called $lxcpath/$lxcname/rootdev
53 */
10bc1861
CB
54int loop_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
55 const char *oldname, const char *cname, const char *oldpath,
56 const char *lxcpath, int snap, uint64_t newsize,
57 struct lxc_conf *conf)
304b4cf3 58{
304b4cf3
CB
59 uint64_t size = newsize;
60 int len, ret;
61 char *srcdev;
cd5f5e48 62 char fstype[100] = "ext4";
304b4cf3
CB
63
64 if (snap) {
cd5f5e48 65 ERROR("The loop storage driver does not support snapshots");
304b4cf3
CB
66 return -1;
67 }
68
69 if (!orig->dest || !orig->src)
70 return -1;
71
72 len = strlen(lxcpath) + strlen(cname) + strlen("rootdev") + 3;
73 srcdev = alloca(len);
74 ret = snprintf(srcdev, len, "%s/%s/rootdev", lxcpath, cname);
cd5f5e48
CB
75 if (ret < 0 || ret >= len) {
76 ERROR("Failed to create string");
304b4cf3 77 return -1;
cd5f5e48 78 }
304b4cf3
CB
79
80 new->src = malloc(len + 5);
cd5f5e48
CB
81 if (!new->src) {
82 ERROR("Failed to allocate memory");
304b4cf3 83 return -1;
cd5f5e48
CB
84 }
85
86 ret = snprintf(new->src, (len + 5), "loop:%s", srcdev);
87 if (ret < 0 || ret >= (len + 5)) {
88 ERROR("Failed to create string");
304b4cf3 89 return -1;
cd5f5e48 90 }
304b4cf3
CB
91
92 new->dest = malloc(len);
cd5f5e48
CB
93 if (!new->dest) {
94 ERROR("Failed to allocate memory");
304b4cf3 95 return -1;
cd5f5e48
CB
96 }
97
304b4cf3 98 ret = snprintf(new->dest, len, "%s/%s/rootfs", lxcpath, cname);
cd5f5e48
CB
99 if (ret < 0 || ret >= len) {
100 ERROR("Failed to create string");
304b4cf3 101 return -1;
cd5f5e48 102 }
304b4cf3 103
cd5f5e48
CB
104 /* It's tempting to say: if orig->src == loopback and !newsize, then
105 * copy the loopback file. However, we'd have to make sure to correctly
106 * keep holes! So punt for now.
107 */
304b4cf3 108 if (is_blktype(orig)) {
cd5f5e48 109 /* detect size */
304b4cf3 110 if (!newsize && blk_getsize(orig, &size) < 0) {
cd5f5e48
CB
111 ERROR("Failed to detect size of loop file \"%s\"",
112 orig->src);
304b4cf3
CB
113 return -1;
114 }
cd5f5e48
CB
115
116 /* detect filesystem */
304b4cf3 117 if (detect_fs(orig, fstype, 100) < 0) {
cd5f5e48 118 INFO("Failed to detect filesystem type for \"%s\"", orig->src);
304b4cf3
CB
119 return -1;
120 }
cd5f5e48 121 } else if (!newsize) {
304b4cf3
CB
122 size = DEFAULT_FS_SIZE;
123 }
cd5f5e48
CB
124
125 ret = do_loop_create(srcdev, size, fstype);
126 if (ret < 0) {
127 ERROR("Failed to create loop storage volume \"%s\" with "
128 "filesystem \"%s\" and size \"%" PRIu64 "\"",
129 srcdev, fstype, size);
130 return -1;
131 }
132
133 return 0;
304b4cf3
CB
134}
135
10bc1861 136int loop_create(struct lxc_storage *bdev, const char *dest, const char *n,
304b4cf3
CB
137 struct bdev_specs *specs)
138{
139 const char *fstype;
140 uint64_t sz;
141 int ret, len;
142 char *srcdev;
143
144 if (!specs)
145 return -1;
146
cd5f5e48
CB
147 /* <dest> is passed in as <lxcpath>/<lxcname>/rootfs, <srcdev> will
148 * be <lxcpath>/<lxcname>/rootdev, and <src> will be "loop:<srcdev>".
149 */
304b4cf3
CB
150 len = strlen(dest) + 2;
151 srcdev = alloca(len);
152
153 ret = snprintf(srcdev, len, "%s", dest);
cd5f5e48
CB
154 if (ret < 0 || ret >= len) {
155 ERROR("Failed to create string");
156 return -1;
157 }
158
159 ret = sprintf(srcdev + len - 4, "dev");
160 if (ret < 0) {
161 ERROR("Failed to create string");
304b4cf3 162 return -1;
cd5f5e48 163 }
304b4cf3
CB
164
165 bdev->src = malloc(len + 5);
cd5f5e48
CB
166 if (!bdev->src) {
167 ERROR("Failed to allocate memory");
304b4cf3 168 return -1;
cd5f5e48
CB
169 }
170
304b4cf3 171 ret = snprintf(bdev->src, len + 5, "loop:%s", srcdev);
cd5f5e48
CB
172 if (ret < 0 || ret >= len + 5) {
173 ERROR("Failed to create string");
304b4cf3 174 return -1;
cd5f5e48 175 }
304b4cf3
CB
176
177 sz = specs->fssize;
178 if (!sz)
179 sz = DEFAULT_FS_SIZE;
180
181 fstype = specs->fstype;
182 if (!fstype)
183 fstype = DEFAULT_FSTYPE;
184
cd5f5e48
CB
185 bdev->dest = strdup(dest);
186 if (!bdev->dest) {
187 ERROR("Failed to duplicate string \"%s\"", dest);
304b4cf3 188 return -1;
cd5f5e48 189 }
304b4cf3 190
cd5f5e48
CB
191 ret = mkdir_p(bdev->dest, 0755);
192 if (ret < 0) {
193 ERROR("Failed creating directory \"%s\"", bdev->dest);
304b4cf3
CB
194 return -1;
195 }
196
cd5f5e48
CB
197
198 ret = do_loop_create(srcdev, sz, fstype);
199 if (ret < 0) {
200 ERROR("Failed to create loop storage volume \"%s\" with "
201 "filesystem \"%s\" and size \"%" PRIu64 "\"",
202 srcdev, fstype, sz);
203 return -1;
204 }
205
206 return 0;
304b4cf3
CB
207}
208
10bc1861 209int loop_destroy(struct lxc_storage *orig) {
70d6bd97
CB
210 char *dir;
211
212 dir = orig->src;
213 if (strncmp(orig->src, "loop:", 5) == 0)
214 dir += 5;
215
216 return unlink(dir);
304b4cf3
CB
217}
218
3d2ae1e2 219bool loop_detect(const char *path)
304b4cf3 220{
7e009d52
CB
221 int ret;
222 struct stat s;
223
f7ac4459 224 if (!strncmp(path, "loop:", 5))
3d2ae1e2 225 return true;
7e009d52
CB
226
227 ret = stat(path, &s);
228 if (ret < 0)
3d2ae1e2 229 return false;
7e009d52
CB
230
231 if (__S_ISTYPE(s.st_mode, S_IFREG))
3d2ae1e2 232 return true;
7e009d52 233
3d2ae1e2 234 return false;
304b4cf3
CB
235}
236
10bc1861 237int loop_mount(struct lxc_storage *bdev)
304b4cf3 238{
c6868a1f 239 int ret, loopfd;
339de297 240 char loname[PATH_MAX];
41dc7155 241 const char *src;
304b4cf3
CB
242
243 if (strcmp(bdev->type, "loop"))
244 return -22;
7e009d52 245
304b4cf3
CB
246 if (!bdev->src || !bdev->dest)
247 return -22;
304b4cf3 248
7e009d52 249 /* skip prefix */
cd5f5e48 250 src = lxc_storage_get_path(bdev->src, bdev->type);
7e009d52
CB
251
252 loopfd = lxc_prepare_loop_dev(src, loname, LO_FLAGS_AUTOCLEAR);
a5b18cb1 253 if (loopfd < 0) {
cd5f5e48 254 ERROR("Failed to prepare loop device for loop file \"%s\"", src);
c6868a1f 255 return -1;
a5b18cb1 256 }
cd5f5e48 257 DEBUG("Prepared loop device \"%s\"", loname);
304b4cf3
CB
258
259 ret = mount_unknown_fs(loname, bdev->dest, bdev->mntopts);
cd5f5e48
CB
260 if (ret < 0) {
261 ERROR("Failed to mount rootfs \"%s\" on \"%s\" via loop device \"%s\"",
262 bdev->src, bdev->dest, loname);
263 close(loopfd);
264 return -1;
265 }
304b4cf3 266
cd5f5e48
CB
267 bdev->lofd = loopfd;
268 DEBUG("Mounted rootfs \"%s\" on \"%s\" via loop device \"%s\"",
269 bdev->src, bdev->dest, loname);
270
271 return 0;
304b4cf3
CB
272}
273
10bc1861 274int loop_umount(struct lxc_storage *bdev)
304b4cf3 275{
cd5f5e48 276 int ret, saved_errno;
304b4cf3
CB
277
278 if (strcmp(bdev->type, "loop"))
279 return -22;
cd5f5e48 280
304b4cf3
CB
281 if (!bdev->src || !bdev->dest)
282 return -22;
cd5f5e48 283
304b4cf3 284 ret = umount(bdev->dest);
cd5f5e48 285 saved_errno = errno;
304b4cf3
CB
286 if (bdev->lofd >= 0) {
287 close(bdev->lofd);
288 bdev->lofd = -1;
289 }
cd5f5e48
CB
290 errno = saved_errno;
291
292 if (ret < 0) {
293 SYSERROR("Failed to umount \"%s\"", bdev->dest);
294 return -1;
295 }
296
297 return 0;
304b4cf3
CB
298}
299
300static int do_loop_create(const char *path, uint64_t size, const char *fstype)
301{
302 int fd, ret;
8737e2a8 303 off_t ret_size;
339de297 304 char cmd_output[PATH_MAX];
cd5f5e48 305 const char *cmd_args[2] = {fstype, path};
a5b18cb1 306
cd5f5e48
CB
307 /* create the new loopback file */
308 fd = creat(path, S_IRUSR | S_IWUSR);
309 if (fd < 0) {
310 SYSERROR("Failed to create new loop file \"%s\"", path);
304b4cf3 311 return -1;
cd5f5e48
CB
312 }
313
8737e2a8
LJ
314 ret_size = lseek(fd, size, SEEK_SET);
315 if (ret_size < 0) {
cd5f5e48
CB
316 SYSERROR("Failed to seek to set new loop file size for loop "
317 "file \"%s\"", path);
304b4cf3
CB
318 close(fd);
319 return -1;
320 }
cd5f5e48
CB
321
322 ret = write(fd, "1", 1);
323 if (ret != 1) {
324 SYSERROR("Failed creating new loop file \"%s\"", path);
304b4cf3
CB
325 close(fd);
326 return -1;
327 }
cd5f5e48 328
304b4cf3
CB
329 ret = close(fd);
330 if (ret < 0) {
cd5f5e48 331 SYSERROR("Failed to create new loop file \"%s\"", path);
304b4cf3
CB
332 return -1;
333 }
334
1a0e70ac 335 /* Create an fs in the loopback file. */
a5b18cb1
CB
336 ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
337 (void *)cmd_args);
cd5f5e48
CB
338 if (ret < 0) {
339 ERROR("Failed to create new filesystem \"%s\" for loop file "
340 "\"%s\": %s", fstype, path, cmd_output);
304b4cf3 341 return -1;
cd5f5e48 342 }
304b4cf3
CB
343
344 return 0;
345}