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