xref: /kvmtool/disk/raw.c (revision 7d22135f6160a5d883cd25637e74fa6d2bb4d97e)
1c9310ac4SAsias He #include "kvm/disk-image.h"
2c9310ac4SAsias He 
3c9310ac4SAsias He static ssize_t raw_image__read_sector_iov(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
4c9310ac4SAsias He {
5c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
6c9310ac4SAsias He 
7c9310ac4SAsias He 	return preadv_in_full(disk->fd, iov, iovcount, offset);
8c9310ac4SAsias He }
9c9310ac4SAsias He 
10c9310ac4SAsias He static ssize_t raw_image__write_sector_iov(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
11c9310ac4SAsias He {
12c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
13c9310ac4SAsias He 
14c9310ac4SAsias He 	return pwritev_in_full(disk->fd, iov, iovcount, offset);
15c9310ac4SAsias He }
16c9310ac4SAsias He 
17c9310ac4SAsias He static int raw_image__read_sector_ro_mmap(struct disk_image *disk, u64 sector, void *dst, u32 dst_len)
18c9310ac4SAsias He {
19c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
20c9310ac4SAsias He 
21c9310ac4SAsias He 	if (offset + dst_len > disk->size)
22c9310ac4SAsias He 		return -1;
23c9310ac4SAsias He 
24c9310ac4SAsias He 	memcpy(dst, disk->priv + offset, dst_len);
25c9310ac4SAsias He 
26c9310ac4SAsias He 	return 0;
27c9310ac4SAsias He }
28c9310ac4SAsias He 
29c9310ac4SAsias He static int raw_image__write_sector_ro_mmap(struct disk_image *disk, u64 sector, void *src, u32 src_len)
30c9310ac4SAsias He {
31c9310ac4SAsias He 	u64 offset = sector << SECTOR_SHIFT;
32c9310ac4SAsias He 
33c9310ac4SAsias He 	if (offset + src_len > disk->size)
34c9310ac4SAsias He 		return -1;
35c9310ac4SAsias He 
36c9310ac4SAsias He 	memcpy(disk->priv + offset, src, src_len);
37c9310ac4SAsias He 
38c9310ac4SAsias He 	return 0;
39c9310ac4SAsias He }
40c9310ac4SAsias He 
41c9310ac4SAsias He static void raw_image__close_ro_mmap(struct disk_image *disk)
42c9310ac4SAsias He {
43c9310ac4SAsias He 	if (disk->priv != MAP_FAILED)
44c9310ac4SAsias He 		munmap(disk->priv, disk->size);
45c9310ac4SAsias He }
46c9310ac4SAsias He 
47c9310ac4SAsias He static struct disk_image_operations raw_image_ops = {
48c9310ac4SAsias He 	.read_sector_iov	= raw_image__read_sector_iov,
49c9310ac4SAsias He 	.write_sector_iov	= raw_image__write_sector_iov
50c9310ac4SAsias He };
51c9310ac4SAsias He 
52c9310ac4SAsias He static struct disk_image_operations raw_image_ro_mmap_ops = {
53c9310ac4SAsias He 	.read_sector		= raw_image__read_sector_ro_mmap,
54c9310ac4SAsias He 	.write_sector		= raw_image__write_sector_ro_mmap,
55c9310ac4SAsias He 	.close			= raw_image__close_ro_mmap,
56c9310ac4SAsias He };
57c9310ac4SAsias He 
58c9310ac4SAsias He struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
59c9310ac4SAsias He {
60*7d22135fSAsias He 
61c9310ac4SAsias He 	if (readonly)
62*7d22135fSAsias He 		/*
63*7d22135fSAsias He 		 * Use mmap's MAP_PRIVATE to implement non-persistent write
64*7d22135fSAsias He 		 * FIXME: This does not work on 32-bit host.
65*7d22135fSAsias He 		 */
66*7d22135fSAsias He 		return disk_image__new(fd, st->st_size, &raw_image_ro_mmap_ops, DISK_IMAGE_MMAP);
67c9310ac4SAsias He 	else
68*7d22135fSAsias He 		/*
69*7d22135fSAsias He 		 * Use read/write instead of mmap
70*7d22135fSAsias He 		 */
71*7d22135fSAsias He 		return disk_image__new(fd, st->st_size, &raw_image_ops, DISK_IMAGE_NOMMAP);
72c9310ac4SAsias He }
73c9310ac4SAsias He 
74c9310ac4SAsias He struct disk_image *blkdev__probe(const char *filename, struct stat *st)
75c9310ac4SAsias He {
76c9310ac4SAsias He 	u64 size;
77c9310ac4SAsias He 	int fd;
78c9310ac4SAsias He 
79c9310ac4SAsias He 	if (!S_ISBLK(st->st_mode))
80c9310ac4SAsias He 		return NULL;
81c9310ac4SAsias He 
82c9310ac4SAsias He 	fd		= open(filename, O_RDONLY);
83c9310ac4SAsias He 	if (fd < 0)
84c9310ac4SAsias He 		return NULL;
85c9310ac4SAsias He 
86c9310ac4SAsias He 	if (ioctl(fd, BLKGETSIZE64, &size) < 0) {
87c9310ac4SAsias He 		close(fd);
88c9310ac4SAsias He 		return NULL;
89c9310ac4SAsias He 	}
90c9310ac4SAsias He 
91*7d22135fSAsias He 	return disk_image__new(fd, size, &raw_image_ro_mmap_ops, DISK_IMAGE_MMAP);
92c9310ac4SAsias He }
93