xref: /kvmtool/disk/raw.c (revision 9f9207c5ad925aebcdad11d5145d2da0cd4a17aa)
1c9310ac4SAsias He #include "kvm/disk-image.h"
2c9310ac4SAsias He 
3*9f9207c5SSasha Levin #include <linux/err.h>
4*9f9207c5SSasha Levin 
5f41a132bSSasha Levin #ifdef CONFIG_HAS_AIO
6f41a132bSSasha Levin #include <libaio.h>
7f41a132bSSasha Levin #endif
8f41a132bSSasha Levin 
95af21162SSasha Levin ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, const struct iovec *iov,
105af21162SSasha Levin 				int iovcount, void *param)
11c9310ac4SAsias He {
12c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
13c9310ac4SAsias He 
14f41a132bSSasha Levin #ifdef CONFIG_HAS_AIO
15f41a132bSSasha Levin 	struct iocb iocb;
16f41a132bSSasha Levin 
17f41a132bSSasha Levin 	return aio_preadv(disk->ctx, &iocb, disk->fd, iov, iovcount, offset,
18f41a132bSSasha Levin 				disk->evt, param);
19f41a132bSSasha Levin #else
20c9310ac4SAsias He 	return preadv_in_full(disk->fd, iov, iovcount, offset);
21f41a132bSSasha Levin #endif
22c9310ac4SAsias He }
23c9310ac4SAsias He 
245af21162SSasha Levin ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, const struct iovec *iov,
255af21162SSasha Levin 				int iovcount, void *param)
26c9310ac4SAsias He {
27c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
28c9310ac4SAsias He 
29f41a132bSSasha Levin #ifdef CONFIG_HAS_AIO
30f41a132bSSasha Levin 	struct iocb iocb;
31f41a132bSSasha Levin 
32f41a132bSSasha Levin 	return aio_pwritev(disk->ctx, &iocb, disk->fd, iov, iovcount, offset,
33f41a132bSSasha Levin 				disk->evt, param);
34f41a132bSSasha Levin #else
35c9310ac4SAsias He 	return pwritev_in_full(disk->fd, iov, iovcount, offset);
36f41a132bSSasha Levin #endif
37c9310ac4SAsias He }
38c9310ac4SAsias He 
395af21162SSasha Levin ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
405af21162SSasha Levin 				int iovcount, void *param)
41c9310ac4SAsias He {
42c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
439d15c39aSSasha Levin 	ssize_t total = 0;
44c9310ac4SAsias He 
452534c9b6SSasha Levin 	while (iovcount--) {
462534c9b6SSasha Levin 		memcpy(iov->iov_base, disk->priv + offset, iov->iov_len);
47c9310ac4SAsias He 
482534c9b6SSasha Levin 		sector	+= iov->iov_len >> SECTOR_SHIFT;
499d15c39aSSasha Levin 		offset	+= iov->iov_len;
509d15c39aSSasha Levin 		total	+= iov->iov_len;
512534c9b6SSasha Levin 		iov++;
52c9310ac4SAsias He 	}
53c9310ac4SAsias He 
542534c9b6SSasha Levin 	return total;
552534c9b6SSasha Levin }
562534c9b6SSasha Levin 
575af21162SSasha Levin ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
585af21162SSasha Levin 				int iovcount, void *param)
59c9310ac4SAsias He {
60c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
619d15c39aSSasha Levin 	ssize_t total = 0;
62c9310ac4SAsias He 
632534c9b6SSasha Levin 	while (iovcount--) {
642534c9b6SSasha Levin 		memcpy(disk->priv + offset, iov->iov_base, iov->iov_len);
65c9310ac4SAsias He 
662534c9b6SSasha Levin 		sector	+= iov->iov_len >> SECTOR_SHIFT;
679d15c39aSSasha Levin 		offset	+= iov->iov_len;
689d15c39aSSasha Levin 		total	+= iov->iov_len;
692534c9b6SSasha Levin 		iov++;
702534c9b6SSasha Levin 	}
71c9310ac4SAsias He 
722534c9b6SSasha Levin 	return total;
73c9310ac4SAsias He }
74c9310ac4SAsias He 
7587ee33c8SAsias He int raw_image__close(struct disk_image *disk)
76c9310ac4SAsias He {
7772133dd2SAsias He 	int ret = 0;
7872133dd2SAsias He 
79c9310ac4SAsias He 	if (disk->priv != MAP_FAILED)
8072133dd2SAsias He 		ret = munmap(disk->priv, disk->size);
8172133dd2SAsias He 
82f41a132bSSasha Levin 	close(disk->evt);
83f41a132bSSasha Levin 
84f41a132bSSasha Levin #ifdef CONFIG_HAS_VIRTIO
85f41a132bSSasha Levin 	io_destroy(disk->ctx);
86f41a132bSSasha Levin #endif
87f41a132bSSasha Levin 
8872133dd2SAsias He 	return ret;
89c9310ac4SAsias He }
90c9310ac4SAsias He 
9187ee33c8SAsias He /*
9287ee33c8SAsias He  * multiple buffer based disk image operations
9387ee33c8SAsias He  */
942534c9b6SSasha Levin static struct disk_image_operations raw_image_regular_ops = {
952534c9b6SSasha Levin 	.read_sector	= raw_image__read_sector,
962534c9b6SSasha Levin 	.write_sector	= raw_image__write_sector,
97c9310ac4SAsias He };
98c9310ac4SAsias He 
999d15c39aSSasha Levin struct disk_image_operations ro_ops = {
1002534c9b6SSasha Levin 	.read_sector	= raw_image__read_sector_mmap,
1012534c9b6SSasha Levin 	.write_sector	= raw_image__write_sector_mmap,
10287ee33c8SAsias He 	.close		= raw_image__close,
103c9310ac4SAsias He };
104c9310ac4SAsias He 
1059d15c39aSSasha Levin struct disk_image_operations ro_ops_nowrite = {
1069d15c39aSSasha Levin 	.read_sector	= raw_image__read_sector,
1079d15c39aSSasha Levin };
1089d15c39aSSasha Levin 
109c9310ac4SAsias He struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
110c9310ac4SAsias He {
111f41a132bSSasha Levin 	struct disk_image *disk;
1127d22135fSAsias He 
1139d15c39aSSasha Levin 	if (readonly) {
1147d22135fSAsias He 		/*
1157d22135fSAsias He 		 * Use mmap's MAP_PRIVATE to implement non-persistent write
1167d22135fSAsias He 		 * FIXME: This does not work on 32-bit host.
1177d22135fSAsias He 		 */
1189d15c39aSSasha Levin 		struct disk_image *disk;
1199d15c39aSSasha Levin 
1209d15c39aSSasha Levin 		disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP);
121*9f9207c5SSasha Levin 		if (IS_ERR_OR_NULL(disk)) {
1229d15c39aSSasha Levin 			disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR);
1237dd56391SSasha Levin #ifdef CONFIG_HAS_AIO
124*9f9207c5SSasha Levin 			if (!IS_ERR_OR_NULL(disk))
125f41a132bSSasha Levin 				disk->async = 1;
126f41a132bSSasha Levin #endif
1279d15c39aSSasha Levin 		}
1289d15c39aSSasha Levin 
1299d15c39aSSasha Levin 		return disk;
1309d15c39aSSasha Levin 	} else {
1317d22135fSAsias He 		/*
1327d22135fSAsias He 		 * Use read/write instead of mmap
1337d22135fSAsias He 		 */
134f41a132bSSasha Levin 		disk = disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR);
1357dd56391SSasha Levin #ifdef CONFIG_HAS_AIO
136*9f9207c5SSasha Levin 		if (!IS_ERR_OR_NULL(disk))
137f41a132bSSasha Levin 			disk->async = 1;
138f41a132bSSasha Levin #endif
139f41a132bSSasha Levin 		return disk;
140c9310ac4SAsias He 	}
1419d15c39aSSasha Levin }
142