1 #include "kvm/disk-image.h"
2
3 #include <linux/err.h>
4 #include <mntent.h>
5
6 /*
7 * raw image and blk dev are similar, so reuse raw image ops.
8 */
9 static struct disk_image_operations blk_dev_ops = {
10 .read = raw_image__read,
11 .write = raw_image__write,
12 .wait = raw_image__wait,
13 .async = true,
14 };
15
is_mounted(struct stat * st)16 static bool is_mounted(struct stat *st)
17 {
18 struct stat st_buf;
19 struct mntent *mnt;
20 FILE *f;
21
22 f = setmntent("/proc/mounts", "r");
23 if (!f)
24 return false;
25
26 while ((mnt = getmntent(f)) != NULL) {
27 if (stat(mnt->mnt_fsname, &st_buf) == 0 &&
28 S_ISBLK(st_buf.st_mode) && st->st_rdev == st_buf.st_rdev) {
29 fclose(f);
30 return true;
31 }
32 }
33
34 fclose(f);
35 return false;
36 }
37
blkdev__probe(const char * filename,int flags,struct stat * st)38 struct disk_image *blkdev__probe(const char *filename, int flags, struct stat *st)
39 {
40 int fd, r;
41 u64 size;
42
43 if (!S_ISBLK(st->st_mode))
44 return ERR_PTR(-EINVAL);
45
46 if (is_mounted(st)) {
47 pr_err("Block device %s is already mounted! Unmount before use.",
48 filename);
49 return ERR_PTR(-EINVAL);
50 }
51
52 /*
53 * Be careful! We are opening host block device!
54 * Open it readonly since we do not want to break user's data on disk.
55 */
56 fd = open(filename, flags);
57 if (fd < 0)
58 return ERR_PTR(fd);
59
60 if (ioctl(fd, BLKGETSIZE64, &size) < 0) {
61 r = -errno;
62 close(fd);
63 return ERR_PTR(r);
64 }
65
66 /*
67 * FIXME: This will not work on 32-bit host because we can not
68 * mmap large disk. There is not enough virtual address space
69 * in 32-bit host. However, this works on 64-bit host.
70 */
71 return disk_image__new(fd, size, &blk_dev_ops, DISK_IMAGE_REGULAR);
72 }
73