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