]> git.proxmox.com Git - pve-qemu-kvm.git/commitdiff
snapshot_start: use bdrv instead of file
authorDietmar Maurer <dietmar@proxmox.com>
Fri, 14 Sep 2012 09:09:45 +0000 (11:09 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Fri, 14 Sep 2012 12:09:52 +0000 (14:09 +0200)
So that we can store state on any valid qemu block device.

qemu-img: return success for non-existing snapshots on snapshot removal

Makefile
debian/changelog
debian/patches/fix-qemu-img-snapshot-removal.patch [new file with mode: 0644]
debian/patches/internal-snapshot.patch
debian/patches/series
debian/rules
new/qemu-file.h [new file with mode: 0644]

index b8036648805137c49c0057e4977e1a309b26c2b2..3b54169d1617b93d3230ada451abb1afece77719 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ RELEASE=2.2
 
 # also update debian/changelog
 KVMVER=1.2
-KVMPKGREL=5
+KVMPKGREL=6
 
 KVMPACKAGE=pve-qemu-kvm
 KVMDIR=qemu-kvm
index e9b3310af1ca621cd5ef04a27e099adce58516c5..39d032f9357741d026ef4003fd0cd80e0dd1b28c 100644 (file)
@@ -1,7 +1,13 @@
+pve-qemu-kvm (1.2-6) unstable; urgency=low
+
+  * qemu-img: return success for non-existing snapshots on snapshot removal
+
+ -- Proxmox Support Team <support@proxmox.com>  Fri, 14 Sep 2012 11:09:09 +0200
+
 pve-qemu-kvm (1.2-5) unstable; urgency=low
 
   * update to 1.2.0
-
+  
  -- Proxmox Support Team <support@proxmox.com>  Fri, 07 Sep 2012 07:40:06 +0200
 
 pve-qemu-kvm (1.2-4) unstable; urgency=low
diff --git a/debian/patches/fix-qemu-img-snapshot-removal.patch b/debian/patches/fix-qemu-img-snapshot-removal.patch
new file mode 100644 (file)
index 0000000..14a2eaa
--- /dev/null
@@ -0,0 +1,15 @@
+Index: new/qemu-img.c
+===================================================================
+--- new.orig/qemu-img.c        2012-09-14 11:03:04.000000000 +0200
++++ new/qemu-img.c     2012-09-14 11:13:39.000000000 +0200
+@@ -1288,7 +1288,9 @@
+             error_report("Could not delete snapshot '%s': %d (%s)",
+                 snapshot_name, ret, strerror(-ret));
+         }
+-        break;
++      // return success if snapshot does not exists
++      if (ret == -ENOENT) ret = 0;
++       break;
+     }
+     /* Cleanup */
index bf1fdf678d48a52dc74f96723315197c9f8af76d..f88af282d6a86046c5fc406cd3773470451fee3e 100644 (file)
@@ -18,8 +18,8 @@ Index: new/qapi-schema.json
 Index: new/qmp.c
 ===================================================================
 --- new.orig/qmp.c     2012-09-07 07:41:45.000000000 +0200
-+++ new/qmp.c  2012-09-13 09:22:06.000000000 +0200
-@@ -479,3 +479,191 @@
++++ new/qmp.c  2012-09-14 14:06:56.000000000 +0200
+@@ -479,3 +479,224 @@
      return arch_query_cpu_definitions(errp);
  }
  
@@ -28,8 +28,23 @@ Index: new/qmp.c
 +      int saved_vm_running;
 +} snap_state;
 +
++static int block_put_buffer(void *opaque, const uint8_t *buf,
++                           int64_t pos, int size)
++{
++      bdrv_pwrite(opaque, pos, buf, size);
++      return size;
++}
++
++static int bdrv_fclose(void *opaque)
++{
++      return bdrv_flush(opaque);
++}
++
 +void qmp_snapshot_start(bool has_statefile, const char *statefile, Error **errp)
 +{
++      BlockDriverState *bs = NULL;
++      BlockDriver *drv = NULL;
++      int bdrv_oflags = BDRV_O_NOCACHE | BDRV_O_RDWR;
 +      QEMUFile *f;
 +      int ret;
 +
@@ -48,19 +63,35 @@ Index: new/qmp.c
 +      if (!has_statefile)
 +              return;
 +
-+      f = qemu_fopen(statefile, "wb");
++      /* Open the image */
++      bs = bdrv_new("vmstate");
++      ret = bdrv_open(bs, statefile, bdrv_oflags, drv);
++      if (ret < 0) {
++              error_set(errp, QERR_OPEN_FILE_FAILED, statefile);
++              goto restart;
++      }
++
++      f = qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose,
++                         NULL, NULL, NULL);
 +      if (!f) {
 +              error_set(errp, QERR_OPEN_FILE_FAILED, statefile);
 +              goto restart;
 +      }
 +
 +      ret = qemu_savevm_state(f);
++
++      bdrv_truncate(bs, qemu_ftell(f)); // ignore errors
++
 +      qemu_fclose(f);
++
 +      if (ret < 0) {
 +              error_set(errp, ERROR_CLASS_GENERIC_ERROR,
 +                        "Error %d while writing VM state\n", ret);
-+              goto restart;
++                      goto restart;
 +      }
++end:
++      if (bs)
++              bdrv_delete(bs);
 +
 +      return;
 +
@@ -71,6 +102,8 @@ Index: new/qmp.c
 +      if (snap_state.saved_vm_running) {
 +              vm_start();
 +      }
++
++      goto end;
 +}
 +
 +void qmp_snapshot_end(Error **errp)
@@ -345,7 +378,16 @@ Index: new/hmp-commands.hx
 Index: new/savevm.c
 ===================================================================
 --- new.orig/savevm.c  2012-09-07 07:41:45.000000000 +0200
-+++ new/savevm.c       2012-09-13 09:22:06.000000000 +0200
++++ new/savevm.c       2012-09-14 11:32:17.000000000 +0200
+@@ -404,7 +404,7 @@
+     return bdrv_flush(opaque);
+ }
+-static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
++QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
+ {
+     if (is_writable)
+         return qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose, 
 @@ -1724,7 +1724,7 @@
      }
  }
@@ -367,3 +409,15 @@ Index: new/sysemu.h
  int qemu_loadvm_state(QEMUFile *f);
  
  /* SLIRP */
+Index: new/qemu-file.h
+===================================================================
+--- new.orig/qemu-file.h       2012-09-14 11:51:31.000000000 +0200
++++ new/qemu-file.h    2012-09-14 11:51:47.000000000 +0200
+@@ -68,6 +68,7 @@
+ QEMUFile *qemu_fopen(const char *filename, const char *mode);
+ QEMUFile *qemu_fdopen(int fd, const char *mode);
+ QEMUFile *qemu_fopen_socket(int fd);
++QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable);
+ QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
+ QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
+ int qemu_stdio_fd(QEMUFile *f);
index e605ce29cf9726fa4aff924fbe1ec680d0db606f..e1f6444dadb657bc646f462d4323d30dac39613f 100644 (file)
@@ -11,3 +11,4 @@ ahci-properly-reset-pxcmd.patch
 #modify-qapi-schema.patch
 #implement-snapshot-drive.patch
 internal-snapshot.patch
+fix-qemu-img-snapshot-removal.patch
index 2604b8d17ad7c80cb7ffd84ff7354f8327e40c36..d5d132d0c73fa572de8929c7975db781704558d5 100755 (executable)
@@ -41,7 +41,7 @@ build-stamp:  config.status
        dh_testdir
 
        # Add here commands to compile the package.
-       $(MAKE) V=1
+       $(MAKE)
 
        #docbook-to-man debian/kvm.sgml > kvm.1
 
diff --git a/new/qemu-file.h b/new/qemu-file.h
new file mode 100644 (file)
index 0000000..f719b02
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef QEMU_FILE_H
+#define QEMU_FILE_H 1
+
+/* This function writes a chunk of data to a file at the given position.
+ * The pos argument can be ignored if the file is only being used for
+ * streaming.  The handler should try to write all of the data it can.
+ */
+typedef int (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf,
+                                    int64_t pos, int size);
+
+/* Read a chunk of data from a file at the given position.  The pos argument
+ * can be ignored if the file is only be used for streaming.  The number of
+ * bytes actually read should be returned.
+ */
+typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf,
+                                    int64_t pos, int size);
+
+/* Close a file
+ *
+ * Return negative error number on error, 0 or positive value on success.
+ *
+ * The meaning of return value on success depends on the specific back-end being
+ * used.
+ */
+typedef int (QEMUFileCloseFunc)(void *opaque);
+
+/* Called to determine if the file has exceeded its bandwidth allocation.  The
+ * bandwidth capping is a soft limit, not a hard limit.
+ */
+typedef int (QEMUFileRateLimit)(void *opaque);
+
+/* Called to change the current bandwidth allocation. This function must return
+ * the new actual bandwidth. It should be new_rate if everything goes ok, and
+ * the old rate otherwise
+ */
+typedef int64_t (QEMUFileSetRateLimit)(void *opaque, int64_t new_rate);
+typedef int64_t (QEMUFileGetRateLimit)(void *opaque);
+
+QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
+                         QEMUFileGetBufferFunc *get_buffer,
+                         QEMUFileCloseFunc *close,
+                         QEMUFileRateLimit *rate_limit,
+                         QEMUFileSetRateLimit *set_rate_limit,
+                         QEMUFileGetRateLimit *get_rate_limit);
+QEMUFile *qemu_fopen(const char *filename, const char *mode);
+QEMUFile *qemu_fdopen(int fd, const char *mode);
+QEMUFile *qemu_fopen_socket(int fd);
+QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable);
+QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
+QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
+int qemu_stdio_fd(QEMUFile *f);
+void qemu_fflush(QEMUFile *f);
+int qemu_fclose(QEMUFile *f);
+void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
+void qemu_put_byte(QEMUFile *f, int v);
+
+static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v)
+{
+    qemu_put_byte(f, (int)v);
+}
+
+#define qemu_put_sbyte qemu_put_byte
+
+void qemu_put_be16(QEMUFile *f, unsigned int v);
+void qemu_put_be32(QEMUFile *f, unsigned int v);
+void qemu_put_be64(QEMUFile *f, uint64_t v);
+int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size);
+int qemu_get_byte(QEMUFile *f);
+
+static inline unsigned int qemu_get_ubyte(QEMUFile *f)
+{
+    return (unsigned int)qemu_get_byte(f);
+}
+
+#define qemu_get_sbyte qemu_get_byte
+
+unsigned int qemu_get_be16(QEMUFile *f);
+unsigned int qemu_get_be32(QEMUFile *f);
+uint64_t qemu_get_be64(QEMUFile *f);
+
+int qemu_file_rate_limit(QEMUFile *f);
+int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
+int64_t qemu_file_get_rate_limit(QEMUFile *f);
+int qemu_file_get_error(QEMUFile *f);
+void qemu_file_set_error(QEMUFile *f, int error);
+
+/* Try to send any outstanding data.  This function is useful when output is
+ * halted due to rate limiting or EAGAIN errors occur as it can be used to
+ * resume output. */
+void qemu_file_put_notify(QEMUFile *f);
+
+static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
+{
+    qemu_put_be64(f, *pv);
+}
+
+static inline void qemu_put_be32s(QEMUFile *f, const uint32_t *pv)
+{
+    qemu_put_be32(f, *pv);
+}
+
+static inline void qemu_put_be16s(QEMUFile *f, const uint16_t *pv)
+{
+    qemu_put_be16(f, *pv);
+}
+
+static inline void qemu_put_8s(QEMUFile *f, const uint8_t *pv)
+{
+    qemu_put_byte(f, *pv);
+}
+
+static inline void qemu_get_be64s(QEMUFile *f, uint64_t *pv)
+{
+    *pv = qemu_get_be64(f);
+}
+
+static inline void qemu_get_be32s(QEMUFile *f, uint32_t *pv)
+{
+    *pv = qemu_get_be32(f);
+}
+
+static inline void qemu_get_be16s(QEMUFile *f, uint16_t *pv)
+{
+    *pv = qemu_get_be16(f);
+}
+
+static inline void qemu_get_8s(QEMUFile *f, uint8_t *pv)
+{
+    *pv = qemu_get_byte(f);
+}
+
+// Signed versions for type safety
+static inline void qemu_put_sbuffer(QEMUFile *f, const int8_t *buf, int size)
+{
+    qemu_put_buffer(f, (const uint8_t *)buf, size);
+}
+
+static inline void qemu_put_sbe16(QEMUFile *f, int v)
+{
+    qemu_put_be16(f, (unsigned int)v);
+}
+
+static inline void qemu_put_sbe32(QEMUFile *f, int v)
+{
+    qemu_put_be32(f, (unsigned int)v);
+}
+
+static inline void qemu_put_sbe64(QEMUFile *f, int64_t v)
+{
+    qemu_put_be64(f, (uint64_t)v);
+}
+
+static inline size_t qemu_get_sbuffer(QEMUFile *f, int8_t *buf, int size)
+{
+    return qemu_get_buffer(f, (uint8_t *)buf, size);
+}
+
+static inline int qemu_get_sbe16(QEMUFile *f)
+{
+    return (int)qemu_get_be16(f);
+}
+
+static inline int qemu_get_sbe32(QEMUFile *f)
+{
+    return (int)qemu_get_be32(f);
+}
+
+static inline int64_t qemu_get_sbe64(QEMUFile *f)
+{
+    return (int64_t)qemu_get_be64(f);
+}
+
+static inline void qemu_put_s8s(QEMUFile *f, const int8_t *pv)
+{
+    qemu_put_8s(f, (const uint8_t *)pv);
+}
+
+static inline void qemu_put_sbe16s(QEMUFile *f, const int16_t *pv)
+{
+    qemu_put_be16s(f, (const uint16_t *)pv);
+}
+
+static inline void qemu_put_sbe32s(QEMUFile *f, const int32_t *pv)
+{
+    qemu_put_be32s(f, (const uint32_t *)pv);
+}
+
+static inline void qemu_put_sbe64s(QEMUFile *f, const int64_t *pv)
+{
+    qemu_put_be64s(f, (const uint64_t *)pv);
+}
+
+static inline void qemu_get_s8s(QEMUFile *f, int8_t *pv)
+{
+    qemu_get_8s(f, (uint8_t *)pv);
+}
+
+static inline void qemu_get_sbe16s(QEMUFile *f, int16_t *pv)
+{
+    qemu_get_be16s(f, (uint16_t *)pv);
+}
+
+static inline void qemu_get_sbe32s(QEMUFile *f, int32_t *pv)
+{
+    qemu_get_be32s(f, (uint32_t *)pv);
+}
+
+static inline void qemu_get_sbe64s(QEMUFile *f, int64_t *pv)
+{
+    qemu_get_be64s(f, (uint64_t *)pv);
+}
+
+int64_t qemu_ftell(QEMUFile *f);
+int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence);
+
+#endif