xref: /kvmtool/include/kvm/disk-image.h (revision 29084a74e900c2760f37827fea7b9c2050f253ed)
1 #ifndef KVM__DISK_IMAGE_H
2 #define KVM__DISK_IMAGE_H
3 
4 #include <linux/types.h>
5 #include <stdbool.h>
6 #include <sys/uio.h>
7 #include <unistd.h>
8 
9 #define SECTOR_SHIFT		9
10 #define SECTOR_SIZE		(1UL << SECTOR_SHIFT)
11 
12 struct disk_image;
13 
14 struct disk_image_operations {
15 	int (*read_sector)(struct disk_image *disk, u64 sector, void *dst, u32 dst_len);
16 	int (*write_sector)(struct disk_image *disk, u64 sector, void *src, u32 src_len);
17 	ssize_t (*read_sector_iov)(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount);
18 	ssize_t (*write_sector_iov)(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount);
19 	int (*flush)(struct disk_image *disk);
20 	void (*close)(struct disk_image *disk);
21 };
22 
23 struct disk_image {
24 	int				fd;
25 	u64				size;
26 	struct disk_image_operations	*ops;
27 	void				*priv;
28 };
29 
30 struct disk_image *disk_image__open(const char *filename, bool readonly);
31 struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops);
32 struct disk_image *disk_image__new_readonly(int fd, u64 size, struct disk_image_operations *ops);
33 void disk_image__close(struct disk_image *disk);
34 
35 static inline int disk_image__read_sector(struct disk_image *disk, u64 sector, void *dst, u32 dst_len)
36 {
37 	return disk->ops->read_sector(disk, sector, dst, dst_len);
38 }
39 
40 static inline int disk_image__write_sector(struct disk_image *disk, u64 sector, void *src, u32 src_len)
41 {
42 	return disk->ops->write_sector(disk, sector, src, src_len);
43 }
44 
45 static inline ssize_t disk_image__read_sector_iov(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
46 {
47 	if (disk->ops->read_sector_iov)
48 		return disk->ops->read_sector_iov(disk, sector, iov, iovcount);
49 
50 	while (iovcount--) {
51 		if (disk->ops->read_sector(disk, sector, iov->iov_base, iov->iov_len) < 0)
52 			return -1;
53 
54 		sector += iov->iov_len >> SECTOR_SHIFT;
55 		iov++;
56 	}
57 
58 	return sector << SECTOR_SHIFT;
59 }
60 
61 static inline ssize_t disk_image__write_sector_iov(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
62 {
63 	if (disk->ops->write_sector_iov)
64 		return disk->ops->write_sector_iov(disk, sector, iov, iovcount);
65 
66 	while (iovcount--) {
67 		if (disk->ops->write_sector(disk, sector, iov->iov_base, iov->iov_len) < 0)
68 			return -1;
69 
70 		sector += iov->iov_len >> SECTOR_SHIFT;
71 		iov++;
72 	}
73 
74 	return sector << SECTOR_SHIFT;
75 }
76 
77 static inline int disk_image__flush(struct disk_image *disk)
78 {
79 	if (disk->ops->flush)
80 		return disk->ops->flush(disk);
81 	return fsync(disk->fd);
82 }
83 
84 #endif /* KVM__DISK_IMAGE_H */
85