diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2018-10-19 10:12:40 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2018-10-19 10:12:40 +0000 |
commit | e014ce92dbc428864aef9723a6d3bde4319f06bc (patch) | |
tree | 72a90057790b5a8544c1402e812405577dfbe64f /usr.sbin/vmctl/vmctl.c | |
parent | dc388d4163b5f0cf447d8f1d605a6b3bd1da6346 (diff) |
Add support to create and convert disk images from existing images
The -i option to vmctl create (eg. vmctl create output.qcow2 -i input.img)
lets you create a new image from an input file and convert it if it is a
different format. This allows to convert qcow2 images from raw images,
raw from qcow2, or even qcow2 from qcow2 and raw from raw to re-optimize
the disk.
This re-uses Ori's vioqcow2.c from vmd by reaching into it and
compiling it in. The API has been adjust to be used from both vmctl
and vmd accordingly.
OK mlarkin@
Diffstat (limited to 'usr.sbin/vmctl/vmctl.c')
-rw-r--r-- | usr.sbin/vmctl/vmctl.c | 117 |
1 files changed, 113 insertions, 4 deletions
diff --git a/usr.sbin/vmctl/vmctl.c b/usr.sbin/vmctl/vmctl.c index a311ed0a512..1feca4754d4 100644 --- a/usr.sbin/vmctl/vmctl.c +++ b/usr.sbin/vmctl/vmctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmctl.c,v 1.61 2018/10/08 16:32:01 reyk Exp $ */ +/* $OpenBSD: vmctl.c,v 1.62 2018/10/19 10:12:39 reyk Exp $ */ /* * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org> @@ -39,6 +39,7 @@ #include <grp.h> #include "vmd.h" +#include "virtio.h" #include "vmctl.h" #include "atomicio.h" @@ -794,6 +795,116 @@ vm_console(struct vmop_info_result *list, size_t ct) } /* + * open_imagefile + * + * Open an imagefile with the specified type, path and size. + * + * Parameters: + * type : format of the image file + * imgfile_path: path to the image file to create + * flags : flags for open(2), e.g. O_RDONLY + * file : file structure + * sz : size of the image file + * + * Return: + * fd : Returns file descriptor of the new image file + * -1 : Operation failed. errno is set. + */ +int +open_imagefile(int type, const char *imgfile_path, int flags, + struct virtio_backing *file, off_t *sz) +{ + int fd, ret, basefd[VM_MAX_BASE_PER_DISK], nfd, i; + char path[PATH_MAX]; + + *sz = 0; + if ((fd = open(imgfile_path, flags)) == -1) + return (-1); + + basefd[0] = fd; + nfd = 1; + + errno = 0; + switch (type) { + case VMDF_QCOW2: + if (strlcpy(path, imgfile_path, sizeof(path)) >= sizeof(path)) + return (-1); + for (i = 0; i < VM_MAX_BASE_PER_DISK - 1; i++, nfd++) { + if ((ret = virtio_qcow2_get_base(basefd[i], + path, sizeof(path), imgfile_path)) == -1) { + log_debug("%s: failed to get base %d", __func__, i); + return -1; + } else if (ret == 0) + break; + + /* + * This might be called after unveil is already + * locked but it is save to ignore the EPERM error + * here as the subsequent open would fail as well. + */ + if ((ret = unveil(path, "r")) != 0 && + (ret != EPERM)) + err(1, "unveil"); + if ((basefd[i + 1] = open(path, O_RDONLY)) == -1) { + log_warn("%s: failed to open base %s", + __func__, path); + return (-1); + } + } + ret = virtio_init_qcow2(file, sz, basefd, nfd); + break; + default: + ret = virtio_init_raw(file, sz, &fd, 1); + break; + } + + if (ret == -1) { + for (i = 0; i < nfd; i++) + close(basefd[i]); + return (-1); + } + + return (fd); +} + +/* + * create_imagefile + * + * Create an empty imagefile with the specified type, path and size. + * + * Parameters: + * type : format of the image file + * imgfile_path: path to the image file to create + * base_path : path to the qcow2 base image + * imgsize : size of the image file to create (in MB) + * format : string identifying the format + * + * Return: + * EEXIST: The requested image file already exists + * 0 : Image file successfully created + * Exxxx : Various other Exxxx errno codes due to other I/O errors + */ +int +create_imagefile(int type, const char *imgfile_path, const char *base_path, + long imgsize, const char **format) +{ + int ret; + + switch (type) { + case VMDF_QCOW2: + *format = "qcow2"; + ret = create_qc2_imagefile(imgfile_path, base_path, imgsize); + break; + default: + *format = "raw"; + ret = create_raw_imagefile(imgfile_path, imgsize); + break; + } + + return (ret); +} + +/* * create_raw_imagefile * * Create an empty imagefile with the specified path and size. @@ -831,7 +942,7 @@ create_raw_imagefile(const char *imgfile_path, long imgsize) } /* - * create_imagefile + * create_qc2_imagefile * * Create an empty qcow2 imagefile with the specified path and size. * @@ -844,8 +955,6 @@ create_raw_imagefile(const char *imgfile_path, long imgsize) * 0 : Image file successfully created * Exxxx : Various other Exxxx errno codes due to other I/O errors */ -#define ALIGN(sz, align) \ - ((sz + align - 1) & ~(align - 1)) int create_qc2_imagefile(const char *imgfile_path, const char *base_path, long imgsize) |