Block patches for the block queue.

-----BEGIN PGP SIGNATURE-----
 
 iQEvBAABCAAZBQJX95G1EhxtcmVpdHpAcmVkaGF0LmNvbQAKCRD0B9sAYdXPQDoY
 CACdQACIgSJ6atD5f6/txGX6IAIvCK/HIqNI8WsnxosmGaV0Zrgtz5kAp8Tk5LFq
 z/T2JaY9n7O3tQfy+laxpAZHFTYEOOCewF0nBeDxePMSB5wgVodIOkUIHZSwI6WE
 2BuampGwjnAH/QtcsaXDkQ8282/vQIgipN1MYpVijYcMWfv/auhiluR6CjGcMM46
 YotaOHkMKWbDnljVT3C5n/HS9xubGh+IQtX9zvQsmTwivDeOlUxI6ZA/b7jDcjB9
 F6rs9EsHLJEF82CVnnX03BL/wPu8Oa/NdzFqCsByx7egH316ay3ALNYrVyI4kS3F
 7zY/DCCpYj1RnpfamEXlNITH
 =9sm9
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'mreitz/tags/pull-block-2016-10-07' into queue-block

Block patches for the block queue.

# gpg: Signature made Fri Oct  7 14:14:45 2016 CEST
# gpg:                using RSA key 0xF407DB0061D5CF40
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>"
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1  1829 F407 DB00 61D5 CF40

* mreitz/tags/pull-block-2016-10-07:
  dmg: Move libbz2 code to dmg-bz2.so
  module: Don't load the same module if requested multiple times
  scripts: Allow block module to not define BlockDriver

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Kevin Wolf 2016-10-07 14:17:11 +02:00
commit 9c7f3fcae7
6 changed files with 155 additions and 62 deletions

View File

@ -41,6 +41,7 @@ gluster.o-libs := $(GLUSTERFS_LIBS)
ssh.o-cflags := $(LIBSSH2_CFLAGS) ssh.o-cflags := $(LIBSSH2_CFLAGS)
ssh.o-libs := $(LIBSSH2_LIBS) ssh.o-libs := $(LIBSSH2_LIBS)
archipelago.o-libs := $(ARCHIPELAGO_LIBS) archipelago.o-libs := $(ARCHIPELAGO_LIBS)
dmg.o-libs := $(BZIP2_LIBS) block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o
dmg-bz2.o-libs := $(BZIP2_LIBS)
qcow.o-libs := -lz qcow.o-libs := -lz
linux-aio.o-libs := -laio linux-aio.o-libs := -laio

61
block/dmg-bz2.c Normal file
View File

@ -0,0 +1,61 @@
/*
* DMG bzip2 uncompression
*
* Copyright (c) 2004 Johannes E. Schindelin
* Copyright (c) 2016 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "dmg.h"
#include <bzlib.h>
static int dmg_uncompress_bz2_do(char *next_in, unsigned int avail_in,
char *next_out, unsigned int avail_out)
{
int ret;
uint64_t total_out;
bz_stream bzstream = {};
ret = BZ2_bzDecompressInit(&bzstream, 0, 0);
if (ret != BZ_OK) {
return -1;
}
bzstream.next_in = next_in;
bzstream.avail_in = avail_in;
bzstream.next_out = next_out;
bzstream.avail_out = avail_out;
ret = BZ2_bzDecompress(&bzstream);
total_out = ((uint64_t)bzstream.total_out_hi32 << 32) +
bzstream.total_out_lo32;
BZ2_bzDecompressEnd(&bzstream);
if (ret != BZ_STREAM_END ||
total_out != avail_out) {
return -1;
}
return 0;
}
__attribute__((constructor))
static void dmg_bz2_init(void)
{
assert(!dmg_uncompress_bz2);
dmg_uncompress_bz2 = dmg_uncompress_bz2_do;
}

View File

@ -28,10 +28,10 @@
#include "qemu/bswap.h" #include "qemu/bswap.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/module.h" #include "qemu/module.h"
#include <zlib.h> #include "dmg.h"
#ifdef CONFIG_BZIP2
#include <bzlib.h> int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in,
#endif char *next_out, unsigned int avail_out);
enum { enum {
/* Limit chunk sizes to prevent unreasonable amounts of memory being used /* Limit chunk sizes to prevent unreasonable amounts of memory being used
@ -41,31 +41,6 @@ enum {
DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512, DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512,
}; };
typedef struct BDRVDMGState {
CoMutex lock;
/* each chunk contains a certain number of sectors,
* offsets[i] is the offset in the .dmg file,
* lengths[i] is the length of the compressed chunk,
* sectors[i] is the sector beginning at offsets[i],
* sectorcounts[i] is the number of sectors in that chunk,
* the sectors array is ordered
* 0<=i<n_chunks */
uint32_t n_chunks;
uint32_t* types;
uint64_t* offsets;
uint64_t* lengths;
uint64_t* sectors;
uint64_t* sectorcounts;
uint32_t current_chunk;
uint8_t *compressed_chunk;
uint8_t *uncompressed_chunk;
z_stream zstream;
#ifdef CONFIG_BZIP2
bz_stream bzstream;
#endif
} BDRVDMGState;
static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename) static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
{ {
int len; int len;
@ -210,10 +185,9 @@ static bool dmg_is_known_block_type(uint32_t entry_type)
case 0x00000001: /* uncompressed */ case 0x00000001: /* uncompressed */
case 0x00000002: /* zeroes */ case 0x00000002: /* zeroes */
case 0x80000005: /* zlib */ case 0x80000005: /* zlib */
#ifdef CONFIG_BZIP2
case 0x80000006: /* bzip2 */
#endif
return true; return true;
case 0x80000006: /* bzip2 */
return !!dmg_uncompress_bz2;
default: default:
return false; return false;
} }
@ -439,6 +413,7 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
int64_t offset; int64_t offset;
int ret; int ret;
block_module_load_one("dmg-bz2");
bs->read_only = true; bs->read_only = true;
s->n_chunks = 0; s->n_chunks = 0;
@ -587,9 +562,6 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
if (!is_sector_in_chunk(s, s->current_chunk, sector_num)) { if (!is_sector_in_chunk(s, s->current_chunk, sector_num)) {
int ret; int ret;
uint32_t chunk = search_chunk(s, sector_num); uint32_t chunk = search_chunk(s, sector_num);
#ifdef CONFIG_BZIP2
uint64_t total_out;
#endif
if (chunk >= s->n_chunks) { if (chunk >= s->n_chunks) {
return -1; return -1;
@ -620,8 +592,10 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
return -1; return -1;
} }
break; } break; }
#ifdef CONFIG_BZIP2
case 0x80000006: /* bzip2 compressed */ case 0x80000006: /* bzip2 compressed */
if (!dmg_uncompress_bz2) {
break;
}
/* we need to buffer, because only the chunk as whole can be /* we need to buffer, because only the chunk as whole can be
* inflated. */ * inflated. */
ret = bdrv_pread(bs->file, s->offsets[chunk], ret = bdrv_pread(bs->file, s->offsets[chunk],
@ -630,24 +604,15 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
return -1; return -1;
} }
ret = BZ2_bzDecompressInit(&s->bzstream, 0, 0); ret = dmg_uncompress_bz2((char *)s->compressed_chunk,
if (ret != BZ_OK) { (unsigned int) s->lengths[chunk],
return -1; (char *)s->uncompressed_chunk,
} (unsigned int)
s->bzstream.next_in = (char *)s->compressed_chunk; (512 * s->sectorcounts[chunk]));
s->bzstream.avail_in = (unsigned int) s->lengths[chunk]; if (ret < 0) {
s->bzstream.next_out = (char *)s->uncompressed_chunk; return ret;
s->bzstream.avail_out = (unsigned int) 512 * s->sectorcounts[chunk];
ret = BZ2_bzDecompress(&s->bzstream);
total_out = ((uint64_t)s->bzstream.total_out_hi32 << 32) +
s->bzstream.total_out_lo32;
BZ2_bzDecompressEnd(&s->bzstream);
if (ret != BZ_STREAM_END ||
total_out != 512 * s->sectorcounts[chunk]) {
return -1;
} }
break; break;
#endif /* CONFIG_BZIP2 */
case 1: /* copy */ case 1: /* copy */
ret = bdrv_pread(bs->file, s->offsets[chunk], ret = bdrv_pread(bs->file, s->offsets[chunk],
s->uncompressed_chunk, s->lengths[chunk]); s->uncompressed_chunk, s->lengths[chunk]);

59
block/dmg.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Header for DMG driver
*
* Copyright (c) 2004-2006 Fabrice Bellard
* Copyright (c) 2016 Red hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef BLOCK_DMG_H
#define BLOCK_DMG_H
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "block/block_int.h"
#include <zlib.h>
typedef struct BDRVDMGState {
CoMutex lock;
/* each chunk contains a certain number of sectors,
* offsets[i] is the offset in the .dmg file,
* lengths[i] is the length of the compressed chunk,
* sectors[i] is the sector beginning at offsets[i],
* sectorcounts[i] is the number of sectors in that chunk,
* the sectors array is ordered
* 0<=i<n_chunks */
uint32_t n_chunks;
uint32_t *types;
uint64_t *offsets;
uint64_t *lengths;
uint64_t *sectors;
uint64_t *sectorcounts;
uint32_t current_chunk;
uint8_t *compressed_chunk;
uint8_t *uncompressed_chunk;
z_stream zstream;
} BDRVDMGState;
extern int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in,
char *next_out, unsigned int avail_out);
#endif

View File

@ -37,7 +37,6 @@ def add_module(fheader, library, format_name, protocol_name):
def process_file(fheader, filename): def process_file(fheader, filename):
# This parser assumes the coding style rules are being followed # This parser assumes the coding style rules are being followed
with open(filename, "r") as cfile: with open(filename, "r") as cfile:
found_something = False
found_start = False found_start = False
library, _ = os.path.splitext(os.path.basename(filename)) library, _ = os.path.splitext(os.path.basename(filename))
for line in cfile: for line in cfile:
@ -51,16 +50,10 @@ def process_file(fheader, filename):
add_module(fheader, library, format_name, protocol_name) add_module(fheader, library, format_name, protocol_name)
found_start = False found_start = False
elif line.find("static BlockDriver") != -1: elif line.find("static BlockDriver") != -1:
found_something = True
found_start = True found_start = True
format_name = "" format_name = ""
protocol_name = "" protocol_name = ""
if not found_something:
print("No BlockDriver struct found in " + filename + ". \
Is this really a module?", file=sys.stderr)
sys.exit(1)
def print_top(fheader): def print_top(fheader):
fheader.write('''/* AUTOMATICALLY GENERATED, DO NOT MODIFY */ fheader.write('''/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
/* /*

View File

@ -163,14 +163,28 @@ void module_load_one(const char *prefix, const char *lib_name)
char *fname = NULL; char *fname = NULL;
char *exec_dir; char *exec_dir;
char *dirs[3]; char *dirs[3];
char *module_name;
int i = 0; int i = 0;
int ret; int ret;
static GHashTable *loaded_modules;
if (!g_module_supported()) { if (!g_module_supported()) {
fprintf(stderr, "Module is not supported by system.\n"); fprintf(stderr, "Module is not supported by system.\n");
return; return;
} }
if (!loaded_modules) {
loaded_modules = g_hash_table_new(g_str_hash, g_str_equal);
}
module_name = g_strdup_printf("%s%s", prefix, lib_name);
if (g_hash_table_lookup(loaded_modules, module_name)) {
g_free(module_name);
return;
}
g_hash_table_insert(loaded_modules, module_name, module_name);
exec_dir = qemu_get_exec_dir(); exec_dir = qemu_get_exec_dir();
dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR); dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR);
dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : ""); dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : "");
@ -180,8 +194,8 @@ void module_load_one(const char *prefix, const char *lib_name)
exec_dir = NULL; exec_dir = NULL;
for (i = 0; i < ARRAY_SIZE(dirs); i++) { for (i = 0; i < ARRAY_SIZE(dirs); i++) {
fname = g_strdup_printf("%s/%s%s%s", fname = g_strdup_printf("%s/%s%s",
dirs[i], prefix, lib_name, HOST_DSOSUF); dirs[i], module_name, HOST_DSOSUF);
ret = module_load_file(fname); ret = module_load_file(fname);
g_free(fname); g_free(fname);
fname = NULL; fname = NULL;