1708dc6cbSAsias He #include "kvm/disk-image.h"
2708dc6cbSAsias He
39f9207c5SSasha Levin #include <linux/err.h>
458fd2b7bSAsias He #include <mntent.h>
59f9207c5SSasha Levin
6708dc6cbSAsias He /*
7708dc6cbSAsias He * raw image and blk dev are similar, so reuse raw image ops.
8708dc6cbSAsias He */
9063e87a0SAsias He static struct disk_image_operations blk_dev_ops = {
10dcd3cd8eSAsias He .read = raw_image__read,
11dcd3cd8eSAsias He .write = raw_image__write,
12*2790307cSJean-Philippe Brucker .wait = raw_image__wait,
13d62e8ee0SJean-Philippe Brucker .async = true,
14708dc6cbSAsias He };
15708dc6cbSAsias He
is_mounted(struct stat * st)1658fd2b7bSAsias He static bool is_mounted(struct stat *st)
1758fd2b7bSAsias He {
1858fd2b7bSAsias He struct stat st_buf;
1958fd2b7bSAsias He struct mntent *mnt;
2058fd2b7bSAsias He FILE *f;
2158fd2b7bSAsias He
2258fd2b7bSAsias He f = setmntent("/proc/mounts", "r");
2358fd2b7bSAsias He if (!f)
2458fd2b7bSAsias He return false;
2558fd2b7bSAsias He
2658fd2b7bSAsias He while ((mnt = getmntent(f)) != NULL) {
2758fd2b7bSAsias He if (stat(mnt->mnt_fsname, &st_buf) == 0 &&
2858fd2b7bSAsias He S_ISBLK(st_buf.st_mode) && st->st_rdev == st_buf.st_rdev) {
2958fd2b7bSAsias He fclose(f);
3058fd2b7bSAsias He return true;
3158fd2b7bSAsias He }
3258fd2b7bSAsias He }
3358fd2b7bSAsias He
3458fd2b7bSAsias He fclose(f);
3558fd2b7bSAsias He return false;
3658fd2b7bSAsias He }
3758fd2b7bSAsias He
blkdev__probe(const char * filename,int flags,struct stat * st)385236b505SAsias He struct disk_image *blkdev__probe(const char *filename, int flags, struct stat *st)
39708dc6cbSAsias He {
409f9207c5SSasha Levin int fd, r;
4158fd2b7bSAsias He u64 size;
42708dc6cbSAsias He
43708dc6cbSAsias He if (!S_ISBLK(st->st_mode))
449f9207c5SSasha Levin return ERR_PTR(-EINVAL);
45708dc6cbSAsias He
4658fd2b7bSAsias He if (is_mounted(st)) {
4758fd2b7bSAsias He pr_err("Block device %s is already mounted! Unmount before use.",
4858fd2b7bSAsias He filename);
4958fd2b7bSAsias He return ERR_PTR(-EINVAL);
5058fd2b7bSAsias He }
5158fd2b7bSAsias He
52063e87a0SAsias He /*
53063e87a0SAsias He * Be careful! We are opening host block device!
54063e87a0SAsias He * Open it readonly since we do not want to break user's data on disk.
55063e87a0SAsias He */
565236b505SAsias He fd = open(filename, flags);
57708dc6cbSAsias He if (fd < 0)
589f9207c5SSasha Levin return ERR_PTR(fd);
59708dc6cbSAsias He
60708dc6cbSAsias He if (ioctl(fd, BLKGETSIZE64, &size) < 0) {
619f9207c5SSasha Levin r = -errno;
62708dc6cbSAsias He close(fd);
639f9207c5SSasha Levin return ERR_PTR(r);
64708dc6cbSAsias He }
65708dc6cbSAsias He
66063e87a0SAsias He /*
67063e87a0SAsias He * FIXME: This will not work on 32-bit host because we can not
68063e87a0SAsias He * mmap large disk. There is not enough virtual address space
69063e87a0SAsias He * in 32-bit host. However, this works on 64-bit host.
70063e87a0SAsias He */
71d62e8ee0SJean-Philippe Brucker return disk_image__new(fd, size, &blk_dev_ops, DISK_IMAGE_REGULAR);
72708dc6cbSAsias He }
73