[PATCH] kvm tools: Use overlayfs when mounting rootfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
 
 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);
+}
+
 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


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux