wok rev 23680

qemu: partial cloop v4 support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Apr 26 15:17:58 2020 +0000 (2020-04-26)
parents ce15cfce8e9f
children 9be86beee5ec
files qemu/receipt qemu/stuff/cloop.u
line diff
     1.1 --- a/qemu/receipt	Sun Apr 26 10:50:29 2020 +0000
     1.2 +++ b/qemu/receipt	Sun Apr 26 15:17:58 2020 +0000
     1.3 @@ -14,10 +14,10 @@
     1.4  TAGS="virtualization emulator"
     1.5  
     1.6  DEPENDS="alsa-lib gnutls libsdl bluez libtasn1 libsasl vde2 libcurl ncurses \
     1.7 -attr util-linux-uuid libgio glib libusb"
     1.8 +attr util-linux-uuid libgio glib libusb zlib liblzma"
     1.9  BUILD_DEPENDS="gettext perl alsa-lib-dev gnutls-dev libsdl-dev bluez-dev \
    1.10  libtasn1-dev vde2-dev curl-dev attr-dev util-linux-uuid-dev libgio-dev \
    1.11 -glib-dev autoconf automake libtool bison flex libusb-dev ncurses-dev file"
    1.12 +glib-dev autoconf automake libtool bison flex libusb-dev ncurses-dev xz-dev file"
    1.13  
    1.14  # Rules to configure and make the package.
    1.15  compile_rules()
     2.1 --- a/qemu/stuff/cloop.u	Sun Apr 26 10:50:29 2020 +0000
     2.2 +++ b/qemu/stuff/cloop.u	Sun Apr 26 15:17:58 2020 +0000
     2.3 @@ -1,6 +1,22 @@
     2.4 ---- block/cloop.c
     2.5 -+++ block/cloop.c
     2.6 -@@ -29,11 +29,90 @@
     2.7 +--- source/qemu-2.0.2/block/cloop.c	2014-08-18 18:03:24.000000000 +0200
     2.8 ++++ cloop.c	2020-04-26 16:58:23.306636715 +0200
     2.9 +@@ -25,33 +25,206 @@
    2.10 + #include "block/block_int.h"
    2.11 + #include "qemu/module.h"
    2.12 + #include <zlib.h>
    2.13 ++#include <lzma.h>
    2.14 ++
    2.15 ++#define CLOOP_COMPRESSOR_ZLIB  0x0
    2.16 ++#define CLOOP_COMPRESSOR_NONE  0x1
    2.17 ++#define CLOOP_COMPRESSOR_XZ    0x2
    2.18 ++#define CLOOP_COMPRESSOR_LZ4   0x3
    2.19 ++#define CLOOP_COMPRESSOR_LZO   0x4
    2.20 ++#define CLOOP_COMPRESSOR_ZSTD  0x5
    2.21 ++#define CLOOP_COMPRESSOR_LINK  0xF
    2.22 ++
    2.23 ++#define CLOOP_BLOCK_FLAGS(x)  ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60))
    2.24 ++#define CLOOP_BLOCK_OFFSET(x)  ((x) & 0x0fffffffffffffffLLU)
    2.25 + 
    2.26   /* Maximum compressed block size */
    2.27   #define MAX_BLOCK_SIZE (64 * 1024 * 1024)
    2.28   
    2.29 @@ -10,74 +26,114 @@
    2.30  +	uint32_t num_blocks;
    2.31  +} cloop_tail;
    2.32  +
    2.33 ++#define CLOOP3_INDEX_SIZE(x)    ((unsigned int)((x) & 0xF))
    2.34 ++#define CLOOP3_BLOCKS_FLAGS(x)  ((unsigned int)((x) & 0x70) >> 4)
    2.35 ++
    2.36  +typedef struct block_info {
    2.37  +	uint64_t offset;	/* 64-bit offsets of compressed block */
    2.38  +	uint32_t size;		/* 32-bit compressed block size */
    2.39 -+	uint32_t optidx;	/* 32-bit index number */
    2.40 ++	uint32_t flags;		/* 32-bit compression flags */
    2.41  +} block_info;
    2.42  +
    2.43 -+static inline int build_index(block_info *offsets, unsigned long n)
    2.44 ++static inline int build_index(struct block_info *offsets, unsigned long n, 
    2.45 ++			unsigned long block_size, unsigned global_flags)
    2.46  +{
    2.47  +	uint32_t *ofs32 = (uint32_t *) offsets;
    2.48 -+	uint64_t *ofs64 = (uint64_t *) offsets;
    2.49 -+	
    2.50 ++	loff_t    *ofs64 = (loff_t *) offsets;
    2.51 ++
    2.52 ++	/* v3 64bits bug: v1 assumed */
    2.53 ++	unsigned long	v3_64;
    2.54 ++	loff_t	prev;
    2.55 ++
    2.56 ++	if (ofs32[0] != 0 && ofs32[1] == 0) {
    2.57 ++		for (v3_64=(n+1)/2, prev=le64_to_cpu(ofs64[v3_64]);
    2.58 ++		     v3_64 > 0 && le64_to_cpu(ofs64[--v3_64]) < prev;
    2.59 ++		     prev=le64_to_cpu(ofs64[v3_64]));
    2.60 ++	}
    2.61 ++
    2.62  +	if (ofs32[0] == 0) {
    2.63  +		if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
    2.64  +			while (n--) {
    2.65  +				offsets[n].offset = be64_to_cpu(offsets[n].offset);
    2.66  +				offsets[n].size = ntohl(offsets[n].size);
    2.67 ++				offsets[n].flags = 0;
    2.68  +        			if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
    2.69  +        				return n+1;
    2.70  +			}
    2.71  +		}
    2.72 -+		else { /* V2.0 */
    2.73 -+			uint64_t last = be64_to_cpu(ofs64[n - 1]);
    2.74 -+			while (n--) {
    2.75 ++		else { /* V2.0/V4.0 */
    2.76 ++			loff_t last = CLOOP_BLOCK_OFFSET(be64_to_cpu(ofs64[n]));
    2.77 ++			uint32_t flags;
    2.78 ++			unsigned long i = n;
    2.79 ++
    2.80 ++			for (flags = 0; n-- ;) {
    2.81 ++				loff_t data = be64_to_cpu(ofs64[n]); 
    2.82 ++
    2.83  +				offsets[n].size = last - 
    2.84 -+					(offsets[n].offset = be64_to_cpu(ofs64[n])); 
    2.85 ++					(offsets[n].offset = CLOOP_BLOCK_OFFSET(data)); 
    2.86  +        			if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
    2.87  +        				return n+1;
    2.88  +				last = offsets[n].offset;
    2.89 ++				offsets[n].flags = CLOOP_BLOCK_FLAGS(data); 
    2.90 ++				flags |= 1 << offsets[n].flags;
    2.91 ++			}
    2.92 ++			if (flags > 1) {
    2.93 ++				while (i--) {
    2.94 ++					if (offsets[i].flags == CLOOP_COMPRESSOR_LINK) {
    2.95 ++						offsets[i] = offsets[offsets[i].offset];
    2.96 ++					}
    2.97 ++				}
    2.98  +			}
    2.99  +		}
   2.100  +	}
   2.101 -+	else if (ofs32[1] == 0) { /* V1.0 */
   2.102 -+		uint64_t last = le64_to_cpu(ofs64[n - 1]);
   2.103 ++	else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */
   2.104 ++		loff_t last = le64_to_cpu(ofs64[n]);
   2.105  +		while (n--) {
   2.106  +			offsets[n].size = last - 
   2.107  +				(offsets[n].offset = le64_to_cpu(ofs64[n])); 
   2.108  +        		if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
   2.109  +        			return n+1;
   2.110  +			last = offsets[n].offset;
   2.111 ++			offsets[n].flags = 0;
   2.112  +		}
   2.113  +	}
   2.114  +	else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
   2.115 -+		uint64_t last = ntohl(ofs32[n - 1]);
   2.116 ++		loff_t last = ntohl(ofs32[n]);
   2.117  +		while (n--) {
   2.118  +			offsets[n].size = last - 
   2.119  +				(offsets[n].offset = ntohl(ofs32[n])); 
   2.120  +        		if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
   2.121  +        			return n+1;
   2.122  +			last = offsets[n].offset;
   2.123 ++			offsets[n].flags = 0;
   2.124  +		}
   2.125  +	}
   2.126  +	else { /* V3.0 */
   2.127  +		unsigned long i;
   2.128 -+		uint64_t j;
   2.129 ++		loff_t j;
   2.130  +		
   2.131 ++		v3_64 = (ofs32[1] == 0) ? 2 : 1;
   2.132  +		for (i = n; i-- > 0; ) {
   2.133 -+			offsets[i].size = ntohl(ofs32[i]); 
   2.134 -+        		if (offsets[i].size > 2 * MAX_BLOCK_SIZE)
   2.135 ++			offsets[i].size = ntohl(ofs32[i*v3_64]); 
   2.136 ++			if ((offsets[i].size & 0x80000000) == 0 &&
   2.137 ++        		    offsets[i].size > 2 * MAX_BLOCK_SIZE)
   2.138  +        			return i+1;
   2.139  +		}
   2.140  +		for (i = 0, j = 128 + 4 + 4; i < n; i++) {
   2.141  +			offsets[i].offset = j;
   2.142 ++			offsets[i].flags = global_flags;
   2.143 ++			if (offsets[i].size == 0xFFFFFFFF) {
   2.144 ++				offsets[i].flags = CLOOP_COMPRESSOR_NONE;
   2.145 ++				offsets[i].size = block_size;
   2.146 ++			}
   2.147 ++			if ((offsets[i].size & 0x80000000) == 0) {
   2.148 ++				j += offsets[i].size;
   2.149 ++			}
   2.150 ++		}
   2.151 ++		for (i = 0; i < n; i++) {
   2.152  +			if (offsets[i].size & 0x80000000) {
   2.153 -+				unsigned long k = offsets[i].size & 0x7FFFFFFF;
   2.154 -+				offsets[i].offset = offsets[k].offset;
   2.155 -+				offsets[i].size = offsets[k].size;
   2.156 ++				offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF];
   2.157  +			}
   2.158 -+			else j += offsets[i].size;
   2.159  +		}
   2.160  +	}
   2.161  +	return 0;
   2.162 @@ -92,7 +148,10 @@
   2.163       uint32_t sectors_per_block;
   2.164       uint32_t current_block;
   2.165       uint8_t *compressed_block;
   2.166 -@@ -43,17 +117,21 @@
   2.167 +     uint8_t *uncompressed_block;
   2.168 +     z_stream zstream;
   2.169 ++    int global_flags;
   2.170 + } BDRVCloopState;
   2.171   
   2.172   static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
   2.173   {
   2.174 @@ -108,21 +167,55 @@
   2.175  +
   2.176  +    if (length > 127) {
   2.177  +        length = 127;
   2.178 -     }
   2.179 --    if (!memcmp(magic_version_2_0, buf, length)) {
   2.180 --        return 2;
   2.181 ++    }
   2.182  +    for (i = 0; i < length - sizeof(magic) + 1; i++) {
   2.183  +	if (buf[i] != magic[0]) continue;
   2.184  +	if (strncmp(buf + i, magic, sizeof(magic) - 1)) continue;
   2.185  +	ret = 2;
   2.186  +	break;
   2.187       }
   2.188 --    return 0;
   2.189 +-    if (!memcmp(magic_version_2_0, buf, length)) {
   2.190 +-        return 2;
   2.191  +    return ret;
   2.192 ++}
   2.193 ++
   2.194 ++static uint32_t cloop_upack(BDRVCloopState *s, int flag)
   2.195 ++{
   2.196 ++    int ret;
   2.197 ++    size_t src_pos;
   2.198 ++    size_t dest_pos;
   2.199 ++    uint64_t memlimit;
   2.200 ++    uint32_t outlen = s->zstream.total_out;
   2.201 ++
   2.202 ++    switch (flag) {
   2.203 ++    case CLOOP_COMPRESSOR_ZLIB:
   2.204 ++        ret = inflateReset(&s->zstream);
   2.205 ++        if (ret != Z_OK) {
   2.206 ++            return 0;
   2.207 ++        }
   2.208 ++        ret = inflate(&s->zstream, Z_FINISH);
   2.209 ++        if (ret != Z_STREAM_END || s->zstream.total_out != outlen) {
   2.210 ++            return 0;
   2.211 ++        }
   2.212 ++        return outlen;
   2.213 ++    case CLOOP_COMPRESSOR_NONE:
   2.214 ++	memcpy(s->zstream.next_out, s->zstream.next_in, s->zstream.avail_in);
   2.215 ++	return s->zstream.avail_in;
   2.216 ++    case CLOOP_COMPRESSOR_XZ:
   2.217 ++        src_pos = 0;
   2.218 ++        dest_pos = 0;
   2.219 ++        memlimit = 32*1024*1024;
   2.220 ++        ret = lzma_stream_buffer_decode(&memlimit, 0, NULL, s->zstream.next_in, &src_pos,
   2.221 ++		 s->zstream.avail_in, s->zstream.next_out, &dest_pos, s->zstream.total_out);
   2.222 ++
   2.223 ++        if(ret != LZMA_OK || s->zstream.avail_in != (int) src_pos) {
   2.224 ++            return 0;
   2.225 ++	}
   2.226 ++	return dest_pos;
   2.227 +     }
   2.228 +     return 0;
   2.229   }
   2.230 - 
   2.231 - static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
   2.232 -@@ -91,79 +169,97 @@
   2.233 +@@ -91,79 +264,92 @@
   2.234                      MAX_BLOCK_SIZE / (1024 * 1024));
   2.235           return -EINVAL;
   2.236       }
   2.237 @@ -198,7 +291,8 @@
   2.238  +            return -EINVAL;
   2.239           }
   2.240  +	len = be32_to_cpu(tail.table_size);
   2.241 -+	toclen = (be32_to_cpu(tail.index_size) & 255) * s->n_blocks;
   2.242 ++	toclen = CLOOP3_INDEX_SIZE(be32_to_cpu(tail.index_size)) * s->n_blocks;
   2.243 ++	s->global_flags = CLOOP3_BLOCKS_FLAGS(be32_to_cpu(tail.index_size));
   2.244   
   2.245  -        size = s->offsets[i] - s->offsets[i - 1];
   2.246  +        s->offsets = g_malloc(offsets_size);
   2.247 @@ -220,21 +314,12 @@
   2.248  +        s->zstream.avail_in = len;
   2.249  +        s->zstream.next_out = s->offsets;
   2.250  +        s->zstream.avail_out = toclen;
   2.251 -+        ret = inflateReset(&s->zstream);
   2.252 -+        if (ret != Z_OK) {
   2.253 ++	if (cloop_unpack(s, s->global_flags) == 0) {
   2.254               ret = -EINVAL;
   2.255               goto fail;
   2.256           }
   2.257 --
   2.258 --        if (size > max_compressed_block_size) {
   2.259 --            max_compressed_block_size = size;
   2.260 -+        ret = inflate(&s->zstream, Z_FINISH);
   2.261 -+        if (ret != Z_STREAM_END || s->zstream.total_out != toclen) {
   2.262 -+            ret = -EINVAL;
   2.263 -+            goto fail;
   2.264 -         }
   2.265  +	g_free(p);
   2.266 -     }
   2.267 ++    }
   2.268  +    else {
   2.269  +        offsets_size = s->n_blocks * sizeof(block_info);
   2.270  +        if (offsets_size > 512 * 1024 * 1024) {
   2.271 @@ -248,16 +333,19 @@
   2.272  +        }
   2.273  +        s->offsets = g_malloc(offsets_size);
   2.274   
   2.275 +-        if (size > max_compressed_block_size) {
   2.276 +-            max_compressed_block_size = size;
   2.277 ++        ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
   2.278 ++        if (ret < 0) {
   2.279 ++            goto fail;
   2.280 +         }
   2.281 +     }
   2.282 +-
   2.283  -    /* initialize zlib engine */
   2.284  -    s->compressed_block = g_malloc(max_compressed_block_size + 1);
   2.285  -    s->uncompressed_block = g_malloc(s->block_size);
   2.286  -    if (inflateInit(&s->zstream) != Z_OK) {
   2.287 -+        ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
   2.288 -+        if (ret < 0) {
   2.289 -+            goto fail;
   2.290 -+        }
   2.291 -+    }
   2.292 -+    ret = build_index(s->offsets, s->n_blocks);
   2.293 ++    ret = build_index(s->offsets, s->n_blocks, s->block_size, s->global_flags);
   2.294  +    if (ret) {
   2.295  +        error_setg(errp, "invalid compressed block size at index %u, "
   2.296  +                   "image file is corrupt", ret-1);
   2.297 @@ -268,7 +356,7 @@
   2.298       s->current_block = s->n_blocks;
   2.299   
   2.300       s->sectors_per_block = s->block_size/512;
   2.301 -@@ -184,10 +280,10 @@
   2.302 +@@ -184,10 +370,10 @@
   2.303   
   2.304       if (s->current_block != block_num) {
   2.305           int ret;
   2.306 @@ -282,3 +370,26 @@
   2.307           if (ret != bytes) {
   2.308               return -1;
   2.309           }
   2.310 +@@ -196,12 +382,7 @@
   2.311 +         s->zstream.avail_in = bytes;
   2.312 +         s->zstream.next_out = s->uncompressed_block;
   2.313 +         s->zstream.avail_out = s->block_size;
   2.314 +-        ret = inflateReset(&s->zstream);
   2.315 +-        if (ret != Z_OK) {
   2.316 +-            return -1;
   2.317 +-        }
   2.318 +-        ret = inflate(&s->zstream, Z_FINISH);
   2.319 +-        if (ret != Z_STREAM_END || s->zstream.total_out != s->block_size) {
   2.320 ++	if (cloop_unpack(s, s->offsets[block_num].flags) == 0) {
   2.321 +             return -1;
   2.322 +         }
   2.323 + 
   2.324 +--- source/qemu-2.0.2/block/Makefile.objs	2014-08-18 18:03:24.000000000 +0200
   2.325 ++++ Makefile.objs	2020-04-26 16:32:51.010232389 +0200
   2.326 +@@ -35,5 +35,5 @@
   2.327 + gluster.o-libs     := $(GLUSTERFS_LIBS)
   2.328 + ssh.o-cflags       := $(LIBSSH2_CFLAGS)
   2.329 + ssh.o-libs         := $(LIBSSH2_LIBS)
   2.330 +-qcow.o-libs        := -lz
   2.331 ++qcow.o-libs        := -lz -llzma
   2.332 + linux-aio.o-libs   := -laio