From 6ec60cfdc448373f877eccca1b1c9e2f4deabfe8 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Wed, 13 Apr 2011 22:56:02 +0300 Subject: [PATCH] kvm tools: Add read-only support for block devices Add support for booting guests to host block devices in read-only mode. Quoting Ingo Molnar: Booting into the host's userspace works out of box now. The following disk-image-less command: ./kvm run ../../arch/x86/boot/bzImage --readonly --image=/dev/sda --params="root=/dev/vda1" has booted all the way into the host's Fedora Rawhide userspace: =================================== Welcome to Fedora release 16 (Rawhide)! [...] Fedora release 16 (Rawhide) Kernel 2.6.39-rc3-tip+ on an x86_64 (ttyS0) aldebaran login: =================================== I ran this as unprivileged user (who had read access to the partitions in question). This is a very useful feature for testing kernels - i can test any random Linux box's userspace via KVM, without having to copy an image there! :-) Cc: Asias He Cc: Cyrill Gorcunov Cc: Prasad Joshi Cc: Sasha Levin Tested-by: Ingo Molnar Signed-off-by: Pekka Enberg --- disk-image.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/disk-image.c b/disk-image.c index fff71b4..f5e11b9 100644 --- a/disk-image.c +++ b/disk-image.c @@ -4,6 +4,9 @@ #include "kvm/qcow.h" #include "kvm/util.h" +#include /* for BLKGETSIZE64 */ + +#include #include #include #include @@ -110,24 +113,44 @@ static struct disk_image_operations raw_image_ro_mmap_ops = { .close = raw_image__close_sector_ro_mmap, }; -static struct disk_image *raw_image__probe(int fd, bool readonly) +static struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly) { - struct stat st; + if (readonly) + return disk_image__new_readonly(fd, st->st_size, &raw_image_ro_mmap_ops); + else + return disk_image__new(fd, st->st_size, &raw_image_ops); +} - if (fstat(fd, &st) < 0) +static struct disk_image *blkdev__probe(const char *filename, struct stat *st) +{ + uint64_t size; + int fd; + + if (!S_ISBLK(st->st_mode)) return NULL; - if (readonly) - return disk_image__new_readonly(fd, st.st_size, &raw_image_ro_mmap_ops); - else - return disk_image__new(fd, st.st_size, &raw_image_ops); + fd = open(filename, O_RDONLY); + if (fd < 0) + return NULL; + + if (ioctl(fd, BLKGETSIZE64, &size) < 0) + return NULL; + + return disk_image__new_readonly(fd, size, &raw_image_ro_mmap_ops); } struct disk_image *disk_image__open(const char *filename, bool readonly) { struct disk_image *self; + struct stat st; int fd; + if (stat(filename, &st) < 0) + return NULL; + + if (S_ISBLK(st.st_mode)) + return blkdev__probe(filename, &st); + fd = open(filename, readonly ? O_RDONLY : O_RDWR); if (fd < 0) return NULL; @@ -136,7 +159,7 @@ struct disk_image *disk_image__open(const char *filename, bool readonly) if (self) return self; - self = raw_image__probe(fd, readonly); + self = raw_image__probe(fd, &st, readonly); if (self) return self;