]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/bdev/lxcaufs.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
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.
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.
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
29 #include <sys/types.h>
37 lxc_log_define(lxcaufs
, lxc
);
39 /* the bulk of this needs to become a common helper */
40 extern char *dir_new_path(char *src
, const char *oldname
, const char *name
,
41 const char *oldpath
, const char *lxcpath
);
43 int aufs_clonepaths(struct bdev
*orig
, struct bdev
*new, const char *oldname
,
44 const char *cname
, const char *oldpath
, const char *lxcpath
,
45 int snap
, uint64_t newsize
, struct lxc_conf
*conf
)
48 ERROR("aufs is only for snapshot clones");
52 if (!orig
->src
|| !orig
->dest
)
55 new->dest
= dir_new_path(orig
->dest
, oldname
, cname
, oldpath
, lxcpath
);
58 if (mkdir_p(new->dest
, 0755) < 0)
61 if (am_unpriv() && chown_mapped_root(new->dest
, conf
) < 0)
62 WARN("Failed to update ownership of %s", new->dest
);
64 if (strcmp(orig
->type
, "dir") == 0) {
65 char *delta
, *lastslash
;
66 int ret
, len
, lastslashidx
;
68 // if we have /var/lib/lxc/c2/rootfs, then delta will be
69 // /var/lib/lxc/c2/delta0
70 lastslash
= strrchr(new->dest
, '/');
73 if (strlen(lastslash
) < 7)
76 lastslashidx
= lastslash
- new->dest
;
78 delta
= malloc(lastslashidx
+ 7);
81 strncpy(delta
, new->dest
, lastslashidx
+1);
82 strcpy(delta
+lastslashidx
, "delta0");
83 if ((ret
= mkdir(delta
, 0755)) < 0) {
84 SYSERROR("error: mkdir %s", delta
);
88 if (am_unpriv() && chown_mapped_root(delta
, conf
) < 0)
89 WARN("Failed to update ownership of %s", delta
);
91 // the src will be 'aufs:lowerdir:upperdir'
92 len
= strlen(delta
) + strlen(orig
->src
) + 12;
93 new->src
= malloc(len
);
98 ret
= snprintf(new->src
, len
, "aufs:%s:%s", orig
->src
, delta
);
100 if (ret
< 0 || ret
>= len
)
102 } else if (strcmp(orig
->type
, "aufs") == 0) {
103 // What exactly do we want to do here?
104 // I think we want to use the original lowerdir, with a
105 // private delta which is originally rsynced from the
107 char *osrc
, *odelta
, *nsrc
, *ndelta
;
109 if (!(osrc
= strdup(orig
->src
)))
111 nsrc
= strchr(osrc
, ':') + 1;
112 if (nsrc
!= osrc
+ 5 || (odelta
= strchr(nsrc
, ':')) == NULL
) {
118 ndelta
= dir_new_path(odelta
, oldname
, cname
, oldpath
, lxcpath
);
123 if ((ret
= mkdir(ndelta
, 0755)) < 0 && errno
!= EEXIST
) {
124 SYSERROR("error: mkdir %s", ndelta
);
129 if (am_unpriv() && chown_mapped_root(ndelta
, conf
) < 0)
130 WARN("Failed to update ownership of %s", ndelta
);
132 struct rsync_data_char rdata
;
136 ret
= userns_exec_1(conf
, rsync_delta_wrapper
, &rdata
,
137 "rsync_delta_wrapper");
139 ret
= rsync_delta(&rdata
);
143 ERROR("copying aufs delta");
146 len
= strlen(nsrc
) + strlen(ndelta
) + 12;
147 new->src
= malloc(len
);
153 ret
= snprintf(new->src
, len
, "aufs:%s:%s", nsrc
, ndelta
);
156 if (ret
< 0 || ret
>= len
)
159 ERROR("aufs clone of %s container is not yet supported",
161 // Note, supporting this will require aufs_mount supporting
162 // mounting of the underlay. No big deal, just needs to be done.
170 * to say 'lxc-create -t ubuntu -n o1 -B aufs' means you want
171 * $lxcpath/$lxcname/rootfs to have the created container, while all
172 * changes after starting the container are written to
173 * $lxcpath/$lxcname/delta0
175 int aufs_create(struct bdev
*bdev
, const char *dest
, const char *n
,
176 struct bdev_specs
*specs
)
179 int ret
, len
= strlen(dest
), newlen
;
181 if (len
< 8 || strcmp(dest
+len
-7, "/rootfs") != 0)
184 if (!(bdev
->dest
= strdup(dest
))) {
185 ERROR("Out of memory");
189 delta
= alloca(strlen(dest
)+1);
191 strcpy(delta
+len
-6, "delta0");
193 if (mkdir_p(delta
, 0755) < 0) {
194 ERROR("Error creating %s", delta
);
198 /* aufs:lower:upper */
199 newlen
= (2 * len
) + strlen("aufs:") + 2;
200 bdev
->src
= malloc(newlen
);
202 ERROR("Out of memory");
205 ret
= snprintf(bdev
->src
, newlen
, "aufs:%s:%s", dest
, delta
);
206 if (ret
< 0 || ret
>= newlen
)
209 if (mkdir_p(bdev
->dest
, 0755) < 0) {
210 ERROR("Error creating %s", bdev
->dest
);
217 int aufs_destroy(struct bdev
*orig
)
221 if (strncmp(orig
->src
, "aufs:", 5) != 0)
223 upper
= strchr(orig
->src
+ 5, ':');
227 return lxc_rmdir_onedev(upper
, NULL
);
230 int aufs_detect(const char *path
)
232 if (strncmp(path
, "aufs:", 5) == 0)
233 return 1; // take their word for it
237 int aufs_mount(struct bdev
*bdev
)
239 char *tmp
, *options
, *dup
, *lower
, *upper
;
241 unsigned long mntflags
;
244 const char *xinopath
= "/dev/shm/aufs.xino";
246 if (strcmp(bdev
->type
, "aufs"))
248 if (!bdev
->src
|| !bdev
->dest
)
251 // separately mount it first
252 // mount -t aufs -obr=${upper}=rw:${lower}=ro lower dest
253 dup
= alloca(strlen(bdev
->src
)+1);
254 strcpy(dup
, bdev
->src
);
255 /* support multiple lower layers */
256 if (!(lower
= strstr(dup
, ":/")))
260 while ((tmp
= strstr(++upper
, ":/"))) {
263 if (--upper
== lower
)
268 if (parse_mntopts(bdev
->mntopts
, &mntflags
, &mntdata
) < 0) {
273 // TODO We should check whether bdev->src is a blockdev, and if so
274 // but for now, only support aufs of a basic directory
276 // AUFS does not work on top of certain filesystems like (XFS or Btrfs)
277 // so add xino=/dev/shm/aufs.xino parameter to mount options.
278 // The same xino option can be specified to multiple aufs mounts, and
279 // a xino file is not shared among multiple aufs mounts.
281 // see http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg02587.html
282 // http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg05126.html
284 len
= strlen(lower
) + strlen(upper
) + strlen(xinopath
) + strlen("br==rw:=ro,,xino=") + strlen(mntdata
) + 1;
285 options
= alloca(len
);
286 ret
= snprintf(options
, len
, "br=%s=rw:%s=ro,%s,xino=%s", upper
, lower
, mntdata
, xinopath
);
289 len
= strlen(lower
) + strlen(upper
) + strlen(xinopath
) + strlen("br==rw:=ro,xino=") + 1;
290 options
= alloca(len
);
291 ret
= snprintf(options
, len
, "br=%s=rw:%s=ro,xino=%s", upper
, lower
, xinopath
);
294 if (ret
< 0 || ret
>= len
) {
299 ret
= mount(lower
, bdev
->dest
, "aufs", MS_MGC_VAL
| mntflags
, options
);
301 SYSERROR("aufs: error mounting %s onto %s options %s",
302 lower
, bdev
->dest
, options
);
304 INFO("aufs: mounted %s onto %s options %s",
305 lower
, bdev
->dest
, options
);
309 int aufs_umount(struct bdev
*bdev
)
311 if (strcmp(bdev
->type
, "aufs"))
313 if (!bdev
->src
|| !bdev
->dest
)
315 return umount(bdev
->dest
);
318 char *aufs_get_rootfs(const char *rootfs_path
, size_t *rootfslen
)
320 char *rootfsdir
= NULL
;
325 if (!rootfs_path
|| !rootfslen
)
328 s1
= strdup(rootfs_path
);
332 if ((s2
= strstr(s1
, ":/"))) {
334 if ((s3
= strstr(s2
, ":/")))
336 rootfsdir
= strdup(s2
);
348 *rootfslen
= strlen(rootfsdir
);
353 int aufs_mkdir(const struct mntent
*mntent
, const struct lxc_rootfs
*rootfs
,
354 const char *lxc_name
, const char *lxc_path
)
356 char lxcpath
[MAXPATHLEN
];
357 char *rootfs_path
= NULL
;
358 char *rootfsdir
= NULL
;
359 char *scratch
= NULL
;
361 char *upperdir
= NULL
;
368 size_t rootfslen
= 0;
370 /* When rootfs == NULL we have a container without a rootfs. */
371 if (rootfs
&& rootfs
->path
)
372 rootfs_path
= rootfs
->path
;
374 opts
= lxc_string_split(mntent
->mnt_opts
, ',');
376 arrlen
= lxc_array_len((void **)opts
);
380 for (i
= 0; i
< arrlen
; i
++) {
381 if (strstr(opts
[i
], "br=") && (strlen(opts
[i
]) > (len
= strlen("br="))))
387 upperdir
= strtok_r(tmp
, ":=", &scratch
);
392 ret
= snprintf(lxcpath
, MAXPATHLEN
, "%s/%s", lxc_path
, lxc_name
);
393 if (ret
< 0 || ret
>= MAXPATHLEN
)
396 rootfsdir
= aufs_get_rootfs(rootfs
->path
, &rootfslen
);
402 * We neither allow users to create upperdirs and workdirs outside the
403 * containerdir nor inside the rootfs. The latter might be debatable.
404 * When we have a container without a rootfs we skip the checks.
408 ret
= mkdir_p(upperdir
, 0755);
409 else if ((strncmp(upperdir
, lxcpath
, strlen(lxcpath
)) == 0) && (strncmp(upperdir
, rootfsdir
, rootfslen
) != 0))
410 ret
= mkdir_p(upperdir
, 0755);
412 WARN("Failed to create upperdir");
418 lxc_free_array((void **)opts
, free
);