1 #include "kvm/disk-image.h" 2 3 ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, 4 int iovcount, void *param) 5 { 6 u64 offset = sector << SECTOR_SHIFT; 7 8 return preadv_in_full(disk->fd, iov, iovcount, offset); 9 } 10 11 ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, 12 int iovcount, void *param) 13 { 14 u64 offset = sector << SECTOR_SHIFT; 15 16 return pwritev_in_full(disk->fd, iov, iovcount, offset); 17 } 18 19 ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, 20 int iovcount, void *param) 21 { 22 u64 offset = sector << SECTOR_SHIFT; 23 ssize_t total = 0; 24 25 while (iovcount--) { 26 memcpy(iov->iov_base, disk->priv + offset, iov->iov_len); 27 28 sector += iov->iov_len >> SECTOR_SHIFT; 29 offset += iov->iov_len; 30 total += iov->iov_len; 31 iov++; 32 } 33 34 return total; 35 } 36 37 ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, 38 int iovcount, void *param) 39 { 40 u64 offset = sector << SECTOR_SHIFT; 41 ssize_t total = 0; 42 43 while (iovcount--) { 44 memcpy(disk->priv + offset, iov->iov_base, iov->iov_len); 45 46 sector += iov->iov_len >> SECTOR_SHIFT; 47 offset += iov->iov_len; 48 total += iov->iov_len; 49 iov++; 50 } 51 52 return total; 53 } 54 55 int raw_image__close(struct disk_image *disk) 56 { 57 int ret = 0; 58 59 if (disk->priv != MAP_FAILED) 60 ret = munmap(disk->priv, disk->size); 61 62 return ret; 63 } 64 65 /* 66 * multiple buffer based disk image operations 67 */ 68 static struct disk_image_operations raw_image_regular_ops = { 69 .read_sector = raw_image__read_sector, 70 .write_sector = raw_image__write_sector, 71 }; 72 73 struct disk_image_operations ro_ops = { 74 .read_sector = raw_image__read_sector_mmap, 75 .write_sector = raw_image__write_sector_mmap, 76 .close = raw_image__close, 77 }; 78 79 struct disk_image_operations ro_ops_nowrite = { 80 .read_sector = raw_image__read_sector, 81 .write_sector = raw_image__write_sector, 82 }; 83 84 struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly) 85 { 86 87 if (readonly) { 88 /* 89 * Use mmap's MAP_PRIVATE to implement non-persistent write 90 * FIXME: This does not work on 32-bit host. 91 */ 92 struct disk_image *disk; 93 94 disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP); 95 if (disk == NULL) { 96 ro_ops = raw_image_regular_ops; 97 ro_ops.write_sector = NULL; 98 disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR); 99 } 100 101 return disk; 102 } else { 103 /* 104 * Use read/write instead of mmap 105 */ 106 return disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR); 107 } 108 } 109