xref: /kvmtool/disk/raw.c (revision 5af21162e519d182f576b6617f2b28ecc4485bda)
1c9310ac4SAsias He #include "kvm/disk-image.h"
2c9310ac4SAsias He 
3*5af21162SSasha Levin ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, const struct iovec *iov,
4*5af21162SSasha Levin 				int iovcount, void *param)
5c9310ac4SAsias He {
6c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
7c9310ac4SAsias He 
8c9310ac4SAsias He 	return preadv_in_full(disk->fd, iov, iovcount, offset);
9c9310ac4SAsias He }
10c9310ac4SAsias He 
11*5af21162SSasha Levin ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, const struct iovec *iov,
12*5af21162SSasha Levin 				int iovcount, void *param)
13c9310ac4SAsias He {
14c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
15c9310ac4SAsias He 
16c9310ac4SAsias He 	return pwritev_in_full(disk->fd, iov, iovcount, offset);
17c9310ac4SAsias He }
18c9310ac4SAsias He 
19*5af21162SSasha Levin ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
20*5af21162SSasha Levin 				int iovcount, void *param)
21c9310ac4SAsias He {
22c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
239d15c39aSSasha Levin 	ssize_t total = 0;
24c9310ac4SAsias He 
252534c9b6SSasha Levin 	while (iovcount--) {
262534c9b6SSasha Levin 		memcpy(iov->iov_base, disk->priv + offset, iov->iov_len);
27c9310ac4SAsias He 
282534c9b6SSasha Levin 		sector	+= iov->iov_len >> SECTOR_SHIFT;
299d15c39aSSasha Levin 		offset	+= iov->iov_len;
309d15c39aSSasha Levin 		total	+= iov->iov_len;
312534c9b6SSasha Levin 		iov++;
32c9310ac4SAsias He 	}
33c9310ac4SAsias He 
342534c9b6SSasha Levin 	return total;
352534c9b6SSasha Levin }
362534c9b6SSasha Levin 
37*5af21162SSasha Levin ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
38*5af21162SSasha Levin 				int iovcount, void *param)
39c9310ac4SAsias He {
40c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
419d15c39aSSasha Levin 	ssize_t total = 0;
42c9310ac4SAsias He 
432534c9b6SSasha Levin 	while (iovcount--) {
442534c9b6SSasha Levin 		memcpy(disk->priv + offset, iov->iov_base, iov->iov_len);
45c9310ac4SAsias He 
462534c9b6SSasha Levin 		sector	+= iov->iov_len >> SECTOR_SHIFT;
479d15c39aSSasha Levin 		offset	+= iov->iov_len;
489d15c39aSSasha Levin 		total	+= iov->iov_len;
492534c9b6SSasha Levin 		iov++;
502534c9b6SSasha Levin 	}
51c9310ac4SAsias He 
522534c9b6SSasha Levin 	return total;
53c9310ac4SAsias He }
54c9310ac4SAsias He 
5587ee33c8SAsias He int raw_image__close(struct disk_image *disk)
56c9310ac4SAsias He {
5772133dd2SAsias He 	int ret = 0;
5872133dd2SAsias He 
59c9310ac4SAsias He 	if (disk->priv != MAP_FAILED)
6072133dd2SAsias He 		ret = munmap(disk->priv, disk->size);
6172133dd2SAsias He 
6272133dd2SAsias He 	return ret;
63c9310ac4SAsias He }
64c9310ac4SAsias He 
6587ee33c8SAsias He /*
6687ee33c8SAsias He  * multiple buffer based disk image operations
6787ee33c8SAsias He  */
682534c9b6SSasha Levin static struct disk_image_operations raw_image_regular_ops = {
692534c9b6SSasha Levin 	.read_sector	= raw_image__read_sector,
702534c9b6SSasha Levin 	.write_sector	= raw_image__write_sector,
71c9310ac4SAsias He };
72c9310ac4SAsias He 
739d15c39aSSasha Levin struct disk_image_operations ro_ops = {
742534c9b6SSasha Levin 	.read_sector	= raw_image__read_sector_mmap,
752534c9b6SSasha Levin 	.write_sector	= raw_image__write_sector_mmap,
7687ee33c8SAsias He 	.close		= raw_image__close,
77c9310ac4SAsias He };
78c9310ac4SAsias He 
799d15c39aSSasha Levin struct disk_image_operations ro_ops_nowrite = {
809d15c39aSSasha Levin 	.read_sector	= raw_image__read_sector,
819d15c39aSSasha Levin 	.write_sector	= raw_image__write_sector,
829d15c39aSSasha Levin };
839d15c39aSSasha Levin 
84c9310ac4SAsias He struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
85c9310ac4SAsias He {
867d22135fSAsias He 
879d15c39aSSasha Levin 	if (readonly) {
887d22135fSAsias He 		/*
897d22135fSAsias He 		 * Use mmap's MAP_PRIVATE to implement non-persistent write
907d22135fSAsias He 		 * FIXME: This does not work on 32-bit host.
917d22135fSAsias He 		 */
929d15c39aSSasha Levin 		struct disk_image *disk;
939d15c39aSSasha Levin 
949d15c39aSSasha Levin 		disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP);
959d15c39aSSasha Levin 		if (disk == NULL) {
969d15c39aSSasha Levin 			ro_ops = raw_image_regular_ops;
979d15c39aSSasha Levin 			ro_ops.write_sector = NULL;
989d15c39aSSasha Levin 			disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR);
999d15c39aSSasha Levin 		}
1009d15c39aSSasha Levin 
1019d15c39aSSasha Levin 		return disk;
1029d15c39aSSasha Levin 	} else {
1037d22135fSAsias He 		/*
1047d22135fSAsias He 		 * Use read/write instead of mmap
1057d22135fSAsias He 		 */
1062534c9b6SSasha Levin 		return disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR);
107c9310ac4SAsias He 	}
1089d15c39aSSasha Levin }
109