xref: /kvmtool/disk/raw.c (revision 2790307c3d6d2aad838e1eef76ec0aa21b110698)
1c9310ac4SAsias He #include "kvm/disk-image.h"
2c9310ac4SAsias He 
39f9207c5SSasha Levin #include <linux/err.h>
49f9207c5SSasha Levin 
raw_image__read_sync(struct disk_image * disk,u64 sector,const struct iovec * iov,int iovcount,void * param)530a9aa69SJean-Philippe Brucker ssize_t raw_image__read_sync(struct disk_image *disk, u64 sector, const struct iovec *iov,
65af21162SSasha Levin 				int iovcount, void *param)
7c9310ac4SAsias He {
830a9aa69SJean-Philippe Brucker 	return preadv_in_full(disk->fd, iov, iovcount, sector << SECTOR_SHIFT);
9c9310ac4SAsias He }
10c9310ac4SAsias He 
raw_image__write_sync(struct disk_image * disk,u64 sector,const struct iovec * iov,int iovcount,void * param)1130a9aa69SJean-Philippe Brucker ssize_t raw_image__write_sync(struct disk_image *disk, u64 sector,
1230a9aa69SJean-Philippe Brucker 			      const struct iovec *iov, int iovcount,
1330a9aa69SJean-Philippe Brucker 			      void *param)
14c9310ac4SAsias He {
1530a9aa69SJean-Philippe Brucker 	return pwritev_in_full(disk->fd, iov, iovcount, sector << SECTOR_SHIFT);
16c9310ac4SAsias He }
17c9310ac4SAsias He 
raw_image__read_mmap(struct disk_image * disk,u64 sector,const struct iovec * iov,int iovcount,void * param)18dcd3cd8eSAsias He ssize_t raw_image__read_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
195af21162SSasha Levin 				int iovcount, void *param)
20c9310ac4SAsias He {
21c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
229d15c39aSSasha Levin 	ssize_t total = 0;
23c9310ac4SAsias He 
242534c9b6SSasha Levin 	while (iovcount--) {
252534c9b6SSasha Levin 		memcpy(iov->iov_base, disk->priv + offset, iov->iov_len);
26c9310ac4SAsias He 
272534c9b6SSasha Levin 		sector	+= iov->iov_len >> SECTOR_SHIFT;
289d15c39aSSasha Levin 		offset	+= iov->iov_len;
299d15c39aSSasha Levin 		total	+= iov->iov_len;
302534c9b6SSasha Levin 		iov++;
31c9310ac4SAsias He 	}
32c9310ac4SAsias He 
332534c9b6SSasha Levin 	return total;
342534c9b6SSasha Levin }
352534c9b6SSasha Levin 
raw_image__write_mmap(struct disk_image * disk,u64 sector,const struct iovec * iov,int iovcount,void * param)36dcd3cd8eSAsias He ssize_t raw_image__write_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
375af21162SSasha Levin 				int iovcount, void *param)
38c9310ac4SAsias He {
39c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
409d15c39aSSasha Levin 	ssize_t total = 0;
41c9310ac4SAsias He 
422534c9b6SSasha Levin 	while (iovcount--) {
432534c9b6SSasha Levin 		memcpy(disk->priv + offset, iov->iov_base, iov->iov_len);
44c9310ac4SAsias He 
452534c9b6SSasha Levin 		sector	+= iov->iov_len >> SECTOR_SHIFT;
469d15c39aSSasha Levin 		offset	+= iov->iov_len;
479d15c39aSSasha Levin 		total	+= iov->iov_len;
482534c9b6SSasha Levin 		iov++;
492534c9b6SSasha Levin 	}
50c9310ac4SAsias He 
512534c9b6SSasha Levin 	return total;
52c9310ac4SAsias He }
53c9310ac4SAsias He 
raw_image__close(struct disk_image * disk)5487ee33c8SAsias He int raw_image__close(struct disk_image *disk)
55c9310ac4SAsias He {
5672133dd2SAsias He 	int ret = 0;
5772133dd2SAsias He 
58c9310ac4SAsias He 	if (disk->priv != MAP_FAILED)
5972133dd2SAsias He 		ret = munmap(disk->priv, disk->size);
6072133dd2SAsias He 
6172133dd2SAsias He 	return ret;
62c9310ac4SAsias He }
63c9310ac4SAsias He 
6487ee33c8SAsias He /*
6587ee33c8SAsias He  * multiple buffer based disk image operations
6687ee33c8SAsias He  */
672534c9b6SSasha Levin static struct disk_image_operations raw_image_regular_ops = {
68dcd3cd8eSAsias He 	.read	= raw_image__read,
69dcd3cd8eSAsias He 	.write	= raw_image__write,
70*2790307cSJean-Philippe Brucker 	.wait	= raw_image__wait,
71d62e8ee0SJean-Philippe Brucker 	.async	= true,
72c9310ac4SAsias He };
73c9310ac4SAsias He 
749d15c39aSSasha Levin struct disk_image_operations ro_ops = {
75dcd3cd8eSAsias He 	.read	= raw_image__read_mmap,
76dcd3cd8eSAsias He 	.write	= raw_image__write_mmap,
7787ee33c8SAsias He 	.close	= raw_image__close,
78c9310ac4SAsias He };
79c9310ac4SAsias He 
809d15c39aSSasha Levin struct disk_image_operations ro_ops_nowrite = {
81dcd3cd8eSAsias He 	.read	= raw_image__read,
82*2790307cSJean-Philippe Brucker 	.wait	= raw_image__wait,
83d62e8ee0SJean-Philippe Brucker 	.async	= true,
849d15c39aSSasha Levin };
859d15c39aSSasha Levin 
raw_image__probe(int fd,struct stat * st,bool readonly)86c9310ac4SAsias He struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
87c9310ac4SAsias He {
889d15c39aSSasha Levin 	if (readonly) {
897d22135fSAsias He 		/*
907d22135fSAsias He 		 * Use mmap's MAP_PRIVATE to implement non-persistent write
917d22135fSAsias He 		 * FIXME: This does not work on 32-bit host.
927d22135fSAsias He 		 */
939d15c39aSSasha Levin 		struct disk_image *disk;
949d15c39aSSasha Levin 
959d15c39aSSasha Levin 		disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP);
969f9207c5SSasha Levin 		if (IS_ERR_OR_NULL(disk)) {
979d15c39aSSasha Levin 			disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR);
989d15c39aSSasha Levin 		}
999d15c39aSSasha Levin 
1009d15c39aSSasha Levin 		return disk;
1019d15c39aSSasha Levin 	} else {
1027d22135fSAsias He 		/*
1037d22135fSAsias He 		 * Use read/write instead of mmap
1047d22135fSAsias He 		 */
105d62e8ee0SJean-Philippe Brucker 		return disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR);
106c9310ac4SAsias He 	}
1079d15c39aSSasha Levin }
108