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*d62e8ee0SJean-Philippe Brucker .async = true, 13708dc6cbSAsias He }; 14708dc6cbSAsias He 1558fd2b7bSAsias He static bool is_mounted(struct stat *st) 1658fd2b7bSAsias He { 1758fd2b7bSAsias He struct stat st_buf; 1858fd2b7bSAsias He struct mntent *mnt; 1958fd2b7bSAsias He FILE *f; 2058fd2b7bSAsias He 2158fd2b7bSAsias He f = setmntent("/proc/mounts", "r"); 2258fd2b7bSAsias He if (!f) 2358fd2b7bSAsias He return false; 2458fd2b7bSAsias He 2558fd2b7bSAsias He while ((mnt = getmntent(f)) != NULL) { 2658fd2b7bSAsias He if (stat(mnt->mnt_fsname, &st_buf) == 0 && 2758fd2b7bSAsias He S_ISBLK(st_buf.st_mode) && st->st_rdev == st_buf.st_rdev) { 2858fd2b7bSAsias He fclose(f); 2958fd2b7bSAsias He return true; 3058fd2b7bSAsias He } 3158fd2b7bSAsias He } 3258fd2b7bSAsias He 3358fd2b7bSAsias He fclose(f); 3458fd2b7bSAsias He return false; 3558fd2b7bSAsias He } 3658fd2b7bSAsias He 375236b505SAsias He struct disk_image *blkdev__probe(const char *filename, int flags, struct stat *st) 38708dc6cbSAsias He { 399f9207c5SSasha Levin int fd, r; 4058fd2b7bSAsias He u64 size; 41708dc6cbSAsias He 42708dc6cbSAsias He if (!S_ISBLK(st->st_mode)) 439f9207c5SSasha Levin return ERR_PTR(-EINVAL); 44708dc6cbSAsias He 4558fd2b7bSAsias He if (is_mounted(st)) { 4658fd2b7bSAsias He pr_err("Block device %s is already mounted! Unmount before use.", 4758fd2b7bSAsias He filename); 4858fd2b7bSAsias He return ERR_PTR(-EINVAL); 4958fd2b7bSAsias He } 5058fd2b7bSAsias He 51063e87a0SAsias He /* 52063e87a0SAsias He * Be careful! We are opening host block device! 53063e87a0SAsias He * Open it readonly since we do not want to break user's data on disk. 54063e87a0SAsias He */ 555236b505SAsias He fd = open(filename, flags); 56708dc6cbSAsias He if (fd < 0) 579f9207c5SSasha Levin return ERR_PTR(fd); 58708dc6cbSAsias He 59708dc6cbSAsias He if (ioctl(fd, BLKGETSIZE64, &size) < 0) { 609f9207c5SSasha Levin r = -errno; 61708dc6cbSAsias He close(fd); 629f9207c5SSasha Levin return ERR_PTR(r); 63708dc6cbSAsias He } 64708dc6cbSAsias He 65063e87a0SAsias He /* 66063e87a0SAsias He * FIXME: This will not work on 32-bit host because we can not 67063e87a0SAsias He * mmap large disk. There is not enough virtual address space 68063e87a0SAsias He * in 32-bit host. However, this works on 64-bit host. 69063e87a0SAsias He */ 70*d62e8ee0SJean-Philippe Brucker return disk_image__new(fd, size, &blk_dev_ops, DISK_IMAGE_REGULAR); 71708dc6cbSAsias He } 72