1 /* 2 * Threaded data processing for Qcow2: compression, encryption 3 * 4 * Copyright (c) 2004-2006 Fabrice Bellard 5 * Copyright (c) 2018 Virtuozzo International GmbH. All rights reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 #include "qemu/osdep.h" 27 28 #define ZLIB_CONST 29 #include <zlib.h> 30 31 #include "qcow2.h" 32 #include "block/thread-pool.h" 33 #include "crypto.h" 34 35 static int coroutine_fn 36 qcow2_co_process(BlockDriverState *bs, ThreadPoolFunc *func, void *arg) 37 { 38 int ret; 39 BDRVQcow2State *s = bs->opaque; 40 ThreadPool *pool = aio_get_thread_pool(bdrv_get_aio_context(bs)); 41 42 qemu_co_mutex_lock(&s->lock); 43 while (s->nb_threads >= QCOW2_MAX_THREADS) { 44 qemu_co_queue_wait(&s->thread_task_queue, &s->lock); 45 } 46 s->nb_threads++; 47 qemu_co_mutex_unlock(&s->lock); 48 49 ret = thread_pool_submit_co(pool, func, arg); 50 51 qemu_co_mutex_lock(&s->lock); 52 s->nb_threads--; 53 qemu_co_queue_next(&s->thread_task_queue); 54 qemu_co_mutex_unlock(&s->lock); 55 56 return ret; 57 } 58 59 60 /* 61 * Compression 62 */ 63 64 typedef ssize_t (*Qcow2CompressFunc)(void *dest, size_t dest_size, 65 const void *src, size_t src_size); 66 typedef struct Qcow2CompressData { 67 void *dest; 68 size_t dest_size; 69 const void *src; 70 size_t src_size; 71 ssize_t ret; 72 73 Qcow2CompressFunc func; 74 } Qcow2CompressData; 75 76 /* 77 * qcow2_compress() 78 * 79 * @dest - destination buffer, @dest_size bytes 80 * @src - source buffer, @src_size bytes 81 * 82 * Returns: compressed size on success 83 * -ENOMEM destination buffer is not enough to store compressed data 84 * -EIO on any other error 85 */ 86 static ssize_t qcow2_compress(void *dest, size_t dest_size, 87 const void *src, size_t src_size) 88 { 89 ssize_t ret; 90 z_stream strm; 91 92 /* best compression, small window, no zlib header */ 93 memset(&strm, 0, sizeof(strm)); 94 ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 95 -12, 9, Z_DEFAULT_STRATEGY); 96 if (ret != Z_OK) { 97 return -EIO; 98 } 99 100 /* 101 * strm.next_in is not const in old zlib versions, such as those used on 102 * OpenBSD/NetBSD, so cast the const away 103 */ 104 strm.avail_in = src_size; 105 strm.next_in = (void *) src; 106 strm.avail_out = dest_size; 107 strm.next_out = dest; 108 109 ret = deflate(&strm, Z_FINISH); 110 if (ret == Z_STREAM_END) { 111 ret = dest_size - strm.avail_out; 112 } else { 113 ret = (ret == Z_OK ? -ENOMEM : -EIO); 114 } 115 116 deflateEnd(&strm); 117 118 return ret; 119 } 120 121 /* 122 * qcow2_decompress() 123 * 124 * Decompress some data (not more than @src_size bytes) to produce exactly 125 * @dest_size bytes. 126 * 127 * @dest - destination buffer, @dest_size bytes 128 * @src - source buffer, @src_size bytes 129 * 130 * Returns: 0 on success 131 * -1 on fail 132 */ 133 static ssize_t qcow2_decompress(void *dest, size_t dest_size, 134 const void *src, size_t src_size) 135 { 136 int ret = 0; 137 z_stream strm; 138 139 memset(&strm, 0, sizeof(strm)); 140 strm.avail_in = src_size; 141 strm.next_in = (void *) src; 142 strm.avail_out = dest_size; 143 strm.next_out = dest; 144 145 ret = inflateInit2(&strm, -12); 146 if (ret != Z_OK) { 147 return -1; 148 } 149 150 ret = inflate(&strm, Z_FINISH); 151 if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || strm.avail_out != 0) { 152 /* 153 * We approve Z_BUF_ERROR because we need @dest buffer to be filled, but 154 * @src buffer may be processed partly (because in qcow2 we know size of 155 * compressed data with precision of one sector) 156 */ 157 ret = -1; 158 } 159 160 inflateEnd(&strm); 161 162 return ret; 163 } 164 165 static int qcow2_compress_pool_func(void *opaque) 166 { 167 Qcow2CompressData *data = opaque; 168 169 data->ret = data->func(data->dest, data->dest_size, 170 data->src, data->src_size); 171 172 return 0; 173 } 174 175 static ssize_t coroutine_fn 176 qcow2_co_do_compress(BlockDriverState *bs, void *dest, size_t dest_size, 177 const void *src, size_t src_size, Qcow2CompressFunc func) 178 { 179 Qcow2CompressData arg = { 180 .dest = dest, 181 .dest_size = dest_size, 182 .src = src, 183 .src_size = src_size, 184 .func = func, 185 }; 186 187 qcow2_co_process(bs, qcow2_compress_pool_func, &arg); 188 189 return arg.ret; 190 } 191 192 ssize_t coroutine_fn 193 qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, 194 const void *src, size_t src_size) 195 { 196 return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, 197 qcow2_compress); 198 } 199 200 ssize_t coroutine_fn 201 qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size, 202 const void *src, size_t src_size) 203 { 204 return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, 205 qcow2_decompress); 206 } 207 208 209 /* 210 * Cryptography 211 */ 212 213 /* 214 * Qcow2EncDecFunc: common prototype of qcrypto_block_encrypt() and 215 * qcrypto_block_decrypt() functions. 216 */ 217 typedef int (*Qcow2EncDecFunc)(QCryptoBlock *block, uint64_t offset, 218 uint8_t *buf, size_t len, Error **errp); 219 220 typedef struct Qcow2EncDecData { 221 QCryptoBlock *block; 222 uint64_t offset; 223 uint8_t *buf; 224 size_t len; 225 226 Qcow2EncDecFunc func; 227 } Qcow2EncDecData; 228 229 static int qcow2_encdec_pool_func(void *opaque) 230 { 231 Qcow2EncDecData *data = opaque; 232 233 return data->func(data->block, data->offset, data->buf, data->len, NULL); 234 } 235 236 static int coroutine_fn 237 qcow2_co_encdec(BlockDriverState *bs, uint64_t file_cluster_offset, 238 uint64_t offset, void *buf, size_t len, Qcow2EncDecFunc func) 239 { 240 BDRVQcow2State *s = bs->opaque; 241 Qcow2EncDecData arg = { 242 .block = s->crypto, 243 .offset = s->crypt_physical_offset ? 244 file_cluster_offset + offset_into_cluster(s, offset) : 245 offset, 246 .buf = buf, 247 .len = len, 248 .func = func, 249 }; 250 251 return qcow2_co_process(bs, qcow2_encdec_pool_func, &arg); 252 } 253 254 int coroutine_fn 255 qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset, 256 uint64_t offset, void *buf, size_t len) 257 { 258 return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len, 259 qcrypto_block_encrypt); 260 } 261 262 int coroutine_fn 263 qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset, 264 uint64_t offset, void *buf, size_t len) 265 { 266 return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len, 267 qcrypto_block_decrypt); 268 } 269