xref: /kvmtool/disk/raw.c (revision 9d15c39a6e86c36bf196f7c0627963194df27701)
1c9310ac4SAsias He #include "kvm/disk-image.h"
2c9310ac4SAsias He 
32534c9b6SSasha Levin ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
4c9310ac4SAsias He {
5c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
6c9310ac4SAsias He 
7c9310ac4SAsias He 	return preadv_in_full(disk->fd, iov, iovcount, offset);
8c9310ac4SAsias He }
9c9310ac4SAsias He 
102534c9b6SSasha Levin ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
11c9310ac4SAsias He {
12c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
13c9310ac4SAsias He 
14c9310ac4SAsias He 	return pwritev_in_full(disk->fd, iov, iovcount, offset);
15c9310ac4SAsias He }
16c9310ac4SAsias He 
172534c9b6SSasha Levin ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
18c9310ac4SAsias He {
19c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
20*9d15c39aSSasha Levin 	ssize_t total = 0;
21c9310ac4SAsias He 
222534c9b6SSasha Levin 	while (iovcount--) {
232534c9b6SSasha Levin 		memcpy(iov->iov_base, disk->priv + offset, iov->iov_len);
24c9310ac4SAsias He 
252534c9b6SSasha Levin 		sector	+= iov->iov_len >> SECTOR_SHIFT;
26*9d15c39aSSasha Levin 		offset	+= iov->iov_len;
27*9d15c39aSSasha Levin 		total	+= iov->iov_len;
282534c9b6SSasha Levin 		iov++;
29c9310ac4SAsias He 	}
30c9310ac4SAsias He 
312534c9b6SSasha Levin 	return total;
322534c9b6SSasha Levin }
332534c9b6SSasha Levin 
342534c9b6SSasha Levin ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
35c9310ac4SAsias He {
36c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
37*9d15c39aSSasha Levin 	ssize_t total = 0;
38c9310ac4SAsias He 
392534c9b6SSasha Levin 	while (iovcount--) {
402534c9b6SSasha Levin 		memcpy(disk->priv + offset, iov->iov_base, iov->iov_len);
41c9310ac4SAsias He 
422534c9b6SSasha Levin 		sector	+= iov->iov_len >> SECTOR_SHIFT;
43*9d15c39aSSasha Levin 		offset	+= iov->iov_len;
44*9d15c39aSSasha Levin 		total	+= iov->iov_len;
452534c9b6SSasha Levin 		iov++;
462534c9b6SSasha Levin 	}
47c9310ac4SAsias He 
482534c9b6SSasha Levin 	return total;
49c9310ac4SAsias He }
50c9310ac4SAsias He 
5187ee33c8SAsias He int raw_image__close(struct disk_image *disk)
52c9310ac4SAsias He {
5372133dd2SAsias He 	int ret = 0;
5472133dd2SAsias He 
55c9310ac4SAsias He 	if (disk->priv != MAP_FAILED)
5672133dd2SAsias He 		ret = munmap(disk->priv, disk->size);
5772133dd2SAsias He 
5872133dd2SAsias He 	return ret;
59c9310ac4SAsias He }
60c9310ac4SAsias He 
6187ee33c8SAsias He /*
6287ee33c8SAsias He  * multiple buffer based disk image operations
6387ee33c8SAsias He  */
642534c9b6SSasha Levin static struct disk_image_operations raw_image_regular_ops = {
652534c9b6SSasha Levin 	.read_sector	= raw_image__read_sector,
662534c9b6SSasha Levin 	.write_sector	= raw_image__write_sector,
67c9310ac4SAsias He };
68c9310ac4SAsias He 
69*9d15c39aSSasha Levin struct disk_image_operations ro_ops = {
702534c9b6SSasha Levin 	.read_sector	= raw_image__read_sector_mmap,
712534c9b6SSasha Levin 	.write_sector	= raw_image__write_sector_mmap,
7287ee33c8SAsias He 	.close		= raw_image__close,
73c9310ac4SAsias He };
74c9310ac4SAsias He 
75*9d15c39aSSasha Levin struct disk_image_operations ro_ops_nowrite = {
76*9d15c39aSSasha Levin 	.read_sector	= raw_image__read_sector,
77*9d15c39aSSasha Levin 	.write_sector	= raw_image__write_sector,
78*9d15c39aSSasha Levin };
79*9d15c39aSSasha Levin 
80c9310ac4SAsias He struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
81c9310ac4SAsias He {
827d22135fSAsias He 
83*9d15c39aSSasha Levin 	if (readonly) {
847d22135fSAsias He 		/*
857d22135fSAsias He 		 * Use mmap's MAP_PRIVATE to implement non-persistent write
867d22135fSAsias He 		 * FIXME: This does not work on 32-bit host.
877d22135fSAsias He 		 */
88*9d15c39aSSasha Levin 		struct disk_image *disk;
89*9d15c39aSSasha Levin 
90*9d15c39aSSasha Levin 		disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP);
91*9d15c39aSSasha Levin 		if (disk == NULL) {
92*9d15c39aSSasha Levin 			ro_ops = raw_image_regular_ops;
93*9d15c39aSSasha Levin 			ro_ops.write_sector = NULL;
94*9d15c39aSSasha Levin 			disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR);
95*9d15c39aSSasha Levin 		}
96*9d15c39aSSasha Levin 
97*9d15c39aSSasha Levin 		return disk;
98*9d15c39aSSasha Levin 	} else {
997d22135fSAsias He 		/*
1007d22135fSAsias He 		 * Use read/write instead of mmap
1017d22135fSAsias He 		 */
1022534c9b6SSasha Levin 		return disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR);
103c9310ac4SAsias He 	}
104*9d15c39aSSasha Levin }
105