1c9310ac4SAsias He #include "kvm/disk-image.h" 2c9310ac4SAsias He 3*f41a132bSSasha Levin #ifdef CONFIG_HAS_AIO 4*f41a132bSSasha Levin #include <libaio.h> 5*f41a132bSSasha Levin #endif 6*f41a132bSSasha Levin 75af21162SSasha Levin ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, 85af21162SSasha Levin int iovcount, void *param) 9c9310ac4SAsias He { 10c9310ac4SAsias He u64 offset = sector << SECTOR_SHIFT; 11c9310ac4SAsias He 12*f41a132bSSasha Levin #ifdef CONFIG_HAS_AIO 13*f41a132bSSasha Levin struct iocb iocb; 14*f41a132bSSasha Levin 15*f41a132bSSasha Levin return aio_preadv(disk->ctx, &iocb, disk->fd, iov, iovcount, offset, 16*f41a132bSSasha Levin disk->evt, param); 17*f41a132bSSasha Levin #else 18c9310ac4SAsias He return preadv_in_full(disk->fd, iov, iovcount, offset); 19*f41a132bSSasha Levin #endif 20c9310ac4SAsias He } 21c9310ac4SAsias He 225af21162SSasha Levin ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, 235af21162SSasha Levin int iovcount, void *param) 24c9310ac4SAsias He { 25c9310ac4SAsias He u64 offset = sector << SECTOR_SHIFT; 26c9310ac4SAsias He 27*f41a132bSSasha Levin #ifdef CONFIG_HAS_AIO 28*f41a132bSSasha Levin struct iocb iocb; 29*f41a132bSSasha Levin 30*f41a132bSSasha Levin return aio_pwritev(disk->ctx, &iocb, disk->fd, iov, iovcount, offset, 31*f41a132bSSasha Levin disk->evt, param); 32*f41a132bSSasha Levin #else 33c9310ac4SAsias He return pwritev_in_full(disk->fd, iov, iovcount, offset); 34*f41a132bSSasha Levin #endif 35c9310ac4SAsias He } 36c9310ac4SAsias He 375af21162SSasha Levin ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, 385af21162SSasha Levin int iovcount, void *param) 39c9310ac4SAsias He { 40c9310ac4SAsias He u64 offset = sector << SECTOR_SHIFT; 419d15c39aSSasha Levin ssize_t total = 0; 42c9310ac4SAsias He 432534c9b6SSasha Levin while (iovcount--) { 442534c9b6SSasha Levin memcpy(iov->iov_base, disk->priv + offset, iov->iov_len); 45c9310ac4SAsias He 462534c9b6SSasha Levin sector += iov->iov_len >> SECTOR_SHIFT; 479d15c39aSSasha Levin offset += iov->iov_len; 489d15c39aSSasha Levin total += iov->iov_len; 492534c9b6SSasha Levin iov++; 50c9310ac4SAsias He } 51c9310ac4SAsias He 522534c9b6SSasha Levin return total; 532534c9b6SSasha Levin } 542534c9b6SSasha Levin 555af21162SSasha Levin ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, 565af21162SSasha Levin int iovcount, void *param) 57c9310ac4SAsias He { 58c9310ac4SAsias He u64 offset = sector << SECTOR_SHIFT; 599d15c39aSSasha Levin ssize_t total = 0; 60c9310ac4SAsias He 612534c9b6SSasha Levin while (iovcount--) { 622534c9b6SSasha Levin memcpy(disk->priv + offset, iov->iov_base, iov->iov_len); 63c9310ac4SAsias He 642534c9b6SSasha Levin sector += iov->iov_len >> SECTOR_SHIFT; 659d15c39aSSasha Levin offset += iov->iov_len; 669d15c39aSSasha Levin total += iov->iov_len; 672534c9b6SSasha Levin iov++; 682534c9b6SSasha Levin } 69c9310ac4SAsias He 702534c9b6SSasha Levin return total; 71c9310ac4SAsias He } 72c9310ac4SAsias He 7387ee33c8SAsias He int raw_image__close(struct disk_image *disk) 74c9310ac4SAsias He { 7572133dd2SAsias He int ret = 0; 7672133dd2SAsias He 77c9310ac4SAsias He if (disk->priv != MAP_FAILED) 7872133dd2SAsias He ret = munmap(disk->priv, disk->size); 7972133dd2SAsias He 80*f41a132bSSasha Levin close(disk->evt); 81*f41a132bSSasha Levin 82*f41a132bSSasha Levin #ifdef CONFIG_HAS_VIRTIO 83*f41a132bSSasha Levin io_destroy(disk->ctx); 84*f41a132bSSasha Levin #endif 85*f41a132bSSasha Levin 8672133dd2SAsias He return ret; 87c9310ac4SAsias He } 88c9310ac4SAsias He 8987ee33c8SAsias He /* 9087ee33c8SAsias He * multiple buffer based disk image operations 9187ee33c8SAsias He */ 922534c9b6SSasha Levin static struct disk_image_operations raw_image_regular_ops = { 932534c9b6SSasha Levin .read_sector = raw_image__read_sector, 942534c9b6SSasha Levin .write_sector = raw_image__write_sector, 95c9310ac4SAsias He }; 96c9310ac4SAsias He 979d15c39aSSasha Levin struct disk_image_operations ro_ops = { 982534c9b6SSasha Levin .read_sector = raw_image__read_sector_mmap, 992534c9b6SSasha Levin .write_sector = raw_image__write_sector_mmap, 10087ee33c8SAsias He .close = raw_image__close, 101c9310ac4SAsias He }; 102c9310ac4SAsias He 1039d15c39aSSasha Levin struct disk_image_operations ro_ops_nowrite = { 1049d15c39aSSasha Levin .read_sector = raw_image__read_sector, 1059d15c39aSSasha Levin .write_sector = raw_image__write_sector, 1069d15c39aSSasha Levin }; 1079d15c39aSSasha Levin 108c9310ac4SAsias He struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly) 109c9310ac4SAsias He { 110*f41a132bSSasha Levin struct disk_image *disk; 1117d22135fSAsias He 1129d15c39aSSasha Levin if (readonly) { 1137d22135fSAsias He /* 1147d22135fSAsias He * Use mmap's MAP_PRIVATE to implement non-persistent write 1157d22135fSAsias He * FIXME: This does not work on 32-bit host. 1167d22135fSAsias He */ 1179d15c39aSSasha Levin struct disk_image *disk; 1189d15c39aSSasha Levin 1199d15c39aSSasha Levin disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP); 1209d15c39aSSasha Levin if (disk == NULL) { 1219d15c39aSSasha Levin ro_ops = raw_image_regular_ops; 122*f41a132bSSasha Levin 1239d15c39aSSasha Levin disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR); 124*f41a132bSSasha Levin #ifdef CONFIG_HAS_VIRTIO 125*f41a132bSSasha Levin if (disk) 126*f41a132bSSasha Levin disk->async = 1; 127*f41a132bSSasha Levin #endif 1289d15c39aSSasha Levin } 1299d15c39aSSasha Levin 1309d15c39aSSasha Levin return disk; 1319d15c39aSSasha Levin } else { 1327d22135fSAsias He /* 1337d22135fSAsias He * Use read/write instead of mmap 1347d22135fSAsias He */ 135*f41a132bSSasha Levin disk = disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR); 136*f41a132bSSasha Levin #ifdef CONFIG_HAS_VIRTIO 137*f41a132bSSasha Levin if (disk) 138*f41a132bSSasha Levin disk->async = 1; 139*f41a132bSSasha Levin #endif 140*f41a132bSSasha Levin return disk; 141c9310ac4SAsias He } 1429d15c39aSSasha Levin } 143