1 #include "kvm/disk-image.h" 2 3 #ifdef CONFIG_HAS_AIO 4 #include <libaio.h> 5 #endif 6 7 ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, 8 int iovcount, void *param) 9 { 10 u64 offset = sector << SECTOR_SHIFT; 11 12 #ifdef CONFIG_HAS_AIO 13 struct iocb iocb; 14 15 return aio_preadv(disk->ctx, &iocb, disk->fd, iov, iovcount, offset, 16 disk->evt, param); 17 #else 18 return preadv_in_full(disk->fd, iov, iovcount, offset); 19 #endif 20 } 21 22 ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, 23 int iovcount, void *param) 24 { 25 u64 offset = sector << SECTOR_SHIFT; 26 27 #ifdef CONFIG_HAS_AIO 28 struct iocb iocb; 29 30 return aio_pwritev(disk->ctx, &iocb, disk->fd, iov, iovcount, offset, 31 disk->evt, param); 32 #else 33 return pwritev_in_full(disk->fd, iov, iovcount, offset); 34 #endif 35 } 36 37 ssize_t raw_image__read_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(iov->iov_base, disk->priv + offset, 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 ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, 56 int iovcount, void *param) 57 { 58 u64 offset = sector << SECTOR_SHIFT; 59 ssize_t total = 0; 60 61 while (iovcount--) { 62 memcpy(disk->priv + offset, iov->iov_base, iov->iov_len); 63 64 sector += iov->iov_len >> SECTOR_SHIFT; 65 offset += iov->iov_len; 66 total += iov->iov_len; 67 iov++; 68 } 69 70 return total; 71 } 72 73 int raw_image__close(struct disk_image *disk) 74 { 75 int ret = 0; 76 77 if (disk->priv != MAP_FAILED) 78 ret = munmap(disk->priv, disk->size); 79 80 close(disk->evt); 81 82 #ifdef CONFIG_HAS_VIRTIO 83 io_destroy(disk->ctx); 84 #endif 85 86 return ret; 87 } 88 89 /* 90 * multiple buffer based disk image operations 91 */ 92 static struct disk_image_operations raw_image_regular_ops = { 93 .read_sector = raw_image__read_sector, 94 .write_sector = raw_image__write_sector, 95 }; 96 97 struct disk_image_operations ro_ops = { 98 .read_sector = raw_image__read_sector_mmap, 99 .write_sector = raw_image__write_sector_mmap, 100 .close = raw_image__close, 101 }; 102 103 struct disk_image_operations ro_ops_nowrite = { 104 .read_sector = raw_image__read_sector, 105 .write_sector = raw_image__write_sector, 106 }; 107 108 struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly) 109 { 110 struct disk_image *disk; 111 112 if (readonly) { 113 /* 114 * Use mmap's MAP_PRIVATE to implement non-persistent write 115 * FIXME: This does not work on 32-bit host. 116 */ 117 struct disk_image *disk; 118 119 disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP); 120 if (disk == NULL) { 121 ro_ops = raw_image_regular_ops; 122 123 disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR); 124 #ifdef CONFIG_HAS_VIRTIO 125 if (disk) 126 disk->async = 1; 127 #endif 128 } 129 130 return disk; 131 } else { 132 /* 133 * Use read/write instead of mmap 134 */ 135 disk = disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR); 136 #ifdef CONFIG_HAS_VIRTIO 137 if (disk) 138 disk->async = 1; 139 #endif 140 return disk; 141 } 142 } 143