diff options
-rw-r--r-- | usr.sbin/vmctl/main.c | 4 | ||||
-rw-r--r-- | usr.sbin/vmctl/vmctl.c | 187 | ||||
-rw-r--r-- | usr.sbin/vmctl/vmctl.h | 5 | ||||
-rw-r--r-- | usr.sbin/vmd/vioqcow2.c | 145 | ||||
-rw-r--r-- | usr.sbin/vmd/vioraw.c | 43 | ||||
-rw-r--r-- | usr.sbin/vmd/virtio.c | 6 | ||||
-rw-r--r-- | usr.sbin/vmd/virtio.h | 10 | ||||
-rw-r--r-- | usr.sbin/vmd/vmboot.c | 6 |
8 files changed, 205 insertions, 201 deletions
diff --git a/usr.sbin/vmctl/main.c b/usr.sbin/vmctl/main.c index da84b5d9e5a..d0efcaf3c8c 100644 --- a/usr.sbin/vmctl/main.c +++ b/usr.sbin/vmctl/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.47 2018/10/19 10:12:39 reyk Exp $ */ +/* $OpenBSD: main.c,v 1.48 2018/11/26 10:39:30 reyk Exp $ */ /* * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org> @@ -658,7 +658,7 @@ ctl_convert(const char *srcfile, const char *dstfile, int dsttype, size_t dstsiz } /* align to megabytes */ - dst.size = ALIGN(dstsize, 1048576); + dst.size = ALIGNSZ(dstsize, 1048576); if ((ret = create_imagefile(dst.type, dst.disk, NULL, dst.size / 1048576, &format)) != 0) { diff --git a/usr.sbin/vmctl/vmctl.c b/usr.sbin/vmctl/vmctl.c index 1feca4754d4..66200a6ab28 100644 --- a/usr.sbin/vmctl/vmctl.c +++ b/usr.sbin/vmctl/vmctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmctl.c,v 1.62 2018/10/19 10:12:39 reyk Exp $ */ +/* $OpenBSD: vmctl.c,v 1.63 2018/11/26 10:39:30 reyk Exp $ */ /* * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org> @@ -851,10 +851,10 @@ open_imagefile(int type, const char *imgfile_path, int flags, return (-1); } } - ret = virtio_init_qcow2(file, sz, basefd, nfd); + ret = virtio_qcow2_init(file, sz, basefd, nfd); break; default: - ret = virtio_init_raw(file, sz, &fd, 1); + ret = virtio_raw_init(file, sz, &fd, 1); break; } @@ -893,191 +893,14 @@ create_imagefile(int type, const char *imgfile_path, const char *base_path, switch (type) { case VMDF_QCOW2: *format = "qcow2"; - ret = create_qc2_imagefile(imgfile_path, base_path, imgsize); + ret = virtio_qcow2_create(imgfile_path, base_path, imgsize); break; default: *format = "raw"; - ret = create_raw_imagefile(imgfile_path, imgsize); + ret = virtio_raw_create(imgfile_path, imgsize); break; } return (ret); } -/* - * create_raw_imagefile - * - * Create an empty imagefile with the specified path and size. - * - * Parameters: - * imgfile_path: path to the image file to create - * imgsize : size of the image file to create (in MB) - * - * 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_raw_imagefile(const char *imgfile_path, long imgsize) -{ - int fd, ret; - - /* Refuse to overwrite an existing image */ - fd = open(imgfile_path, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, - S_IRUSR | S_IWUSR); - if (fd == -1) - return (errno); - - /* Extend to desired size */ - if (ftruncate(fd, (off_t)imgsize * 1024 * 1024) == -1) { - ret = errno; - close(fd); - unlink(imgfile_path); - return (ret); - } - - ret = close(fd); - return (ret); -} - -/* - * create_qc2_imagefile - * - * Create an empty qcow2 imagefile with the specified path and size. - * - * Parameters: - * imgfile_path: path to the image file to create - * imgsize : size of the image file to create (in MB) - * - * 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_qc2_imagefile(const char *imgfile_path, - const char *base_path, long imgsize) -{ - struct qcheader { - char magic[4]; - uint32_t version; - uint64_t backingoff; - uint32_t backingsz; - uint32_t clustershift; - uint64_t disksz; - uint32_t cryptmethod; - uint32_t l1sz; - uint64_t l1off; - uint64_t refoff; - uint32_t refsz; - uint32_t snapcount; - uint64_t snapsz; - /* v3 additions */ - uint64_t incompatfeatures; - uint64_t compatfeatures; - uint64_t autoclearfeatures; - uint32_t reforder; - uint32_t headersz; - } __packed hdr, basehdr; - int fd, ret; - ssize_t base_len; - uint64_t l1sz, refsz, disksz, initsz, clustersz; - uint64_t l1off, refoff, v, i, l1entrysz, refentrysz; - uint16_t refs; - - disksz = 1024 * 1024 * imgsize; - - if (base_path) { - fd = open(base_path, O_RDONLY); - if (read(fd, &basehdr, sizeof(basehdr)) != sizeof(basehdr)) - err(1, "failure to read base image header"); - close(fd); - if (strncmp(basehdr.magic, - VM_MAGIC_QCOW, strlen(VM_MAGIC_QCOW)) != 0) - errx(1, "base image is not a qcow2 file"); - if (!disksz) - disksz = betoh64(basehdr.disksz); - else if (disksz != betoh64(basehdr.disksz)) - errx(1, "base size does not match requested size"); - } - if (!base_path && !disksz) - errx(1, "missing disk size"); - - clustersz = (1<<16); - l1off = ALIGN(sizeof(hdr), clustersz); - - l1entrysz = clustersz * clustersz / 8; - l1sz = (disksz + l1entrysz - 1) / l1entrysz; - - refoff = ALIGN(l1off + 8*l1sz, clustersz); - refentrysz = clustersz * clustersz * clustersz / 2; - refsz = (disksz + refentrysz - 1) / refentrysz; - - initsz = ALIGN(refoff + refsz*clustersz, clustersz); - base_len = base_path ? strlen(base_path) : 0; - - memcpy(hdr.magic, VM_MAGIC_QCOW, strlen(VM_MAGIC_QCOW)); - hdr.version = htobe32(3); - hdr.backingoff = htobe64(base_path ? sizeof(hdr) : 0); - hdr.backingsz = htobe32(base_len); - hdr.clustershift = htobe32(16); - hdr.disksz = htobe64(disksz); - hdr.cryptmethod = htobe32(0); - hdr.l1sz = htobe32(l1sz); - hdr.l1off = htobe64(l1off); - hdr.refoff = htobe64(refoff); - hdr.refsz = htobe32(refsz); - hdr.snapcount = htobe32(0); - hdr.snapsz = htobe64(0); - hdr.incompatfeatures = htobe64(0); - hdr.compatfeatures = htobe64(0); - hdr.autoclearfeatures = htobe64(0); - hdr.reforder = htobe32(4); - hdr.headersz = htobe32(sizeof(hdr)); - - /* Refuse to overwrite an existing image */ - fd = open(imgfile_path, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, - S_IRUSR | S_IWUSR); - if (fd == -1) - return (errno); - - /* Write out the header */ - if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) - goto error; - - /* Add the base image */ - if (base_path && write(fd, base_path, base_len) != base_len) - goto error; - - /* Extend to desired size, and add one refcount cluster */ - if (ftruncate(fd, (off_t)initsz + clustersz) == -1) - goto error; - - /* - * Paranoia: if our disk image takes more than one cluster - * to refcount the initial image, fail. - */ - if (initsz/clustersz > clustersz/2) { - errno = ERANGE; - goto error; - } - - /* Add a refcount block, and refcount ourselves. */ - v = htobe64(initsz); - if (pwrite(fd, &v, 8, refoff) != 8) - goto error; - for (i = 0; i < initsz/clustersz + 1; i++) { - refs = htobe16(1); - if (pwrite(fd, &refs, 2, initsz + 2*i) != 2) - goto error; - } - - ret = close(fd); - return (ret); -error: - ret = errno; - close(fd); - unlink(imgfile_path); - return (errno); -} diff --git a/usr.sbin/vmctl/vmctl.h b/usr.sbin/vmctl/vmctl.h index 2948a4fc0ce..37aeac34ce2 100644 --- a/usr.sbin/vmctl/vmctl.h +++ b/usr.sbin/vmctl/vmctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmctl.h,v 1.27 2018/10/19 10:12:39 reyk Exp $ */ +/* $OpenBSD: vmctl.h,v 1.28 2018/11/26 10:39:30 reyk Exp $ */ /* * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org> @@ -71,9 +71,6 @@ struct ctl_command { struct imsgbuf *ibuf; -#define ALIGN(sz, align) ((sz + align - 1) & ~(align - 1)) -#define MIN(a,b) (((a)<(b))?(a):(b)) - /* main.c */ int vmmaction(struct parse_result *); int parse_ifs(struct parse_result *, char *, int); diff --git a/usr.sbin/vmd/vioqcow2.c b/usr.sbin/vmd/vioqcow2.c index be6964bb5bd..185e8178946 100644 --- a/usr.sbin/vmd/vioqcow2.c +++ b/usr.sbin/vmd/vioqcow2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vioqcow2.c,v 1.11 2018/11/24 04:51:55 ori Exp $ */ +/* $OpenBSD: vioqcow2.c,v 1.12 2018/11/26 10:39:30 reyk Exp $ */ /* * Copyright (c) 2018 Ori Bernstein <ori@eigenstate.org> @@ -29,6 +29,7 @@ #include <assert.h> #include <libgen.h> #include <err.h> +#include <errno.h> #include "vmd.h" #include "vmm.h" @@ -118,7 +119,7 @@ static void qc2_close(void *, int); * May open snapshot base images. */ int -virtio_init_qcow2(struct virtio_backing *file, off_t *szp, int *fd, size_t nfd) +virtio_qcow2_init(struct virtio_backing *file, off_t *szp, int *fd, size_t nfd) { struct qcdisk *diskp; @@ -608,3 +609,143 @@ inc_refs(struct qcdisk *disk, off_t off, int newcluster) fatal("%s: could not write ref block", __func__); } +/* + * virtio_qcow2_create + * + * Create an empty qcow2 imagefile with the specified path and size. + * + * Parameters: + * imgfile_path: path to the image file to create + * imgsize : size of the image file to create (in MB) + * + * 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 +virtio_qcow2_create(const char *imgfile_path, + const char *base_path, long imgsize) +{ + struct qcheader { + char magic[4]; + uint32_t version; + uint64_t backingoff; + uint32_t backingsz; + uint32_t clustershift; + uint64_t disksz; + uint32_t cryptmethod; + uint32_t l1sz; + uint64_t l1off; + uint64_t refoff; + uint32_t refsz; + uint32_t snapcount; + uint64_t snapsz; + /* v3 additions */ + uint64_t incompatfeatures; + uint64_t compatfeatures; + uint64_t autoclearfeatures; + uint32_t reforder; + uint32_t headersz; + } __packed hdr, basehdr; + int fd, ret; + ssize_t base_len; + uint64_t l1sz, refsz, disksz, initsz, clustersz; + uint64_t l1off, refoff, v, i, l1entrysz, refentrysz; + uint16_t refs; + + disksz = 1024 * 1024 * imgsize; + + if (base_path) { + fd = open(base_path, O_RDONLY); + if (read(fd, &basehdr, sizeof(basehdr)) != sizeof(basehdr)) + err(1, "failure to read base image header"); + close(fd); + if (strncmp(basehdr.magic, + VM_MAGIC_QCOW, strlen(VM_MAGIC_QCOW)) != 0) + errx(1, "base image is not a qcow2 file"); + if (!disksz) + disksz = betoh64(basehdr.disksz); + else if (disksz != betoh64(basehdr.disksz)) + errx(1, "base size does not match requested size"); + } + if (!base_path && !disksz) + errx(1, "missing disk size"); + + clustersz = (1<<16); + l1off = ALIGNSZ(sizeof(hdr), clustersz); + + l1entrysz = clustersz * clustersz / 8; + l1sz = (disksz + l1entrysz - 1) / l1entrysz; + + refoff = ALIGNSZ(l1off + 8*l1sz, clustersz); + refentrysz = clustersz * clustersz * clustersz / 2; + refsz = (disksz + refentrysz - 1) / refentrysz; + + initsz = ALIGNSZ(refoff + refsz*clustersz, clustersz); + base_len = base_path ? strlen(base_path) : 0; + + memcpy(hdr.magic, VM_MAGIC_QCOW, strlen(VM_MAGIC_QCOW)); + hdr.version = htobe32(3); + hdr.backingoff = htobe64(base_path ? sizeof(hdr) : 0); + hdr.backingsz = htobe32(base_len); + hdr.clustershift = htobe32(16); + hdr.disksz = htobe64(disksz); + hdr.cryptmethod = htobe32(0); + hdr.l1sz = htobe32(l1sz); + hdr.l1off = htobe64(l1off); + hdr.refoff = htobe64(refoff); + hdr.refsz = htobe32(refsz); + hdr.snapcount = htobe32(0); + hdr.snapsz = htobe64(0); + hdr.incompatfeatures = htobe64(0); + hdr.compatfeatures = htobe64(0); + hdr.autoclearfeatures = htobe64(0); + hdr.reforder = htobe32(4); + hdr.headersz = htobe32(sizeof(hdr)); + + /* Refuse to overwrite an existing image */ + fd = open(imgfile_path, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, + S_IRUSR | S_IWUSR); + if (fd == -1) + return (errno); + + /* Write out the header */ + if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) + goto error; + + /* Add the base image */ + if (base_path && write(fd, base_path, base_len) != base_len) + goto error; + + /* Extend to desired size, and add one refcount cluster */ + if (ftruncate(fd, (off_t)initsz + clustersz) == -1) + goto error; + + /* + * Paranoia: if our disk image takes more than one cluster + * to refcount the initial image, fail. + */ + if (initsz/clustersz > clustersz/2) { + errno = ERANGE; + goto error; + } + + /* Add a refcount block, and refcount ourselves. */ + v = htobe64(initsz); + if (pwrite(fd, &v, 8, refoff) != 8) + goto error; + for (i = 0; i < initsz/clustersz + 1; i++) { + refs = htobe16(1); + if (pwrite(fd, &refs, 2, initsz + 2*i) != 2) + goto error; + } + + ret = close(fd); + return (ret); +error: + ret = errno; + close(fd); + unlink(imgfile_path); + return (errno); +} diff --git a/usr.sbin/vmd/vioraw.c b/usr.sbin/vmd/vioraw.c index 370e5b06892..de9ab65258c 100644 --- a/usr.sbin/vmd/vioraw.c +++ b/usr.sbin/vmd/vioraw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vioraw.c,v 1.4 2018/10/08 16:32:01 reyk Exp $ */ +/* $OpenBSD: vioraw.c,v 1.5 2018/11/26 10:39:30 reyk Exp $ */ /* * Copyright (c) 2018 Ori Bernstein <ori@eigenstate.org> * @@ -16,12 +16,15 @@ */ #include <sys/types.h> +#include <sys/stat.h> #include <machine/vmmvar.h> #include <dev/pci/pcireg.h> #include <stdlib.h> #include <unistd.h> +#include <fcntl.h> +#include <errno.h> #include "vmd.h" #include "vmm.h" @@ -53,7 +56,7 @@ raw_close(void *file, int stayopen) * returning -1 for error, 0 for success. */ int -virtio_init_raw(struct virtio_backing *file, off_t *szp, int *fd, size_t nfd) +virtio_raw_init(struct virtio_backing *file, off_t *szp, int *fd, size_t nfd) { off_t sz; int *fdp; @@ -76,3 +79,39 @@ virtio_init_raw(struct virtio_backing *file, off_t *szp, int *fd, size_t nfd) return 0; } +/* + * virtio_raw_create + * + * Create an empty imagefile with the specified path and size. + * + * Parameters: + * imgfile_path: path to the image file to create + * imgsize : size of the image file to create (in MB) + * + * 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 +virtio_raw_create(const char *imgfile_path, long imgsize) +{ + int fd, ret; + + /* Refuse to overwrite an existing image */ + fd = open(imgfile_path, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, + S_IRUSR | S_IWUSR); + if (fd == -1) + return (errno); + + /* Extend to desired size */ + if (ftruncate(fd, (off_t)imgsize * 1024 * 1024) == -1) { + ret = errno; + close(fd); + unlink(imgfile_path); + return (ret); + } + + ret = close(fd); + return (ret); +} diff --git a/usr.sbin/vmd/virtio.c b/usr.sbin/vmd/virtio.c index 4b84ae467fd..6397ba786a3 100644 --- a/usr.sbin/vmd/virtio.c +++ b/usr.sbin/vmd/virtio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: virtio.c,v 1.73 2018/10/19 10:12:39 reyk Exp $ */ +/* $OpenBSD: virtio.c,v 1.74 2018/11/26 10:39:30 reyk Exp $ */ /* * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> @@ -1771,9 +1771,9 @@ virtio_init_disk(struct virtio_backing *file, off_t *sz, */ switch (type) { case VMDF_RAW: - return virtio_init_raw(file, sz, fd, nfd); + return virtio_raw_init(file, sz, fd, nfd); case VMDF_QCOW2: - return virtio_init_qcow2(file, sz, fd, nfd); + return virtio_qcow2_init(file, sz, fd, nfd); } log_warnx("%s: invalid disk format", __func__); return -1; diff --git a/usr.sbin/vmd/virtio.h b/usr.sbin/vmd/virtio.h index 28aedc93e84..56dc536d1d3 100644 --- a/usr.sbin/vmd/virtio.h +++ b/usr.sbin/vmd/virtio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: virtio.h,v 1.32 2018/10/19 10:12:39 reyk Exp $ */ +/* $OpenBSD: virtio.h,v 1.33 2018/11/26 10:39:30 reyk Exp $ */ /* * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> @@ -20,6 +20,8 @@ #define VIRTQUEUE_ALIGN(n) (((n)+(VIRTIO_PAGE_SIZE-1))& \ ~(VIRTIO_PAGE_SIZE-1)) +#define ALIGNSZ(sz, align) ((sz + align - 1) & ~(align - 1)) +#define MIN(a,b) (((a)<(b))?(a):(b)) /* Queue sizes must be power of two */ #define VIORND_QUEUE_SIZE 64 @@ -272,8 +274,10 @@ void viornd_update_qa(void); int viornd_notifyq(void); ssize_t virtio_qcow2_get_base(int, char *, size_t, const char *); -int virtio_init_raw(struct virtio_backing *, off_t *, int*, size_t); -int virtio_init_qcow2(struct virtio_backing *, off_t *, int*, size_t); +int virtio_qcow2_create(const char *, const char *, long); +int virtio_qcow2_init(struct virtio_backing *, off_t *, int*, size_t); +int virtio_raw_create(const char *, long); +int virtio_raw_init(struct virtio_backing *, off_t *, int*, size_t); int virtio_blk_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t); int vioblk_dump(int); diff --git a/usr.sbin/vmd/vmboot.c b/usr.sbin/vmd/vmboot.c index ec8c07fd6e3..d249e8701eb 100644 --- a/usr.sbin/vmd/vmboot.c +++ b/usr.sbin/vmd/vmboot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmboot.c,v 1.6 2018/10/08 16:32:01 reyk Exp $ */ +/* $OpenBSD: vmboot.c,v 1.7 2018/11/26 10:39:30 reyk Exp $ */ /* * Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org> @@ -414,13 +414,13 @@ vmboot_open(int kernel_fd, int *disk_fd, int nfd, unsigned int disk_type, switch (vmboot->vbp_type) { case VMDF_RAW: - if (virtio_init_raw(vfp, &sz, disk_fd, nfd) == -1) { + if (virtio_raw_init(vfp, &sz, disk_fd, nfd) == -1) { log_debug("%s: could not open raw disk", __func__); goto fail; } break; case VMDF_QCOW2: - if (virtio_init_qcow2(vfp, &sz, disk_fd, nfd) == -1) { + if (virtio_qcow2_init(vfp, &sz, disk_fd, nfd) == -1) { log_debug("%s: could not open qcow2 disk", __func__); goto fail; } |