On Tue, Aug 9, 2011 at 5:57 PM, Sasha Levin <levinsasha928@xxxxxxxxx> 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 <miklos@xxxxxxxxxx> > Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx> > --- > 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 majordomo@xxxxxxxxxxxxxxx > 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html