xref: /kvmtool/disk/raw.c (revision 7dd5639103024c5356a81d5e386b716f42c5a4e7)
1c9310ac4SAsias He #include "kvm/disk-image.h"
2c9310ac4SAsias He 
3f41a132bSSasha Levin #ifdef CONFIG_HAS_AIO
4f41a132bSSasha Levin #include <libaio.h>
5f41a132bSSasha Levin #endif
6f41a132bSSasha Levin 
75af21162SSasha Levin ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, const struct iovec *iov,
85af21162SSasha Levin 				int iovcount, void *param)
9c9310ac4SAsias He {
10c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
11c9310ac4SAsias He 
12f41a132bSSasha Levin #ifdef CONFIG_HAS_AIO
13f41a132bSSasha Levin 	struct iocb iocb;
14f41a132bSSasha Levin 
15f41a132bSSasha Levin 	return aio_preadv(disk->ctx, &iocb, disk->fd, iov, iovcount, offset,
16f41a132bSSasha Levin 				disk->evt, param);
17f41a132bSSasha Levin #else
18c9310ac4SAsias He 	return preadv_in_full(disk->fd, iov, iovcount, offset);
19f41a132bSSasha Levin #endif
20c9310ac4SAsias He }
21c9310ac4SAsias He 
225af21162SSasha Levin ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, const struct iovec *iov,
235af21162SSasha Levin 				int iovcount, void *param)
24c9310ac4SAsias He {
25c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
26c9310ac4SAsias He 
27f41a132bSSasha Levin #ifdef CONFIG_HAS_AIO
28f41a132bSSasha Levin 	struct iocb iocb;
29f41a132bSSasha Levin 
30f41a132bSSasha Levin 	return aio_pwritev(disk->ctx, &iocb, disk->fd, iov, iovcount, offset,
31f41a132bSSasha Levin 				disk->evt, param);
32f41a132bSSasha Levin #else
33c9310ac4SAsias He 	return pwritev_in_full(disk->fd, iov, iovcount, offset);
34f41a132bSSasha Levin #endif
35c9310ac4SAsias He }
36c9310ac4SAsias He 
375af21162SSasha Levin ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
385af21162SSasha 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(iov->iov_base, disk->priv + offset, 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++;
50c9310ac4SAsias He 	}
51c9310ac4SAsias He 
522534c9b6SSasha Levin 	return total;
532534c9b6SSasha Levin }
542534c9b6SSasha Levin 
555af21162SSasha Levin ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
565af21162SSasha Levin 				int iovcount, void *param)
57c9310ac4SAsias He {
58c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
599d15c39aSSasha Levin 	ssize_t total = 0;
60c9310ac4SAsias He 
612534c9b6SSasha Levin 	while (iovcount--) {
622534c9b6SSasha Levin 		memcpy(disk->priv + offset, iov->iov_base, iov->iov_len);
63c9310ac4SAsias He 
642534c9b6SSasha Levin 		sector	+= iov->iov_len >> SECTOR_SHIFT;
659d15c39aSSasha Levin 		offset	+= iov->iov_len;
669d15c39aSSasha Levin 		total	+= iov->iov_len;
672534c9b6SSasha Levin 		iov++;
682534c9b6SSasha Levin 	}
69c9310ac4SAsias He 
702534c9b6SSasha Levin 	return total;
71c9310ac4SAsias He }
72c9310ac4SAsias He 
7387ee33c8SAsias He int raw_image__close(struct disk_image *disk)
74c9310ac4SAsias He {
7572133dd2SAsias He 	int ret = 0;
7672133dd2SAsias He 
77c9310ac4SAsias He 	if (disk->priv != MAP_FAILED)
7872133dd2SAsias He 		ret = munmap(disk->priv, disk->size);
7972133dd2SAsias He 
80f41a132bSSasha Levin 	close(disk->evt);
81f41a132bSSasha Levin 
82f41a132bSSasha Levin #ifdef CONFIG_HAS_VIRTIO
83f41a132bSSasha Levin 	io_destroy(disk->ctx);
84f41a132bSSasha Levin #endif
85f41a132bSSasha Levin 
8672133dd2SAsias He 	return ret;
87c9310ac4SAsias He }
88c9310ac4SAsias He 
8987ee33c8SAsias He /*
9087ee33c8SAsias He  * multiple buffer based disk image operations
9187ee33c8SAsias He  */
922534c9b6SSasha Levin static struct disk_image_operations raw_image_regular_ops = {
932534c9b6SSasha Levin 	.read_sector	= raw_image__read_sector,
942534c9b6SSasha Levin 	.write_sector	= raw_image__write_sector,
95c9310ac4SAsias He };
96c9310ac4SAsias He 
979d15c39aSSasha Levin struct disk_image_operations ro_ops = {
982534c9b6SSasha Levin 	.read_sector	= raw_image__read_sector_mmap,
992534c9b6SSasha Levin 	.write_sector	= raw_image__write_sector_mmap,
10087ee33c8SAsias He 	.close		= raw_image__close,
101c9310ac4SAsias He };
102c9310ac4SAsias He 
1039d15c39aSSasha Levin struct disk_image_operations ro_ops_nowrite = {
1049d15c39aSSasha Levin 	.read_sector	= raw_image__read_sector,
1059d15c39aSSasha Levin 	.write_sector	= raw_image__write_sector,
1069d15c39aSSasha Levin };
1079d15c39aSSasha Levin 
108c9310ac4SAsias He struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
109c9310ac4SAsias He {
110f41a132bSSasha Levin 	struct disk_image *disk;
1117d22135fSAsias He 
1129d15c39aSSasha Levin 	if (readonly) {
1137d22135fSAsias He 		/*
1147d22135fSAsias He 		 * Use mmap's MAP_PRIVATE to implement non-persistent write
1157d22135fSAsias He 		 * FIXME: This does not work on 32-bit host.
1167d22135fSAsias He 		 */
1179d15c39aSSasha Levin 		struct disk_image *disk;
1189d15c39aSSasha Levin 
1199d15c39aSSasha Levin 		disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP);
1209d15c39aSSasha Levin 		if (disk == NULL) {
1219d15c39aSSasha Levin 			ro_ops = raw_image_regular_ops;
122f41a132bSSasha Levin 
1239d15c39aSSasha Levin 			disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR);
124*7dd56391SSasha Levin #ifdef CONFIG_HAS_AIO
125f41a132bSSasha Levin 			if (disk)
126f41a132bSSasha Levin 				disk->async = 1;
127f41a132bSSasha Levin #endif
1289d15c39aSSasha Levin 		}
1299d15c39aSSasha Levin 
1309d15c39aSSasha Levin 		return disk;
1319d15c39aSSasha Levin 	} else {
1327d22135fSAsias He 		/*
1337d22135fSAsias He 		 * Use read/write instead of mmap
1347d22135fSAsias He 		 */
135f41a132bSSasha Levin 		disk = disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR);
136*7dd56391SSasha Levin #ifdef CONFIG_HAS_AIO
137f41a132bSSasha Levin 		if (disk)
138f41a132bSSasha Levin 			disk->async = 1;
139f41a132bSSasha Levin #endif
140f41a132bSSasha Levin 		return disk;
141c9310ac4SAsias He 	}
1429d15c39aSSasha Levin }
143