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