qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

dmg: Move libbz2 code to dmg-bz2.so

dmg.o was moved to block-obj-m in 5505e8b76 to become a separate module,
so that its reference to libbz2, since 6b383c08c, doesn't add an extra
library to the main executable.

Until recently, commit 06e60f70a (blockdev: Add dynamic module loading
for block drivers) moved it back to block-obj-y to simplify the design
of dynamic loading of block modules. But we don't want to lose the
feature of less library dependency on the main executable.

The solution here is to move only the bz2 related code to a separate
DSO file, and load it when dmg_open is called.

dmg_probe doesn't depend on bz2 support to work, and is the only code in
this file which can run before dmg_open.

While we are at it, fix the unhelpful cast of last argument passed to
dmg_uncompress_bz2.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-id: 1473043845-13197-4-git-send-email-famz@redhat.com
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>

authored by

Fam Zheng and committed by
Max Reitz
27685a8d dffa41b4

+139 -53
+2 -1
block/Makefile.objs
··· 41 41 ssh.o-cflags := $(LIBSSH2_CFLAGS) 42 42 ssh.o-libs := $(LIBSSH2_LIBS) 43 43 archipelago.o-libs := $(ARCHIPELAGO_LIBS) 44 - dmg.o-libs := $(BZIP2_LIBS) 44 + block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o 45 + dmg-bz2.o-libs := $(BZIP2_LIBS) 45 46 qcow.o-libs := -lz 46 47 linux-aio.o-libs := -laio
+61
block/dmg-bz2.c
··· 1 + /* 2 + * DMG bzip2 uncompression 3 + * 4 + * Copyright (c) 2004 Johannes E. Schindelin 5 + * Copyright (c) 2016 Red Hat, Inc. 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 + #include "qemu/osdep.h" 26 + #include "qemu-common.h" 27 + #include "dmg.h" 28 + #include <bzlib.h> 29 + 30 + static int dmg_uncompress_bz2_do(char *next_in, unsigned int avail_in, 31 + char *next_out, unsigned int avail_out) 32 + { 33 + int ret; 34 + uint64_t total_out; 35 + bz_stream bzstream = {}; 36 + 37 + ret = BZ2_bzDecompressInit(&bzstream, 0, 0); 38 + if (ret != BZ_OK) { 39 + return -1; 40 + } 41 + bzstream.next_in = next_in; 42 + bzstream.avail_in = avail_in; 43 + bzstream.next_out = next_out; 44 + bzstream.avail_out = avail_out; 45 + ret = BZ2_bzDecompress(&bzstream); 46 + total_out = ((uint64_t)bzstream.total_out_hi32 << 32) + 47 + bzstream.total_out_lo32; 48 + BZ2_bzDecompressEnd(&bzstream); 49 + if (ret != BZ_STREAM_END || 50 + total_out != avail_out) { 51 + return -1; 52 + } 53 + return 0; 54 + } 55 + 56 + __attribute__((constructor)) 57 + static void dmg_bz2_init(void) 58 + { 59 + assert(!dmg_uncompress_bz2); 60 + dmg_uncompress_bz2 = dmg_uncompress_bz2_do; 61 + }
+17 -52
block/dmg.c
··· 28 28 #include "qemu/bswap.h" 29 29 #include "qemu/error-report.h" 30 30 #include "qemu/module.h" 31 - #include <zlib.h> 32 - #ifdef CONFIG_BZIP2 33 - #include <bzlib.h> 34 - #endif 31 + #include "dmg.h" 32 + 33 + int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in, 34 + char *next_out, unsigned int avail_out); 35 35 36 36 enum { 37 37 /* Limit chunk sizes to prevent unreasonable amounts of memory being used ··· 40 40 DMG_LENGTHS_MAX = 64 * 1024 * 1024, /* 64 MB */ 41 41 DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512, 42 42 }; 43 - 44 - typedef struct BDRVDMGState { 45 - CoMutex lock; 46 - /* each chunk contains a certain number of sectors, 47 - * offsets[i] is the offset in the .dmg file, 48 - * lengths[i] is the length of the compressed chunk, 49 - * sectors[i] is the sector beginning at offsets[i], 50 - * sectorcounts[i] is the number of sectors in that chunk, 51 - * the sectors array is ordered 52 - * 0<=i<n_chunks */ 53 - 54 - uint32_t n_chunks; 55 - uint32_t* types; 56 - uint64_t* offsets; 57 - uint64_t* lengths; 58 - uint64_t* sectors; 59 - uint64_t* sectorcounts; 60 - uint32_t current_chunk; 61 - uint8_t *compressed_chunk; 62 - uint8_t *uncompressed_chunk; 63 - z_stream zstream; 64 - #ifdef CONFIG_BZIP2 65 - bz_stream bzstream; 66 - #endif 67 - } BDRVDMGState; 68 43 69 44 static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename) 70 45 { ··· 210 185 case 0x00000001: /* uncompressed */ 211 186 case 0x00000002: /* zeroes */ 212 187 case 0x80000005: /* zlib */ 213 - #ifdef CONFIG_BZIP2 188 + return true; 214 189 case 0x80000006: /* bzip2 */ 215 - #endif 216 - return true; 190 + return !!dmg_uncompress_bz2; 217 191 default: 218 192 return false; 219 193 } ··· 439 413 int64_t offset; 440 414 int ret; 441 415 416 + block_module_load_one("dmg-bz2"); 442 417 bs->read_only = true; 443 418 444 419 s->n_chunks = 0; ··· 587 562 if (!is_sector_in_chunk(s, s->current_chunk, sector_num)) { 588 563 int ret; 589 564 uint32_t chunk = search_chunk(s, sector_num); 590 - #ifdef CONFIG_BZIP2 591 - uint64_t total_out; 592 - #endif 593 565 594 566 if (chunk >= s->n_chunks) { 595 567 return -1; ··· 620 592 return -1; 621 593 } 622 594 break; } 623 - #ifdef CONFIG_BZIP2 624 595 case 0x80000006: /* bzip2 compressed */ 596 + if (!dmg_uncompress_bz2) { 597 + break; 598 + } 625 599 /* we need to buffer, because only the chunk as whole can be 626 600 * inflated. */ 627 601 ret = bdrv_pread(bs->file, s->offsets[chunk], ··· 630 604 return -1; 631 605 } 632 606 633 - ret = BZ2_bzDecompressInit(&s->bzstream, 0, 0); 634 - if (ret != BZ_OK) { 635 - return -1; 636 - } 637 - s->bzstream.next_in = (char *)s->compressed_chunk; 638 - s->bzstream.avail_in = (unsigned int) s->lengths[chunk]; 639 - s->bzstream.next_out = (char *)s->uncompressed_chunk; 640 - s->bzstream.avail_out = (unsigned int) 512 * s->sectorcounts[chunk]; 641 - ret = BZ2_bzDecompress(&s->bzstream); 642 - total_out = ((uint64_t)s->bzstream.total_out_hi32 << 32) + 643 - s->bzstream.total_out_lo32; 644 - BZ2_bzDecompressEnd(&s->bzstream); 645 - if (ret != BZ_STREAM_END || 646 - total_out != 512 * s->sectorcounts[chunk]) { 647 - return -1; 607 + ret = dmg_uncompress_bz2((char *)s->compressed_chunk, 608 + (unsigned int) s->lengths[chunk], 609 + (char *)s->uncompressed_chunk, 610 + (unsigned int) 611 + (512 * s->sectorcounts[chunk])); 612 + if (ret < 0) { 613 + return ret; 648 614 } 649 615 break; 650 - #endif /* CONFIG_BZIP2 */ 651 616 case 1: /* copy */ 652 617 ret = bdrv_pread(bs->file, s->offsets[chunk], 653 618 s->uncompressed_chunk, s->lengths[chunk]);
+59
block/dmg.h
··· 1 + /* 2 + * Header for DMG driver 3 + * 4 + * Copyright (c) 2004-2006 Fabrice Bellard 5 + * Copyright (c) 2016 Red hat, Inc. 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 + #ifndef BLOCK_DMG_H 27 + #define BLOCK_DMG_H 28 + 29 + #include "qemu/osdep.h" 30 + #include "qemu-common.h" 31 + #include "block/block_int.h" 32 + #include <zlib.h> 33 + 34 + typedef struct BDRVDMGState { 35 + CoMutex lock; 36 + /* each chunk contains a certain number of sectors, 37 + * offsets[i] is the offset in the .dmg file, 38 + * lengths[i] is the length of the compressed chunk, 39 + * sectors[i] is the sector beginning at offsets[i], 40 + * sectorcounts[i] is the number of sectors in that chunk, 41 + * the sectors array is ordered 42 + * 0<=i<n_chunks */ 43 + 44 + uint32_t n_chunks; 45 + uint32_t *types; 46 + uint64_t *offsets; 47 + uint64_t *lengths; 48 + uint64_t *sectors; 49 + uint64_t *sectorcounts; 50 + uint32_t current_chunk; 51 + uint8_t *compressed_chunk; 52 + uint8_t *uncompressed_chunk; 53 + z_stream zstream; 54 + } BDRVDMGState; 55 + 56 + extern int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in, 57 + char *next_out, unsigned int avail_out); 58 + 59 + #endif