1 #include "kvm/disk-image.h"
2
3 #include <linux/err.h>
4
raw_image__read_sync(struct disk_image * disk,u64 sector,const struct iovec * iov,int iovcount,void * param)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
raw_image__write_sync(struct disk_image * disk,u64 sector,const struct iovec * iov,int iovcount,void * param)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
raw_image__read_mmap(struct disk_image * disk,u64 sector,const struct iovec * iov,int iovcount,void * param)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
raw_image__write_mmap(struct disk_image * disk,u64 sector,const struct iovec * iov,int iovcount,void * param)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
raw_image__close(struct disk_image * disk)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 .wait = raw_image__wait,
71 .async = true,
72 };
73
74 struct disk_image_operations ro_ops = {
75 .read = raw_image__read_mmap,
76 .write = raw_image__write_mmap,
77 .close = raw_image__close,
78 };
79
80 struct disk_image_operations ro_ops_nowrite = {
81 .read = raw_image__read,
82 .wait = raw_image__wait,
83 .async = true,
84 };
85
raw_image__probe(int fd,struct stat * st,bool readonly)86 struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
87 {
88 if (readonly) {
89 /*
90 * Use mmap's MAP_PRIVATE to implement non-persistent write
91 * FIXME: This does not work on 32-bit host.
92 */
93 struct disk_image *disk;
94
95 disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP);
96 if (IS_ERR_OR_NULL(disk)) {
97 disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR);
98 }
99
100 return disk;
101 } else {
102 /*
103 * Use read/write instead of mmap
104 */
105 return disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR);
106 }
107 }
108