1c9310ac4SAsias He #include "kvm/disk-image.h" 2c9310ac4SAsias He 39f9207c5SSasha Levin #include <linux/err.h> 49f9207c5SSasha Levin 5*30a9aa69SJean-Philippe Brucker ssize_t raw_image__read_sync(struct disk_image *disk, u64 sector, const struct iovec *iov, 65af21162SSasha Levin int iovcount, void *param) 7c9310ac4SAsias He { 8*30a9aa69SJean-Philippe Brucker return preadv_in_full(disk->fd, iov, iovcount, sector << SECTOR_SHIFT); 9c9310ac4SAsias He } 10c9310ac4SAsias He 11*30a9aa69SJean-Philippe Brucker ssize_t raw_image__write_sync(struct disk_image *disk, u64 sector, 12*30a9aa69SJean-Philippe Brucker const struct iovec *iov, int iovcount, 13*30a9aa69SJean-Philippe Brucker void *param) 14c9310ac4SAsias He { 15*30a9aa69SJean-Philippe Brucker return pwritev_in_full(disk->fd, iov, iovcount, sector << SECTOR_SHIFT); 16c9310ac4SAsias He } 17c9310ac4SAsias He 18dcd3cd8eSAsias He ssize_t raw_image__read_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, 195af21162SSasha Levin int iovcount, void *param) 20c9310ac4SAsias He { 21c9310ac4SAsias He u64 offset = sector << SECTOR_SHIFT; 229d15c39aSSasha Levin ssize_t total = 0; 23c9310ac4SAsias He 242534c9b6SSasha Levin while (iovcount--) { 252534c9b6SSasha Levin memcpy(iov->iov_base, disk->priv + offset, iov->iov_len); 26c9310ac4SAsias He 272534c9b6SSasha Levin sector += iov->iov_len >> SECTOR_SHIFT; 289d15c39aSSasha Levin offset += iov->iov_len; 299d15c39aSSasha Levin total += iov->iov_len; 302534c9b6SSasha Levin iov++; 31c9310ac4SAsias He } 32c9310ac4SAsias He 332534c9b6SSasha Levin return total; 342534c9b6SSasha Levin } 352534c9b6SSasha Levin 36dcd3cd8eSAsias He ssize_t raw_image__write_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, 375af21162SSasha Levin int iovcount, void *param) 38c9310ac4SAsias He { 39c9310ac4SAsias He u64 offset = sector << SECTOR_SHIFT; 409d15c39aSSasha Levin ssize_t total = 0; 41c9310ac4SAsias He 422534c9b6SSasha Levin while (iovcount--) { 432534c9b6SSasha Levin memcpy(disk->priv + offset, iov->iov_base, iov->iov_len); 44c9310ac4SAsias He 452534c9b6SSasha Levin sector += iov->iov_len >> SECTOR_SHIFT; 469d15c39aSSasha Levin offset += iov->iov_len; 479d15c39aSSasha Levin total += iov->iov_len; 482534c9b6SSasha Levin iov++; 492534c9b6SSasha Levin } 50c9310ac4SAsias He 512534c9b6SSasha Levin return total; 52c9310ac4SAsias He } 53c9310ac4SAsias He 5487ee33c8SAsias He int raw_image__close(struct disk_image *disk) 55c9310ac4SAsias He { 5672133dd2SAsias He int ret = 0; 5772133dd2SAsias He 58c9310ac4SAsias He if (disk->priv != MAP_FAILED) 5972133dd2SAsias He ret = munmap(disk->priv, disk->size); 6072133dd2SAsias He 6172133dd2SAsias He return ret; 62c9310ac4SAsias He } 63c9310ac4SAsias He 6487ee33c8SAsias He /* 6587ee33c8SAsias He * multiple buffer based disk image operations 6687ee33c8SAsias He */ 672534c9b6SSasha Levin static struct disk_image_operations raw_image_regular_ops = { 68dcd3cd8eSAsias He .read = raw_image__read, 69dcd3cd8eSAsias He .write = raw_image__write, 70c9310ac4SAsias He }; 71c9310ac4SAsias He 729d15c39aSSasha Levin struct disk_image_operations ro_ops = { 73dcd3cd8eSAsias He .read = raw_image__read_mmap, 74dcd3cd8eSAsias He .write = raw_image__write_mmap, 7587ee33c8SAsias He .close = raw_image__close, 76c9310ac4SAsias He }; 77c9310ac4SAsias He 789d15c39aSSasha Levin struct disk_image_operations ro_ops_nowrite = { 79dcd3cd8eSAsias He .read = raw_image__read, 809d15c39aSSasha Levin }; 819d15c39aSSasha Levin 82c9310ac4SAsias He struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly) 83c9310ac4SAsias He { 84f41a132bSSasha Levin struct disk_image *disk; 857d22135fSAsias He 869d15c39aSSasha Levin if (readonly) { 877d22135fSAsias He /* 887d22135fSAsias He * Use mmap's MAP_PRIVATE to implement non-persistent write 897d22135fSAsias He * FIXME: This does not work on 32-bit host. 907d22135fSAsias He */ 919d15c39aSSasha Levin struct disk_image *disk; 929d15c39aSSasha Levin 939d15c39aSSasha Levin disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP); 949f9207c5SSasha Levin if (IS_ERR_OR_NULL(disk)) { 959d15c39aSSasha Levin disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR); 967dd56391SSasha Levin #ifdef CONFIG_HAS_AIO 979f9207c5SSasha Levin if (!IS_ERR_OR_NULL(disk)) 98f41a132bSSasha Levin disk->async = 1; 99f41a132bSSasha Levin #endif 1009d15c39aSSasha Levin } 1019d15c39aSSasha Levin 1029d15c39aSSasha Levin return disk; 1039d15c39aSSasha Levin } else { 1047d22135fSAsias He /* 1057d22135fSAsias He * Use read/write instead of mmap 1067d22135fSAsias He */ 107f41a132bSSasha Levin disk = disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR); 1087dd56391SSasha Levin #ifdef CONFIG_HAS_AIO 1099f9207c5SSasha Levin if (!IS_ERR_OR_NULL(disk)) 110f41a132bSSasha Levin disk->async = 1; 111f41a132bSSasha Levin #endif 112f41a132bSSasha Levin return disk; 113c9310ac4SAsias He } 1149d15c39aSSasha Levin } 115