On Tue, Aug 9, 2011 at 5:57 PM, Sasha Levin <[email protected]> wrote:
> This patch uses (the not yet merged) overlayfs to allow booting complex
> distribution rootfs and provide
> a COW layer within the rootfs.
>
> We use overlayfs for two reasons:
> - Overwrite the /etc/fstab file so that the mounter will use the virtio-9p
> device as root instead of
> /dev/vda.
> - Provide a COW space so that changes aren't written back to the rootfs.
> This allows easy testing and
> work without ruining your rootfs.
>
> Usage:
> '--overlayfs [root_dir]' - Use root_dir to boot the guest, COW is provided
> automatically.
>
> Please note that host kernel support needs to have overlayfs support. This
> feature is not yet available
> as part of the mainline kernel, therefore if you'd like to try out this patch
> you should pull overlayfs
> into your kernel tree.
>
> Latest version of overlayfs can be found here:
> git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git overlayfs.v11
>
> Cc: Miklos Szeredi <[email protected]>
> Signed-off-by: Sasha Levin <[email protected]>
> ---
> tools/kvm/Makefile | 2 +-
> tools/kvm/builtin-run.c | 87
> +++++++++++++++++++++++++++++++++--
> tools/kvm/include/kvm/builtin-run.h | 5 ++
> tools/kvm/kvm-cpu.c | 2 +
> 4 files changed, 91 insertions(+), 5 deletions(-)
>
> diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
> index 8d45ebf..acb3aca 100644
> --- a/tools/kvm/Makefile
> +++ b/tools/kvm/Makefile
> @@ -130,7 +130,7 @@ DEFINES += -D_GNU_SOURCE
> DEFINES += -DKVMTOOLS_VERSION='"$(KVMTOOLS_VERSION)"'
>
> KVM_INCLUDE := include
> -CFLAGS += $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I../../include
> -I../../arch/$(ARCH)/include/ -Os -g
> +CFLAGS += $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I../../include
> -I../../arch/$(ARCH)/include/ -O0 -g
Please drop this :-)
>
> ifneq ($(WERROR),0)
> WARNINGS += -Werror
> diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
> index c8539cc..19f7d6b 100644
> --- a/tools/kvm/builtin-run.c
> +++ b/tools/kvm/builtin-run.c
> @@ -76,6 +76,7 @@ static const char *guest_mac;
> static const char *host_mac;
> static const char *script;
> static const char *guest_name;
> +static const char *overlayfs;
> static bool single_step;
> static bool readonly_image[MAX_DISK_IMAGES];
> static bool vnc;
> @@ -91,6 +92,13 @@ bool do_debug_print = false;
> static int nrcpus;
> static int vidmode = -1;
>
> +/* Apperantly <linux/fs.h> and <sys/mount.h> don't work well together */
> +int mount(const char *source, const char *target,
> + const char *filesystemtype, unsigned long mountflags,
> + const void *data);
> +int umount(const char *target);
> +
> +
> static const char * const run_usage[] = {
> "kvm run [<options>] [<kernel image>]",
> NULL
> @@ -169,6 +177,7 @@ static const struct option options[] = {
> OPT_BOOLEAN('\0', "balloon", &balloon, "Enable virtio balloon"),
> OPT_BOOLEAN('\0', "vnc", &vnc, "Enable VNC framebuffer"),
> OPT_BOOLEAN('\0', "sdl", &sdl, "Enable SDL framebuffer"),
> + OPT_STRING('\0', "overlayfs", &overlayfs, "overlayfs", "Root FS"),
>
> OPT_GROUP("Kernel options:"),
> OPT_STRING('k', "kernel", &kernel_filename, "kernel",
> @@ -491,6 +500,71 @@ void kvm_run_help(void)
> usage_with_options(run_usage, options);
> }
>
> +int kvm_create_overlayfs(struct kvm* kvm)
> +{
> + char tmp[PATH_MAX];
> + char cow[PATH_MAX], overlay[PATH_MAX], rootfs[PATH_MAX];
> +
> + /*
> + * Create 3 directories for building our mount.
> + * Read rootfs -> modification layer -> cow layer -> new root
> + */
> +
> + sprintf(cow, "%s-cow", guest_name);
> + sprintf(rootfs, "%s-rootfs", guest_name);
> + sprintf(overlay, "%s-overlay", guest_name);
> +
> + if (mkdir(cow, 0777) < 0) {
> + /* If the COW dir is already there it's ok - just use it */
> + if (errno != EEXIST)
> + goto cleanup;
> + }
> +
> + if (mkdir(rootfs, 0777) < 0)
> + goto cleanup;
> +
> + if (mkdir(overlay, 0777) < 0)
> + goto cleanup;
> +
> + sprintf(tmp, "lowerdir=%s,upperdir=virt", overlayfs);
> + if (mount("overlayfs", overlay, "overlayfs", MS_MGC_VAL, tmp) < 0) {
> + printf("%d\n", errno);
> + goto cleanup;
> +
> + }
> +
> + sprintf(tmp, "lowerdir=%s,upperdir=%s", overlay, cow);
> + if (mount("overlayfs", rootfs, "overlayfs", MS_MGC_VAL, tmp) < 0)
> + goto cleanup;
> +
> + if (realpath(rootfs, tmp) == 0 ||
> + virtio_9p__init(kvm, tmp, "/dev/root") < 0)
> + die("Unable to initialize virtio 9p");
> + using_rootfs = 1;
> +
> + return 0;
> +
> +cleanup:
> + kvm_remove_overlayfs();
> +
> + return -1;
> +}
> +
> +void kvm_remove_overlayfs(void)
> +{
> + char cow[PATH_MAX], overlay[PATH_MAX], rootfs[PATH_MAX];
> +
> + sprintf(cow, "%s-cow", guest_name);
> + sprintf(rootfs, "%s-rootfs", guest_name);
> + sprintf(overlay, "%s-overlay", guest_name);
> +
> + umount(rootfs);
> + umount(overlay);
> + rmdir(cow);
> + rmdir(overlay);
> + rmdir(rootfs);
> +}
I guess this is OK for this patch but for the long-term I think we
should make the guests persistent so that
kvm run
picks up the previous copy-on-write overlayfs automatically. That'd
probably mean that 'kvm run' will always attempt to use a guest named
'default' that's automatically created upon the first time 'kvm run'
is invoked.
We should also make 'kvm list' print out something like
default [powered off]
Ingo probably has some ideas on this as well.
> +
> int kvm_cmd_run(int argc, const char **argv, const char *prefix)
> {
> struct virtio_net_parameters net_params;
> @@ -634,7 +708,7 @@ int kvm_cmd_run(int argc, const char **argv, const char
> *prefix)
> strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline));
>
> hi = NULL;
> - if (!using_rootfs && !image_filename[0]) {
> + if (!overlayfs && !using_rootfs && !image_filename[0]) {
> hi = host_image(real_cmdline, sizeof(real_cmdline));
> if (hi) {
> image_filename[0] = hi;
> @@ -643,12 +717,17 @@ int kvm_cmd_run(int argc, const char **argv, const char
> *prefix)
> }
> }
>
> - if (!strstr(real_cmdline, "root="))
> - strlcat(real_cmdline, " root=/dev/vda rw ",
> sizeof(real_cmdline));
> + if (overlayfs) {
> + if (kvm_create_overlayfs(kvm) < 0)
> + die("Failed creating overlayfs - did you remember to
> apply the overlayfs patches?");
> + }
>
> - if (using_rootfs)
> + if (using_rootfs || overlayfs)
> strcat(real_cmdline, " root=/dev/root
> rootflags=rw,trans=virtio,version=9p2000.u rootfstype=9p");
>
> + if (!strstr(real_cmdline, "root="))
> + strlcat(real_cmdline, " root=/dev/vda rw ",
> sizeof(real_cmdline));
> +
> if (image_count) {
> kvm->nr_disks = image_count;
> kvm->disks = disk_image__open_all(image_filename,
> readonly_image, image_count);
> diff --git a/tools/kvm/include/kvm/builtin-run.h
> b/tools/kvm/include/kvm/builtin-run.h
> index d056ad4..aa12a42 100644
> --- a/tools/kvm/include/kvm/builtin-run.h
> +++ b/tools/kvm/include/kvm/builtin-run.h
> @@ -1,6 +1,11 @@
> #ifndef __KVM_RUN_H__
> #define __KVM_RUN_H__
>
> +struct kvm;
> +
> +void kvm_remove_overlayfs(void);
> +int kvm_create_overlayfs(struct kvm* kvm);
> +
> int kvm_cmd_run(int argc, const char **argv, const char *prefix);
> void kvm_run_help(void);
>
> diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
> index 2f5d23c..6f60138 100644
> --- a/tools/kvm/kvm-cpu.c
> +++ b/tools/kvm/kvm-cpu.c
> @@ -3,6 +3,7 @@
> #include "kvm/symbol.h"
> #include "kvm/util.h"
> #include "kvm/kvm.h"
> +#include "kvm/builtin-run.h"
>
> #include <asm/msr-index.h>
>
> @@ -422,6 +423,7 @@ static void kvm_cpu__handle_coalesced_mmio(struct kvm_cpu
> *cpu)
> void kvm_cpu__reboot(void)
> {
> pthread_kill(kvm_cpus[0]->thread, SIGKVMEXIT);
> + kvm_remove_overlayfs();
> }
>
> int kvm_cpu__start(struct kvm_cpu *cpu)
> --
> 1.7.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html