xref: /kvmtool/disk/raw.c (revision 2790307c3d6d2aad838e1eef76ec0aa21b110698)
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