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