1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
#include "kvm/disk-image.h"
#include <linux/err.h>
#ifdef CONFIG_HAS_AIO
#include <libaio.h>
#endif
ssize_t raw_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov,
int iovcount, void *param)
{
u64 offset = sector << SECTOR_SHIFT;
#ifdef CONFIG_HAS_AIO
struct iocb iocb;
return aio_preadv(disk->ctx, &iocb, disk->fd, iov, iovcount, offset,
disk->evt, param);
#else
return preadv_in_full(disk->fd, iov, iovcount, offset);
#endif
}
ssize_t raw_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov,
int iovcount, void *param)
{
u64 offset = sector << SECTOR_SHIFT;
#ifdef CONFIG_HAS_AIO
struct iocb iocb;
return aio_pwritev(disk->ctx, &iocb, disk->fd, iov, iovcount, offset,
disk->evt, param);
#else
return pwritev_in_full(disk->fd, iov, iovcount, offset);
#endif
}
ssize_t raw_image__read_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
int iovcount, void *param)
{
u64 offset = sector << SECTOR_SHIFT;
ssize_t total = 0;
while (iovcount--) {
memcpy(iov->iov_base, disk->priv + offset, iov->iov_len);
sector += iov->iov_len >> SECTOR_SHIFT;
offset += iov->iov_len;
total += iov->iov_len;
iov++;
}
return total;
}
ssize_t raw_image__write_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
int iovcount, void *param)
{
u64 offset = sector << SECTOR_SHIFT;
ssize_t total = 0;
while (iovcount--) {
memcpy(disk->priv + offset, iov->iov_base, iov->iov_len);
sector += iov->iov_len >> SECTOR_SHIFT;
offset += iov->iov_len;
total += iov->iov_len;
iov++;
}
return total;
}
int raw_image__close(struct disk_image *disk)
{
int ret = 0;
if (disk->priv != MAP_FAILED)
ret = munmap(disk->priv, disk->size);
close(disk->evt);
#ifdef CONFIG_HAS_VIRTIO
io_destroy(disk->ctx);
#endif
return ret;
}
/*
* multiple buffer based disk image operations
*/
static struct disk_image_operations raw_image_regular_ops = {
.read = raw_image__read,
.write = raw_image__write,
};
struct disk_image_operations ro_ops = {
.read = raw_image__read_mmap,
.write = raw_image__write_mmap,
.close = raw_image__close,
};
struct disk_image_operations ro_ops_nowrite = {
.read = raw_image__read,
};
struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
{
struct disk_image *disk;
if (readonly) {
/*
* Use mmap's MAP_PRIVATE to implement non-persistent write
* FIXME: This does not work on 32-bit host.
*/
struct disk_image *disk;
disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP);
if (IS_ERR_OR_NULL(disk)) {
disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR);
#ifdef CONFIG_HAS_AIO
if (!IS_ERR_OR_NULL(disk))
disk->async = 1;
#endif
}
return disk;
} else {
/*
* Use read/write instead of mmap
*/
disk = disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR);
#ifdef CONFIG_HAS_AIO
if (!IS_ERR_OR_NULL(disk))
disk->async = 1;
#endif
return disk;
}
}
|