1708dc6cbSAsias He #include "kvm/disk-image.h" 2708dc6cbSAsias He 39f9207c5SSasha Levin #include <linux/err.h> 4*58fd2b7bSAsias 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 = { 1087ee33c8SAsias He .read_sector = raw_image__read_sector, 1187ee33c8SAsias He .write_sector = raw_image__write_sector, 12708dc6cbSAsias He }; 13708dc6cbSAsias He 14*58fd2b7bSAsias He static bool is_mounted(struct stat *st) 15*58fd2b7bSAsias He { 16*58fd2b7bSAsias He struct stat st_buf; 17*58fd2b7bSAsias He struct mntent *mnt; 18*58fd2b7bSAsias He FILE *f; 19*58fd2b7bSAsias He 20*58fd2b7bSAsias He f = setmntent("/proc/mounts", "r"); 21*58fd2b7bSAsias He if (!f) 22*58fd2b7bSAsias He return false; 23*58fd2b7bSAsias He 24*58fd2b7bSAsias He while ((mnt = getmntent(f)) != NULL) { 25*58fd2b7bSAsias He if (stat(mnt->mnt_fsname, &st_buf) == 0 && 26*58fd2b7bSAsias He S_ISBLK(st_buf.st_mode) && st->st_rdev == st_buf.st_rdev) { 27*58fd2b7bSAsias He fclose(f); 28*58fd2b7bSAsias He return true; 29*58fd2b7bSAsias He } 30*58fd2b7bSAsias He } 31*58fd2b7bSAsias He 32*58fd2b7bSAsias He fclose(f); 33*58fd2b7bSAsias He return false; 34*58fd2b7bSAsias He } 35*58fd2b7bSAsias He 36708dc6cbSAsias He struct disk_image *blkdev__probe(const char *filename, struct stat *st) 37708dc6cbSAsias He { 38*58fd2b7bSAsias He struct disk_image *disk; 399f9207c5SSasha Levin int fd, r; 40*58fd2b7bSAsias He u64 size; 41708dc6cbSAsias He 42708dc6cbSAsias He if (!S_ISBLK(st->st_mode)) 439f9207c5SSasha Levin return ERR_PTR(-EINVAL); 44708dc6cbSAsias He 45*58fd2b7bSAsias He if (is_mounted(st)) { 46*58fd2b7bSAsias He pr_err("Block device %s is already mounted! Unmount before use.", 47*58fd2b7bSAsias He filename); 48*58fd2b7bSAsias He return ERR_PTR(-EINVAL); 49*58fd2b7bSAsias He } 50*58fd2b7bSAsias 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 */ 55*58fd2b7bSAsias He fd = open(filename, O_RDWR); 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*58fd2b7bSAsias He disk = disk_image__new(fd, size, &blk_dev_ops, DISK_IMAGE_REGULAR); 71*58fd2b7bSAsias He #ifdef CONFIG_HAS_AIO 72*58fd2b7bSAsias He if (!IS_ERR_OR_NULL(disk)) 73*58fd2b7bSAsias He disk->async = 1; 74*58fd2b7bSAsias He #endif 75*58fd2b7bSAsias He return disk; 76708dc6cbSAsias He } 77