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