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 * -EIO 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; 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 -EIO; 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 = 0; 158 } else { 159 ret = -EIO; 160 } 161 162 inflateEnd(&strm); 163 164 return ret; 165 } 166 167 static int qcow2_compress_pool_func(void *opaque) 168 { 169 Qcow2CompressData *data = opaque; 170 171 data->ret = data->func(data->dest, data->dest_size, 172 data->src, data->src_size); 173 174 return 0; 175 } 176 177 static ssize_t coroutine_fn 178 qcow2_co_do_compress(BlockDriverState *bs, void *dest, size_t dest_size, 179 const void *src, size_t src_size, Qcow2CompressFunc func) 180 { 181 Qcow2CompressData arg = { 182 .dest = dest, 183 .dest_size = dest_size, 184 .src = src, 185 .src_size = src_size, 186 .func = func, 187 }; 188 189 qcow2_co_process(bs, qcow2_compress_pool_func, &arg); 190 191 return arg.ret; 192 } 193 194 ssize_t coroutine_fn 195 qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size, 196 const void *src, size_t src_size) 197 { 198 return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, 199 qcow2_compress); 200 } 201 202 ssize_t coroutine_fn 203 qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size, 204 const void *src, size_t src_size) 205 { 206 return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, 207 qcow2_decompress); 208 } 209 210 211 /* 212 * Cryptography 213 */ 214 215 /* 216 * Qcow2EncDecFunc: common prototype of qcrypto_block_encrypt() and 217 * qcrypto_block_decrypt() functions. 218 */ 219 typedef int (*Qcow2EncDecFunc)(QCryptoBlock *block, uint64_t offset, 220 uint8_t *buf, size_t len, Error **errp); 221 222 typedef struct Qcow2EncDecData { 223 QCryptoBlock *block; 224 uint64_t offset; 225 uint8_t *buf; 226 size_t len; 227 228 Qcow2EncDecFunc func; 229 } Qcow2EncDecData; 230 231 static int qcow2_encdec_pool_func(void *opaque) 232 { 233 Qcow2EncDecData *data = opaque; 234 235 return data->func(data->block, data->offset, data->buf, data->len, NULL); 236 } 237 238 static int coroutine_fn 239 qcow2_co_encdec(BlockDriverState *bs, uint64_t host_offset, 240 uint64_t guest_offset, void *buf, size_t len, 241 Qcow2EncDecFunc func) 242 { 243 BDRVQcow2State *s = bs->opaque; 244 Qcow2EncDecData arg = { 245 .block = s->crypto, 246 .offset = s->crypt_physical_offset ? host_offset : guest_offset, 247 .buf = buf, 248 .len = len, 249 .func = func, 250 }; 251 uint64_t sector_size; 252 253 assert(s->crypto); 254 255 sector_size = qcrypto_block_get_sector_size(s->crypto); 256 assert(QEMU_IS_ALIGNED(guest_offset, sector_size)); 257 assert(QEMU_IS_ALIGNED(host_offset, sector_size)); 258 assert(QEMU_IS_ALIGNED(len, sector_size)); 259 260 return len == 0 ? 0 : qcow2_co_process(bs, qcow2_encdec_pool_func, &arg); 261 } 262 263 /* 264 * qcow2_co_encrypt() 265 * 266 * Encrypts one or more contiguous aligned sectors 267 * 268 * @host_offset - underlying storage offset of the first sector of the 269 * data to be encrypted 270 * 271 * @guest_offset - guest (virtual) offset of the first sector of the 272 * data to be encrypted 273 * 274 * @buf - buffer with the data to encrypt, that after encryption 275 * will be written to the underlying storage device at 276 * @host_offset 277 * 278 * @len - length of the buffer (must be a multiple of the encryption 279 * sector size) 280 * 281 * Depending on the encryption method, @host_offset and/or @guest_offset 282 * may be used for generating the initialization vector for 283 * encryption. 284 * 285 * Note that while the whole range must be aligned on sectors, it 286 * does not have to be aligned on clusters and can also cross cluster 287 * boundaries 288 */ 289 int coroutine_fn 290 qcow2_co_encrypt(BlockDriverState *bs, uint64_t host_offset, 291 uint64_t guest_offset, void *buf, size_t len) 292 { 293 return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len, 294 qcrypto_block_encrypt); 295 } 296 297 /* 298 * qcow2_co_decrypt() 299 * 300 * Decrypts one or more contiguous aligned sectors 301 * Similar to qcow2_co_encrypt 302 */ 303 int coroutine_fn 304 qcow2_co_decrypt(BlockDriverState *bs, uint64_t host_offset, 305 uint64_t guest_offset, void *buf, size_t len) 306 { 307 return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len, 308 qcrypto_block_decrypt); 309 } 310