mirror of
https://github.com/clearlinux/kvmtool.git
synced 2026-08-26 16:28:12 +00:00
kvm tools: Fixes for disk image module
Fixes include: - Error handling - Cleanup - Standard init/uninit Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
This commit is contained in:
+20
-7
@@ -1094,11 +1094,13 @@ static int kvm_cmd_run_init(int argc, const char **argv)
|
||||
|
||||
if (image_count) {
|
||||
kvm->nr_disks = image_count;
|
||||
kvm->disks = disk_image__open_all(image_filename, readonly_image, image_count);
|
||||
if (!kvm->disks)
|
||||
die("Unable to load all disk images.");
|
||||
|
||||
virtio_blk__init_all(kvm);
|
||||
kvm->disks = disk_image__open_all(image_filename, readonly_image, image_count);
|
||||
if (IS_ERR(kvm->disks)) {
|
||||
r = PTR_ERR(kvm->disks);
|
||||
pr_err("disk_image__open_all() failed with error %ld\n",
|
||||
PTR_ERR(kvm->disks));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
printf(" # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME,
|
||||
@@ -1129,6 +1131,12 @@ static int kvm_cmd_run_init(int argc, const char **argv)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = virtio_blk__init(kvm);
|
||||
if (r < 0) {
|
||||
pr_err("virtio_blk__init() failed with error %d\n", r);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (active_console == CONSOLE_VIRTIO)
|
||||
virtio_console__init(kvm);
|
||||
|
||||
@@ -1272,10 +1280,15 @@ static void kvm_cmd_run_exit(int guest_ret)
|
||||
|
||||
fb__stop();
|
||||
|
||||
virtio_blk__delete_all(kvm);
|
||||
r = virtio_blk__exit(kvm);
|
||||
if (r < 0)
|
||||
pr_warning("virtio_blk__exit() failed with error %d\n", r);
|
||||
|
||||
virtio_rng__delete_all(kvm);
|
||||
|
||||
disk_image__close_all(kvm->disks, image_count);
|
||||
r = disk_image__close_all(kvm->disks, image_count);
|
||||
if (r < 0)
|
||||
pr_warning("disk_image__close_all() failed with error %d\n", r);
|
||||
free(kvm_cpus);
|
||||
|
||||
r = serial8250__exit(kvm);
|
||||
|
||||
+8
-5
@@ -1,5 +1,7 @@
|
||||
#include "kvm/disk-image.h"
|
||||
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* raw image and blk dev are similar, so reuse raw image ops.
|
||||
*/
|
||||
@@ -12,22 +14,23 @@ static struct disk_image_operations blk_dev_ops = {
|
||||
struct disk_image *blkdev__probe(const char *filename, struct stat *st)
|
||||
{
|
||||
u64 size;
|
||||
int fd;
|
||||
int fd, r;
|
||||
|
||||
if (!S_ISBLK(st->st_mode))
|
||||
return NULL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/*
|
||||
* Be careful! We are opening host block device!
|
||||
* Open it readonly since we do not want to break user's data on disk.
|
||||
*/
|
||||
fd = open(filename, O_RDONLY);
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
return ERR_PTR(fd);
|
||||
|
||||
if (ioctl(fd, BLKGETSIZE64, &size) < 0) {
|
||||
r = -errno;
|
||||
close(fd);
|
||||
return NULL;
|
||||
return ERR_PTR(r);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+47
-29
@@ -2,6 +2,7 @@
|
||||
#include "kvm/qcow.h"
|
||||
#include "kvm/virtio-blk.h"
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
@@ -31,14 +32,17 @@ static void *disk_image__thread(void *param)
|
||||
struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops, int use_mmap)
|
||||
{
|
||||
struct disk_image *disk;
|
||||
int r;
|
||||
|
||||
disk = malloc(sizeof *disk);
|
||||
disk = malloc(sizeof *disk);
|
||||
if (!disk)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
disk->fd = fd;
|
||||
disk->size = size;
|
||||
disk->ops = ops;
|
||||
*disk = (struct disk_image) {
|
||||
.fd = fd,
|
||||
.size = size,
|
||||
.ops = ops,
|
||||
};
|
||||
|
||||
if (use_mmap == DISK_IMAGE_MMAP) {
|
||||
/*
|
||||
@@ -46,8 +50,9 @@ struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operation
|
||||
*/
|
||||
disk->priv = mmap(NULL, size, PROT_RW, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
|
||||
if (disk->priv == MAP_FAILED) {
|
||||
r = -errno;
|
||||
free(disk);
|
||||
disk = NULL;
|
||||
return ERR_PTR(r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +62,12 @@ struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operation
|
||||
|
||||
disk->evt = eventfd(0, 0);
|
||||
io_setup(AIO_MAX, &disk->ctx);
|
||||
if (pthread_create(&thread, NULL, disk_image__thread, disk) != 0)
|
||||
die("Failed starting IO thread");
|
||||
r = pthread_create(&thread, NULL, disk_image__thread, disk);
|
||||
if (r) {
|
||||
r = -errno;
|
||||
free(disk);
|
||||
return ERR_PTR(r);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return disk;
|
||||
@@ -71,54 +80,58 @@ struct disk_image *disk_image__open(const char *filename, bool readonly)
|
||||
int fd;
|
||||
|
||||
if (stat(filename, &st) < 0)
|
||||
return NULL;
|
||||
return ERR_PTR(-errno);
|
||||
|
||||
/* blk device ?*/
|
||||
disk = blkdev__probe(filename, &st);
|
||||
if (disk)
|
||||
disk = blkdev__probe(filename, &st);
|
||||
if (!IS_ERR_OR_NULL(disk))
|
||||
return disk;
|
||||
|
||||
fd = open(filename, readonly ? O_RDONLY : O_RDWR);
|
||||
fd = open(filename, readonly ? O_RDONLY : O_RDWR);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
return ERR_PTR(fd);
|
||||
|
||||
/* qcow image ?*/
|
||||
disk = qcow_probe(fd, true);
|
||||
if (disk) {
|
||||
disk = qcow_probe(fd, true);
|
||||
if (!IS_ERR_OR_NULL(disk)) {
|
||||
pr_warning("Forcing read-only support for QCOW");
|
||||
return disk;
|
||||
}
|
||||
|
||||
/* raw image ?*/
|
||||
disk = raw_image__probe(fd, &st, readonly);
|
||||
if (disk)
|
||||
disk = raw_image__probe(fd, &st, readonly);
|
||||
if (!IS_ERR_OR_NULL(disk))
|
||||
return disk;
|
||||
|
||||
if (close(fd) < 0)
|
||||
pr_warning("close() failed");
|
||||
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
struct disk_image **disk_image__open_all(const char **filenames, bool *readonly, int count)
|
||||
{
|
||||
struct disk_image **disks;
|
||||
int i;
|
||||
void *err;
|
||||
|
||||
if (!count || count > MAX_DISK_IMAGES)
|
||||
return NULL;
|
||||
if (!count)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (count > MAX_DISK_IMAGES)
|
||||
return ERR_PTR(-ENOSPC);
|
||||
|
||||
disks = calloc(count, sizeof(*disks));
|
||||
if (!disks)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!filenames[i])
|
||||
continue;
|
||||
|
||||
disks[i] = disk_image__open(filenames[i], readonly[i]);
|
||||
if (!disks[i]) {
|
||||
if (IS_ERR_OR_NULL(disks[i])) {
|
||||
pr_err("Loading disk image '%s' failed", filenames[i]);
|
||||
err = disks[i];
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -126,10 +139,11 @@ struct disk_image **disk_image__open_all(const char **filenames, bool *readonly,
|
||||
return disks;
|
||||
error:
|
||||
for (i = 0; i < count; i++)
|
||||
disk_image__close(disks[i]);
|
||||
if (!IS_ERR_OR_NULL(disks[i]))
|
||||
disk_image__close(disks[i]);
|
||||
|
||||
free(disks);
|
||||
return NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
int disk_image__flush(struct disk_image *disk)
|
||||
@@ -157,12 +171,14 @@ int disk_image__close(struct disk_image *disk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void disk_image__close_all(struct disk_image **disks, int count)
|
||||
int disk_image__close_all(struct disk_image **disks, int count)
|
||||
{
|
||||
while (count)
|
||||
disk_image__close(disks[--count]);
|
||||
|
||||
free(disks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -181,7 +197,7 @@ ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec
|
||||
total = disk->ops->read_sector(disk, sector, iov, iovcount, param);
|
||||
if (total < 0) {
|
||||
pr_info("disk_image__read error: total=%ld\n", (long)total);
|
||||
return -1;
|
||||
return total;
|
||||
}
|
||||
} else {
|
||||
/* Do nothing */
|
||||
@@ -213,7 +229,7 @@ ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iove
|
||||
total = disk->ops->write_sector(disk, sector, iov, iovcount, param);
|
||||
if (total < 0) {
|
||||
pr_info("disk_image__write error: total=%ld\n", (long)total);
|
||||
return -1;
|
||||
return total;
|
||||
}
|
||||
} else {
|
||||
/* Do nothing */
|
||||
@@ -228,9 +244,11 @@ ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iove
|
||||
ssize_t disk_image__get_serial(struct disk_image *disk, void *buffer, ssize_t *len)
|
||||
{
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
if (fstat(disk->fd, &st) != 0)
|
||||
return 0;
|
||||
r = fstat(disk->fd, &st);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
*len = snprintf(buffer, *len, "%llu%llu%llu", (u64)st.st_dev, (u64)st.st_rdev, (u64)st.st_ino);
|
||||
return *len;
|
||||
|
||||
+1
-1
@@ -1334,7 +1334,7 @@ static struct disk_image *qcow2_probe(int fd, bool readonly)
|
||||
else
|
||||
disk_image = disk_image__new(fd, h->size, &qcow_disk_ops, DISK_IMAGE_REGULAR);
|
||||
|
||||
if (!disk_image)
|
||||
if (IS_ERR_OR_NULL(disk_image))
|
||||
goto free_refcount_table;
|
||||
|
||||
disk_image->async = 0;
|
||||
|
||||
+5
-4
@@ -1,5 +1,7 @@
|
||||
#include "kvm/disk-image.h"
|
||||
|
||||
#include <linux/err.h>
|
||||
|
||||
#ifdef CONFIG_HAS_AIO
|
||||
#include <libaio.h>
|
||||
#endif
|
||||
@@ -116,11 +118,10 @@ struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
|
||||
struct disk_image *disk;
|
||||
|
||||
disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP);
|
||||
if (disk == NULL) {
|
||||
|
||||
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 (disk)
|
||||
if (!IS_ERR_OR_NULL(disk))
|
||||
disk->async = 1;
|
||||
#endif
|
||||
}
|
||||
@@ -132,7 +133,7 @@ struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
|
||||
*/
|
||||
disk = disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR);
|
||||
#ifdef CONFIG_HAS_AIO
|
||||
if (disk)
|
||||
if (!IS_ERR_OR_NULL(disk))
|
||||
disk->async = 1;
|
||||
#endif
|
||||
return disk;
|
||||
|
||||
@@ -57,7 +57,7 @@ struct disk_image *disk_image__open(const char *filename, bool readonly);
|
||||
struct disk_image **disk_image__open_all(const char **filenames, bool *readonly, int count);
|
||||
struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops, int mmap);
|
||||
int disk_image__close(struct disk_image *disk);
|
||||
void disk_image__close_all(struct disk_image **disks, int count);
|
||||
int disk_image__close_all(struct disk_image **disks, int count);
|
||||
int disk_image__flush(struct disk_image *disk);
|
||||
ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov,
|
||||
int iovcount, void *param);
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
|
||||
struct kvm;
|
||||
|
||||
void virtio_blk__init(struct kvm *kvm, struct disk_image *disk);
|
||||
void virtio_blk__init_all(struct kvm *kvm);
|
||||
void virtio_blk__delete_all(struct kvm *kvm);
|
||||
int virtio_blk__init(struct kvm *kvm);
|
||||
int virtio_blk__exit(struct kvm *kvm);
|
||||
void virtio_blk_complete(void *param, long len);
|
||||
|
||||
#endif /* KVM__BLK_VIRTIO_H */
|
||||
|
||||
+27
-10
@@ -208,17 +208,17 @@ static struct virtio_ops blk_dev_virtio_ops = (struct virtio_ops) {
|
||||
.get_size_vq = get_size_vq,
|
||||
};
|
||||
|
||||
void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
|
||||
static int virtio_blk__init_one(struct kvm *kvm, struct disk_image *disk)
|
||||
{
|
||||
struct blk_dev *bdev;
|
||||
unsigned int i;
|
||||
|
||||
if (!disk)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
bdev = calloc(1, sizeof(struct blk_dev));
|
||||
if (bdev == NULL)
|
||||
die("Failed allocating bdev");
|
||||
return -ENOMEM;
|
||||
|
||||
*bdev = (struct blk_dev) {
|
||||
.mutex = PTHREAD_MUTEX_INITIALIZER,
|
||||
@@ -251,23 +251,40 @@ void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
|
||||
"Please make sure that the guest kernel was "
|
||||
"compiled with CONFIG_VIRTIO_BLK=y enabled "
|
||||
"in its .config");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void virtio_blk__init_all(struct kvm *kvm)
|
||||
static int virtio_blk__exit_one(struct kvm *kvm, struct blk_dev *bdev)
|
||||
{
|
||||
int i;
|
||||
list_del(&bdev->list);
|
||||
free(bdev);
|
||||
|
||||
for (i = 0; i < kvm->nr_disks; i++)
|
||||
virtio_blk__init(kvm, kvm->disks[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void virtio_blk__delete_all(struct kvm *kvm)
|
||||
int virtio_blk__init(struct kvm *kvm)
|
||||
{
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < kvm->nr_disks; i++) {
|
||||
r = virtio_blk__init_one(kvm, kvm->disks[i]);
|
||||
if (r < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
cleanup:
|
||||
return virtio_blk__exit(kvm);
|
||||
}
|
||||
|
||||
int virtio_blk__exit(struct kvm *kvm)
|
||||
{
|
||||
while (!list_empty(&bdevs)) {
|
||||
struct blk_dev *bdev;
|
||||
|
||||
bdev = list_first_entry(&bdevs, struct blk_dev, list);
|
||||
list_del(&bdev->list);
|
||||
free(bdev);
|
||||
virtio_blk__exit_one(kvm, bdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user