xref: /kvmtool/disk/raw.c (revision dcd3cd8e4e8267fb5e13930ffb8d47cd1268e07d)
1c9310ac4SAsias He #include "kvm/disk-image.h"
2c9310ac4SAsias He 
39f9207c5SSasha Levin #include <linux/err.h>
49f9207c5SSasha Levin 
5f41a132bSSasha Levin #ifdef CONFIG_HAS_AIO
6f41a132bSSasha Levin #include <libaio.h>
7f41a132bSSasha Levin #endif
8f41a132bSSasha Levin 
9*dcd3cd8eSAsias He ssize_t raw_image__read(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 
24*dcd3cd8eSAsias He ssize_t raw_image__write(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 
39*dcd3cd8eSAsias He ssize_t raw_image__read_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 
57*dcd3cd8eSAsias He ssize_t raw_image__write_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 = {
95*dcd3cd8eSAsias He 	.read	= raw_image__read,
96*dcd3cd8eSAsias He 	.write	= raw_image__write,
97c9310ac4SAsias He };
98c9310ac4SAsias He 
999d15c39aSSasha Levin struct disk_image_operations ro_ops = {
100*dcd3cd8eSAsias He 	.read	= raw_image__read_mmap,
101*dcd3cd8eSAsias He 	.write	= raw_image__write_mmap,
10287ee33c8SAsias He 	.close		= raw_image__close,
103c9310ac4SAsias He };
104c9310ac4SAsias He 
1059d15c39aSSasha Levin struct disk_image_operations ro_ops_nowrite = {
106*dcd3cd8eSAsias He 	.read	= raw_image__read,
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);
1219f9207c5SSasha 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
1249f9207c5SSasha 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
1369f9207c5SSasha Levin 		if (!IS_ERR_OR_NULL(disk))
137f41a132bSSasha Levin 			disk->async = 1;
138f41a132bSSasha Levin #endif
139f41a132bSSasha Levin 		return disk;
140c9310ac4SAsias He 	}
1419d15c39aSSasha Levin }
142