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