]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools, qcow: I/O error on compressed sectors
authorPekka Enberg <penberg@kernel.org>
Sun, 10 Jul 2011 12:36:11 +0000 (15:36 +0300)
committerPekka Enberg <penberg@kernel.org>
Sun, 10 Jul 2011 12:47:34 +0000 (15:47 +0300)
We currently don't support compressed sectors in QCOW images so warn the user
about it and return a I/O error.

Cc: Asias He <asias.hejun@gmail.com>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Prasad Joshi <prasadjoshi124@gmail.com>
Cc: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/disk/qcow.c
tools/kvm/include/kvm/qcow.h

index 13c8bea496f621c1b88eb5eed3f8b3eef3c738e0..bf0ac33a47aae5dc59a1396595ab42d18fc831a1 100644 (file)
@@ -260,7 +260,14 @@ static ssize_t qcow_read_cluster(struct qcow *q, u64 offset, void *dst, u32 dst_
                length = dst_len;
 
        mutex_lock(&q->mutex);
-       l2_table_offset = be64_to_cpu(table->l1_table[l1_idx]) & ~header->oflag_mask;
+
+       l2_table_offset = be64_to_cpu(table->l1_table[l1_idx]);
+       if (l2_table_offset & QCOW_OFLAG_COMPRESSED) {
+               pr_warning("compressed sectors are not supported");
+               goto out_error;
+       }
+
+       l2_table_offset &= QCOW_OFFSET_MASK;
        if (!l2_table_offset)
                goto zero_cluster;
 
@@ -275,7 +282,13 @@ static ssize_t qcow_read_cluster(struct qcow *q, u64 offset, void *dst, u32 dst_
        if (l2_idx >= l2_table_size)
                goto out_error;
 
-       clust_start = be64_to_cpu(l2_table->table[l2_idx]) & ~header->oflag_mask;
+       clust_start = be64_to_cpu(l2_table->table[l2_idx]);
+       if (clust_start & QCOW_OFLAG_COMPRESSED) {
+               pr_warning("compressed sectors are not supported");
+               goto out_error;
+       }
+
+       clust_start &= QCOW_OFFSET_MASK;
        if (!clust_start)
                goto zero_cluster;
 
@@ -414,7 +427,13 @@ static ssize_t qcow_write_cluster(struct qcow *q, u64 offset, void *buf, u32 src
 
        mutex_lock(&q->mutex);
 
-       l2t_off         = be64_to_cpu(table->l1_table[l1t_idx]) & ~header->oflag_mask;
+       l2t_off = be64_to_cpu(table->l1_table[l1t_idx]);
+       if (l2t_off & QCOW_OFLAG_COMPRESSED) {
+               pr_warning("compressed sectors are not supported");
+               goto error;
+       }
+
+       l2t_off &= QCOW_OFFSET_MASK;
        if (l2t_off) {
                /* read and cache l2 table */
                l2t = qcow_read_l2_table(q, l2t_off);
@@ -451,7 +470,13 @@ static ssize_t qcow_write_cluster(struct qcow *q, u64 offset, void *buf, u32 src
        if (!f_sz)
                goto error;
 
-       clust_start     = be64_to_cpu(l2t->table[l2t_idx]) & ~header->oflag_mask;
+       clust_start     = be64_to_cpu(l2t->table[l2t_idx]);
+       if (clust_start & QCOW_OFLAG_COMPRESSED) {
+               pr_warning("compressed sectors are not supported");
+               goto error;
+       }
+
+       clust_start &= QCOW_OFFSET_MASK;
        if (!clust_start) {
                clust_start             = ALIGN(f_sz, clust_sz);
                l2t->table[l2t_idx]     = cpu_to_be64(clust_start);
@@ -621,7 +646,6 @@ static void *qcow2_read_header(int fd)
                .l1_size                = f_header.l1_size,
                .cluster_bits           = f_header.cluster_bits,
                .l2_bits                = f_header.cluster_bits - 3,
-               .oflag_mask             = QCOW2_OFLAG_MASK,
        };
 
        return header;
@@ -721,7 +745,6 @@ static void *qcow1_read_header(int fd)
                .l1_size                = f_header.size / ((1 << f_header.l2_bits) * (1 << f_header.cluster_bits)),
                .cluster_bits           = f_header.cluster_bits,
                .l2_bits                = f_header.l2_bits,
-               .oflag_mask             = QCOW1_OFLAG_MASK,
        };
 
        return header;
index 650d3c290fd73b9afc8e18c7828059308b8f8e31..ec9c77db4325c7afb21dfd2074bc39c8b187e10a 100644 (file)
 #define QCOW1_VERSION          1
 #define QCOW2_VERSION          2
 
-#define QCOW1_OFLAG_COMPRESSED (1LL << 63)
+#define QCOW_OFLAG_COPIED      (1ULL << 63)
+#define QCOW_OFLAG_COMPRESSED  (1ULL << 62)
 
-#define QCOW1_OFLAG_MASK       QCOW1_OFLAG_COMPRESSED
+#define QCOW_OFLAGS_MASK       (QCOW_OFLAG_COPIED|QCOW_OFLAG_COMPRESSED)
 
-#define QCOW2_OFLAG_COPIED     (1LL << 63)
-#define QCOW2_OFLAG_COMPRESSED (1LL << 62)
-#define QCOW2_OFLAG_MASK       (QCOW2_OFLAG_COPIED|QCOW2_OFLAG_COMPRESSED)
+#define QCOW_OFFSET_MASK       (~QCOW_OFLAGS_MASK)
 
 #define MAX_CACHE_NODES         32
 
@@ -54,7 +53,6 @@ struct qcow_header {
        u32                     l1_size;
        u8                      cluster_bits;
        u8                      l2_bits;
-       u64                     oflag_mask;
 };
 
 struct qcow1_header_disk {