Block patches
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJT90oJAAoJEH8JsnLIjy/Wc5MP/igS9+mf96x2t6a3ayi6XPNN AiQDuZWhpRMWvxD7jWj0nUTvrRjMpsWDFXAU95SnhxznVVCqgfTsDr/fPLQt/aan S2yNTdSPmAmR1+e3WuK4uFPLwGcWSbemfpPPYd2e6+pEw8DN/zQ0+GXnXrPIKo3m SEmAGcwuvdKJCVhYxlJBS6lQtZwzV+JmtaR16ouCwdkctR/Y/SLyb7lOAqEcOBDP NY/ORgLtbz+qjOgvGIIT5nW68ALAFKx6tWaqnNm8QeEg2QLPJrtAkb9n1rSDl7F1 AiTFTSgNjbLkhkap5sTvKy1e/yeIDM5wynfeqscQDd81QFPmIfQITUeD+cL+fgh2 8EUWIgUpYCnzYCcO+DNL6ofEOGSF0hl8YULsGJv+KOLAqsTVTPQv6VNj5ltSKtGJ vlCkjRiAIqgQyXXSaJIn1pKLiLPJfrmaA4gJRccPnZycztc23/jumpfDNPipw4u9 9hulLXQ2HkpGuqkBxsWS4rxv57gFle2Pdi+kyz+jmR17EHHwfyZHvXi0Grwsn6v1 gDfGMCeLLzy0CNB4e+JaY3vLhw1p3P0yPH5ON875fSuorSnc6hxge7A28bBJCySU inCIDBalNXiQQlQGLV/48ZaF7kxbC6ywHs2ZBXwRU8377AnCIFOlGs0Obx/TWo8K Yq7RPwUipOOnrOoijIGn =tfGn -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging Block patches # gpg: Signature made Fri 22 Aug 2014 14:47:53 BST using RSA key ID C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" * remotes/kevin/tags/for-upstream: (29 commits) qemu-img: Allow cache mode specification for amend qemu-img: Allow source cache mode specification vmdk: Use bdrv_nb_sectors() where sectors, not bytes are wanted blkdebug: Delete BH in bdrv_aio_cancel qemu-iotests: add test case 101 for short file I/O raw-posix: fix O_DIRECT short reads block/iscsi: fix memory corruption on iscsi resize block/vvfat.c: remove debugging code to reinit stderr if NULL iotests: Add test for image filename construction quorum: Implement bdrv_refresh_filename() nbd: Implement bdrv_refresh_filename() blkverify: Implement bdrv_refresh_filename() blkdebug: Implement bdrv_refresh_filename() block: Add bdrv_refresh_filename() virtio-blk: fix reference a pointer which might be freed virtio-blk: allow block_resize with dataplane block: acquire AioContext in qmp_block_resize() qemu-iotests: Fix 028 reference output for qed test-coroutine: test cost introduced by coroutine iotests: Add test for qcow2's cache options ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
33886ebeec
@ -283,7 +283,7 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
|
||||
nr_sectors = total_sectors - cur_sector;
|
||||
}
|
||||
|
||||
blk = g_malloc(sizeof(BlkMigBlock));
|
||||
blk = g_new(BlkMigBlock, 1);
|
||||
blk->buf = g_malloc(BLOCK_SIZE);
|
||||
blk->bmds = bmds;
|
||||
blk->sector = cur_sector;
|
||||
@ -354,7 +354,7 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
|
||||
return;
|
||||
}
|
||||
|
||||
bmds = g_malloc0(sizeof(BlkMigDevState));
|
||||
bmds = g_new0(BlkMigDevState, 1);
|
||||
bmds->bs = bs;
|
||||
bmds->bulk_completed = 0;
|
||||
bmds->total_sectors = sectors;
|
||||
@ -465,7 +465,7 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
|
||||
} else {
|
||||
nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
|
||||
}
|
||||
blk = g_malloc(sizeof(BlkMigBlock));
|
||||
blk = g_new(BlkMigBlock, 1);
|
||||
blk->buf = g_malloc(BLOCK_SIZE);
|
||||
blk->bmds = bmds;
|
||||
blk->sector = sector;
|
||||
|
149
block.c
149
block.c
@ -351,7 +351,7 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bs = g_malloc0(sizeof(BlockDriverState));
|
||||
bs = g_new0(BlockDriverState, 1);
|
||||
QLIST_INIT(&bs->dirty_bitmaps);
|
||||
pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
|
||||
if (device_name[0] != '\0') {
|
||||
@ -964,6 +964,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
||||
} else {
|
||||
bs->filename[0] = '\0';
|
||||
}
|
||||
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), bs->filename);
|
||||
|
||||
bs->drv = drv;
|
||||
bs->opaque = g_malloc0(drv->instance_size);
|
||||
@ -1505,6 +1506,8 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
|
||||
}
|
||||
}
|
||||
|
||||
bdrv_refresh_filename(bs);
|
||||
|
||||
/* For snapshot=on, create a temporary qcow2 overlay. bs points to the
|
||||
* temporary snapshot afterwards. */
|
||||
if (snapshot_flags) {
|
||||
@ -1845,6 +1848,8 @@ void bdrv_close(BlockDriverState *bs)
|
||||
bs->zero_beyond_eof = false;
|
||||
QDECREF(bs->options);
|
||||
bs->options = NULL;
|
||||
QDECREF(bs->full_open_options);
|
||||
bs->full_open_options = NULL;
|
||||
|
||||
if (bs->file != NULL) {
|
||||
bdrv_unref(bs->file);
|
||||
@ -2628,7 +2633,7 @@ int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
|
||||
* into our deletion queue, until we hit the 'base'
|
||||
*/
|
||||
while (intermediate) {
|
||||
intermediate_state = g_malloc0(sizeof(BlkIntermediateStates));
|
||||
intermediate_state = g_new0(BlkIntermediateStates, 1);
|
||||
intermediate_state->bs = intermediate;
|
||||
QSIMPLEQ_INSERT_TAIL(&states_to_delete, intermediate_state, entry);
|
||||
|
||||
@ -3755,7 +3760,7 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
formats = g_realloc(formats, (count + 1) * sizeof(char *));
|
||||
formats = g_renew(const char *, formats, count + 1);
|
||||
formats[count++] = drv->format_name;
|
||||
it(opaque, drv->format_name);
|
||||
}
|
||||
@ -5330,7 +5335,7 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, int granularity,
|
||||
errno = -bitmap_size;
|
||||
return NULL;
|
||||
}
|
||||
bitmap = g_malloc0(sizeof(BdrvDirtyBitmap));
|
||||
bitmap = g_new0(BdrvDirtyBitmap, 1);
|
||||
bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(granularity) - 1);
|
||||
QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
|
||||
return bitmap;
|
||||
@ -5356,8 +5361,8 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
|
||||
BlockDirtyInfoList **plist = &list;
|
||||
|
||||
QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
|
||||
BlockDirtyInfo *info = g_malloc0(sizeof(BlockDirtyInfo));
|
||||
BlockDirtyInfoList *entry = g_malloc0(sizeof(BlockDirtyInfoList));
|
||||
BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
|
||||
BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1);
|
||||
info->count = bdrv_get_dirty_count(bs, bm);
|
||||
info->granularity =
|
||||
((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bm->bitmap));
|
||||
@ -5451,7 +5456,7 @@ void bdrv_op_block(BlockDriverState *bs, BlockOpType op, Error *reason)
|
||||
BdrvOpBlocker *blocker;
|
||||
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
|
||||
|
||||
blocker = g_malloc0(sizeof(BdrvOpBlocker));
|
||||
blocker = g_new0(BdrvOpBlocker, 1);
|
||||
blocker->reason = reason;
|
||||
QLIST_INSERT_HEAD(&bs->op_blockers[op], blocker, list);
|
||||
}
|
||||
@ -5894,3 +5899,133 @@ void bdrv_flush_io_queue(BlockDriverState *bs)
|
||||
bdrv_flush_io_queue(bs->file);
|
||||
}
|
||||
}
|
||||
|
||||
static bool append_open_options(QDict *d, BlockDriverState *bs)
|
||||
{
|
||||
const QDictEntry *entry;
|
||||
bool found_any = false;
|
||||
|
||||
for (entry = qdict_first(bs->options); entry;
|
||||
entry = qdict_next(bs->options, entry))
|
||||
{
|
||||
/* Only take options for this level and exclude all non-driver-specific
|
||||
* options */
|
||||
if (!strchr(qdict_entry_key(entry), '.') &&
|
||||
strcmp(qdict_entry_key(entry), "node-name"))
|
||||
{
|
||||
qobject_incref(qdict_entry_value(entry));
|
||||
qdict_put_obj(d, qdict_entry_key(entry), qdict_entry_value(entry));
|
||||
found_any = true;
|
||||
}
|
||||
}
|
||||
|
||||
return found_any;
|
||||
}
|
||||
|
||||
/* Updates the following BDS fields:
|
||||
* - exact_filename: A filename which may be used for opening a block device
|
||||
* which (mostly) equals the given BDS (even without any
|
||||
* other options; so reading and writing must return the same
|
||||
* results, but caching etc. may be different)
|
||||
* - full_open_options: Options which, when given when opening a block device
|
||||
* (without a filename), result in a BDS (mostly)
|
||||
* equalling the given one
|
||||
* - filename: If exact_filename is set, it is copied here. Otherwise,
|
||||
* full_open_options is converted to a JSON object, prefixed with
|
||||
* "json:" (for use through the JSON pseudo protocol) and put here.
|
||||
*/
|
||||
void bdrv_refresh_filename(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
QDict *opts;
|
||||
|
||||
if (!drv) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* This BDS's file name will most probably depend on its file's name, so
|
||||
* refresh that first */
|
||||
if (bs->file) {
|
||||
bdrv_refresh_filename(bs->file);
|
||||
}
|
||||
|
||||
if (drv->bdrv_refresh_filename) {
|
||||
/* Obsolete information is of no use here, so drop the old file name
|
||||
* information before refreshing it */
|
||||
bs->exact_filename[0] = '\0';
|
||||
if (bs->full_open_options) {
|
||||
QDECREF(bs->full_open_options);
|
||||
bs->full_open_options = NULL;
|
||||
}
|
||||
|
||||
drv->bdrv_refresh_filename(bs);
|
||||
} else if (bs->file) {
|
||||
/* Try to reconstruct valid information from the underlying file */
|
||||
bool has_open_options;
|
||||
|
||||
bs->exact_filename[0] = '\0';
|
||||
if (bs->full_open_options) {
|
||||
QDECREF(bs->full_open_options);
|
||||
bs->full_open_options = NULL;
|
||||
}
|
||||
|
||||
opts = qdict_new();
|
||||
has_open_options = append_open_options(opts, bs);
|
||||
|
||||
/* If no specific options have been given for this BDS, the filename of
|
||||
* the underlying file should suffice for this one as well */
|
||||
if (bs->file->exact_filename[0] && !has_open_options) {
|
||||
strcpy(bs->exact_filename, bs->file->exact_filename);
|
||||
}
|
||||
/* Reconstructing the full options QDict is simple for most format block
|
||||
* drivers, as long as the full options are known for the underlying
|
||||
* file BDS. The full options QDict of that file BDS should somehow
|
||||
* contain a representation of the filename, therefore the following
|
||||
* suffices without querying the (exact_)filename of this BDS. */
|
||||
if (bs->file->full_open_options) {
|
||||
qdict_put_obj(opts, "driver",
|
||||
QOBJECT(qstring_from_str(drv->format_name)));
|
||||
QINCREF(bs->file->full_open_options);
|
||||
qdict_put_obj(opts, "file", QOBJECT(bs->file->full_open_options));
|
||||
|
||||
bs->full_open_options = opts;
|
||||
} else {
|
||||
QDECREF(opts);
|
||||
}
|
||||
} else if (!bs->full_open_options && qdict_size(bs->options)) {
|
||||
/* There is no underlying file BDS (at least referenced by BDS.file),
|
||||
* so the full options QDict should be equal to the options given
|
||||
* specifically for this block device when it was opened (plus the
|
||||
* driver specification).
|
||||
* Because those options don't change, there is no need to update
|
||||
* full_open_options when it's already set. */
|
||||
|
||||
opts = qdict_new();
|
||||
append_open_options(opts, bs);
|
||||
qdict_put_obj(opts, "driver",
|
||||
QOBJECT(qstring_from_str(drv->format_name)));
|
||||
|
||||
if (bs->exact_filename[0]) {
|
||||
/* This may not work for all block protocol drivers (some may
|
||||
* require this filename to be parsed), but we have to find some
|
||||
* default solution here, so just include it. If some block driver
|
||||
* does not support pure options without any filename at all or
|
||||
* needs some special format of the options QDict, it needs to
|
||||
* implement the driver-specific bdrv_refresh_filename() function.
|
||||
*/
|
||||
qdict_put_obj(opts, "filename",
|
||||
QOBJECT(qstring_from_str(bs->exact_filename)));
|
||||
}
|
||||
|
||||
bs->full_open_options = opts;
|
||||
}
|
||||
|
||||
if (bs->exact_filename[0]) {
|
||||
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
|
||||
} else if (bs->full_open_options) {
|
||||
QString *json = qobject_to_json(QOBJECT(bs->full_open_options));
|
||||
snprintf(bs->filename, sizeof(bs->filename), "json:%s",
|
||||
qstring_get_str(json));
|
||||
QDECREF(json);
|
||||
}
|
||||
}
|
||||
|
@ -750,7 +750,7 @@ static int archipelago_submit_request(BDRVArchipelagoState *s,
|
||||
char *target;
|
||||
void *data = NULL;
|
||||
struct xseg_request *req;
|
||||
AIORequestData *reqdata = g_malloc(sizeof(AIORequestData));
|
||||
AIORequestData *reqdata = g_new(AIORequestData, 1);
|
||||
|
||||
targetlen = strlen(s->volname);
|
||||
req = xseg_get_request(s->xseg, s->srcport, s->vportno, X_ALLOC);
|
||||
@ -827,7 +827,7 @@ static int archipelago_aio_segmented_rw(BDRVArchipelagoState *s,
|
||||
int i, ret, segments_nr, last_segment_size;
|
||||
ArchipelagoSegmentedRequest *segreq;
|
||||
|
||||
segreq = g_malloc(sizeof(ArchipelagoSegmentedRequest));
|
||||
segreq = g_new(ArchipelagoSegmentedRequest, 1);
|
||||
|
||||
if (op == ARCHIP_OP_FLUSH) {
|
||||
segments_nr = 1;
|
||||
@ -960,7 +960,7 @@ static int64_t archipelago_volume_info(BDRVArchipelagoState *s)
|
||||
int ret, targetlen;
|
||||
struct xseg_request *req;
|
||||
struct xseg_reply_info *xinfo;
|
||||
AIORequestData *reqdata = g_malloc(sizeof(AIORequestData));
|
||||
AIORequestData *reqdata = g_new(AIORequestData, 1);
|
||||
|
||||
const char *volname = s->volname;
|
||||
targetlen = strlen(volname);
|
||||
|
101
block/blkdebug.c
101
block/blkdebug.c
@ -26,6 +26,10 @@
|
||||
#include "qemu/config-file.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
typedef struct BDRVBlkdebugState {
|
||||
int state;
|
||||
@ -449,6 +453,10 @@ static void error_callback_bh(void *opaque)
|
||||
static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
{
|
||||
BlkdebugAIOCB *acb = container_of(blockacb, BlkdebugAIOCB, common);
|
||||
if (acb->bh) {
|
||||
qemu_bh_delete(acb->bh);
|
||||
acb->bh = NULL;
|
||||
}
|
||||
qemu_aio_release(acb);
|
||||
}
|
||||
|
||||
@ -706,6 +714,98 @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
|
||||
return bdrv_getlength(bs->file);
|
||||
}
|
||||
|
||||
static void blkdebug_refresh_filename(BlockDriverState *bs)
|
||||
{
|
||||
BDRVBlkdebugState *s = bs->opaque;
|
||||
struct BlkdebugRule *rule;
|
||||
QDict *opts;
|
||||
QList *inject_error_list = NULL, *set_state_list = NULL;
|
||||
QList *suspend_list = NULL;
|
||||
int event;
|
||||
|
||||
if (!bs->file->full_open_options) {
|
||||
/* The config file cannot be recreated, so creating a plain filename
|
||||
* is impossible */
|
||||
return;
|
||||
}
|
||||
|
||||
opts = qdict_new();
|
||||
qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("blkdebug")));
|
||||
|
||||
QINCREF(bs->file->full_open_options);
|
||||
qdict_put_obj(opts, "image", QOBJECT(bs->file->full_open_options));
|
||||
|
||||
for (event = 0; event < BLKDBG_EVENT_MAX; event++) {
|
||||
QLIST_FOREACH(rule, &s->rules[event], next) {
|
||||
if (rule->action == ACTION_INJECT_ERROR) {
|
||||
QDict *inject_error = qdict_new();
|
||||
|
||||
qdict_put_obj(inject_error, "event", QOBJECT(qstring_from_str(
|
||||
BlkdebugEvent_lookup[rule->event])));
|
||||
qdict_put_obj(inject_error, "state",
|
||||
QOBJECT(qint_from_int(rule->state)));
|
||||
qdict_put_obj(inject_error, "errno", QOBJECT(qint_from_int(
|
||||
rule->options.inject.error)));
|
||||
qdict_put_obj(inject_error, "sector", QOBJECT(qint_from_int(
|
||||
rule->options.inject.sector)));
|
||||
qdict_put_obj(inject_error, "once", QOBJECT(qbool_from_int(
|
||||
rule->options.inject.once)));
|
||||
qdict_put_obj(inject_error, "immediately",
|
||||
QOBJECT(qbool_from_int(
|
||||
rule->options.inject.immediately)));
|
||||
|
||||
if (!inject_error_list) {
|
||||
inject_error_list = qlist_new();
|
||||
}
|
||||
|
||||
qlist_append_obj(inject_error_list, QOBJECT(inject_error));
|
||||
} else if (rule->action == ACTION_SET_STATE) {
|
||||
QDict *set_state = qdict_new();
|
||||
|
||||
qdict_put_obj(set_state, "event", QOBJECT(qstring_from_str(
|
||||
BlkdebugEvent_lookup[rule->event])));
|
||||
qdict_put_obj(set_state, "state",
|
||||
QOBJECT(qint_from_int(rule->state)));
|
||||
qdict_put_obj(set_state, "new_state", QOBJECT(qint_from_int(
|
||||
rule->options.set_state.new_state)));
|
||||
|
||||
if (!set_state_list) {
|
||||
set_state_list = qlist_new();
|
||||
}
|
||||
|
||||
qlist_append_obj(set_state_list, QOBJECT(set_state));
|
||||
} else if (rule->action == ACTION_SUSPEND) {
|
||||
QDict *suspend = qdict_new();
|
||||
|
||||
qdict_put_obj(suspend, "event", QOBJECT(qstring_from_str(
|
||||
BlkdebugEvent_lookup[rule->event])));
|
||||
qdict_put_obj(suspend, "state",
|
||||
QOBJECT(qint_from_int(rule->state)));
|
||||
qdict_put_obj(suspend, "tag", QOBJECT(qstring_from_str(
|
||||
rule->options.suspend.tag)));
|
||||
|
||||
if (!suspend_list) {
|
||||
suspend_list = qlist_new();
|
||||
}
|
||||
|
||||
qlist_append_obj(suspend_list, QOBJECT(suspend));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inject_error_list) {
|
||||
qdict_put_obj(opts, "inject-error", QOBJECT(inject_error_list));
|
||||
}
|
||||
if (set_state_list) {
|
||||
qdict_put_obj(opts, "set-state", QOBJECT(set_state_list));
|
||||
}
|
||||
if (suspend_list) {
|
||||
qdict_put_obj(opts, "suspend", QOBJECT(suspend_list));
|
||||
}
|
||||
|
||||
bs->full_open_options = opts;
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_blkdebug = {
|
||||
.format_name = "blkdebug",
|
||||
.protocol_name = "blkdebug",
|
||||
@ -715,6 +815,7 @@ static BlockDriver bdrv_blkdebug = {
|
||||
.bdrv_file_open = blkdebug_open,
|
||||
.bdrv_close = blkdebug_close,
|
||||
.bdrv_getlength = blkdebug_getlength,
|
||||
.bdrv_refresh_filename = blkdebug_refresh_filename,
|
||||
|
||||
.bdrv_aio_readv = blkdebug_aio_readv,
|
||||
.bdrv_aio_writev = blkdebug_aio_writev,
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <stdarg.h>
|
||||
#include "qemu/sockets.h" /* for EINPROGRESS on Windows */
|
||||
#include "block/block_int.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
typedef struct {
|
||||
BlockDriverState *test_file;
|
||||
@ -320,6 +322,32 @@ static void blkverify_attach_aio_context(BlockDriverState *bs,
|
||||
bdrv_attach_aio_context(s->test_file, new_context);
|
||||
}
|
||||
|
||||
static void blkverify_refresh_filename(BlockDriverState *bs)
|
||||
{
|
||||
BDRVBlkverifyState *s = bs->opaque;
|
||||
|
||||
/* bs->file has already been refreshed */
|
||||
bdrv_refresh_filename(s->test_file);
|
||||
|
||||
if (bs->file->full_open_options && s->test_file->full_open_options) {
|
||||
QDict *opts = qdict_new();
|
||||
qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("blkverify")));
|
||||
|
||||
QINCREF(bs->file->full_open_options);
|
||||
qdict_put_obj(opts, "raw", QOBJECT(bs->file->full_open_options));
|
||||
QINCREF(s->test_file->full_open_options);
|
||||
qdict_put_obj(opts, "test", QOBJECT(s->test_file->full_open_options));
|
||||
|
||||
bs->full_open_options = opts;
|
||||
}
|
||||
|
||||
if (bs->file->exact_filename[0] && s->test_file->exact_filename[0]) {
|
||||
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
||||
"blkverify:%s:%s",
|
||||
bs->file->exact_filename, s->test_file->exact_filename);
|
||||
}
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_blkverify = {
|
||||
.format_name = "blkverify",
|
||||
.protocol_name = "blkverify",
|
||||
@ -329,6 +357,7 @@ static BlockDriver bdrv_blkverify = {
|
||||
.bdrv_file_open = blkverify_open,
|
||||
.bdrv_close = blkverify_close,
|
||||
.bdrv_getlength = blkverify_getlength,
|
||||
.bdrv_refresh_filename = blkverify_refresh_filename,
|
||||
|
||||
.bdrv_aio_readv = blkverify_aio_readv,
|
||||
.bdrv_aio_writev = blkverify_aio_writev,
|
||||
|
@ -131,7 +131,7 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
s->catalog_bitmap = g_try_malloc(s->catalog_size * 4);
|
||||
s->catalog_bitmap = g_try_new(uint32_t, s->catalog_size);
|
||||
if (s->catalog_size && s->catalog_bitmap == NULL) {
|
||||
error_setg(errp, "Could not allocate memory for catalog");
|
||||
return -ENOMEM;
|
||||
|
@ -291,7 +291,7 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
|
||||
BDRVGlusterState *s = bs->opaque;
|
||||
int open_flags = 0;
|
||||
int ret = 0;
|
||||
GlusterConf *gconf = g_malloc0(sizeof(GlusterConf));
|
||||
GlusterConf *gconf = g_new0(GlusterConf, 1);
|
||||
QemuOpts *opts;
|
||||
Error *local_err = NULL;
|
||||
const char *filename;
|
||||
@ -351,12 +351,12 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
|
||||
assert(state != NULL);
|
||||
assert(state->bs != NULL);
|
||||
|
||||
state->opaque = g_malloc0(sizeof(BDRVGlusterReopenState));
|
||||
state->opaque = g_new0(BDRVGlusterReopenState, 1);
|
||||
reop_s = state->opaque;
|
||||
|
||||
qemu_gluster_parse_flags(state->flags, &open_flags);
|
||||
|
||||
gconf = g_malloc0(sizeof(GlusterConf));
|
||||
gconf = g_new0(GlusterConf, 1);
|
||||
|
||||
reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, errp);
|
||||
if (reop_s->glfs == NULL) {
|
||||
@ -486,7 +486,7 @@ static int qemu_gluster_create(const char *filename,
|
||||
int prealloc = 0;
|
||||
int64_t total_size = 0;
|
||||
char *tmp = NULL;
|
||||
GlusterConf *gconf = g_malloc0(sizeof(GlusterConf));
|
||||
GlusterConf *gconf = g_new0(GlusterConf, 1);
|
||||
|
||||
glfs = qemu_gluster_init(gconf, filename, errp);
|
||||
if (!glfs) {
|
||||
|
@ -1512,7 +1512,8 @@ static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
|
||||
if (iscsilun->allocationmap != NULL) {
|
||||
g_free(iscsilun->allocationmap);
|
||||
iscsilun->allocationmap =
|
||||
bitmap_new(DIV_ROUND_UP(bs->total_sectors,
|
||||
bitmap_new(DIV_ROUND_UP(sector_lun2qemu(iscsilun->num_blocks,
|
||||
iscsilun),
|
||||
iscsilun->cluster_sectors));
|
||||
}
|
||||
|
||||
@ -1532,7 +1533,7 @@ static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
/* Read out options */
|
||||
total_size =
|
||||
qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
|
||||
bs->opaque = g_malloc0(sizeof(struct IscsiLun));
|
||||
bs->opaque = g_new0(struct IscsiLun, 1);
|
||||
iscsilun = bs->opaque;
|
||||
|
||||
bs_options = qdict_new();
|
||||
|
36
block/nbd.c
36
block/nbd.c
@ -31,8 +31,10 @@
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
@ -338,6 +340,37 @@ static void nbd_attach_aio_context(BlockDriverState *bs,
|
||||
nbd_client_session_attach_aio_context(&s->client, new_context);
|
||||
}
|
||||
|
||||
static void nbd_refresh_filename(BlockDriverState *bs)
|
||||
{
|
||||
BDRVNBDState *s = bs->opaque;
|
||||
QDict *opts = qdict_new();
|
||||
const char *path = qemu_opt_get(s->socket_opts, "path");
|
||||
const char *host = qemu_opt_get(s->socket_opts, "host");
|
||||
const char *port = qemu_opt_get(s->socket_opts, "port");
|
||||
const char *export = qemu_opt_get(s->socket_opts, "export");
|
||||
|
||||
qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("nbd")));
|
||||
|
||||
if (path) {
|
||||
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
||||
"nbd+unix:%s", path);
|
||||
qdict_put_obj(opts, "path", QOBJECT(qstring_from_str(path)));
|
||||
} else if (export) {
|
||||
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
||||
"nbd:%s:%s/%s", host, port, export);
|
||||
qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(host)));
|
||||
qdict_put_obj(opts, "port", QOBJECT(qstring_from_str(port)));
|
||||
qdict_put_obj(opts, "export", QOBJECT(qstring_from_str(export)));
|
||||
} else {
|
||||
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
||||
"nbd:%s:%s", host, port);
|
||||
qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(host)));
|
||||
qdict_put_obj(opts, "port", QOBJECT(qstring_from_str(port)));
|
||||
}
|
||||
|
||||
bs->full_open_options = opts;
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_nbd = {
|
||||
.format_name = "nbd",
|
||||
.protocol_name = "nbd",
|
||||
@ -352,6 +385,7 @@ static BlockDriver bdrv_nbd = {
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.bdrv_detach_aio_context = nbd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nbd_attach_aio_context,
|
||||
.bdrv_refresh_filename = nbd_refresh_filename,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_nbd_tcp = {
|
||||
@ -368,6 +402,7 @@ static BlockDriver bdrv_nbd_tcp = {
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.bdrv_detach_aio_context = nbd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nbd_attach_aio_context,
|
||||
.bdrv_refresh_filename = nbd_refresh_filename,
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_nbd_unix = {
|
||||
@ -384,6 +419,7 @@ static BlockDriver bdrv_nbd_unix = {
|
||||
.bdrv_getlength = nbd_getlength,
|
||||
.bdrv_detach_aio_context = nbd_detach_aio_context,
|
||||
.bdrv_attach_aio_context = nbd_attach_aio_context,
|
||||
.bdrv_refresh_filename = nbd_refresh_filename,
|
||||
};
|
||||
|
||||
static void bdrv_nbd_init(void)
|
||||
|
@ -409,7 +409,7 @@ static int nfs_file_create(const char *url, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
int64_t total_size = 0;
|
||||
NFSClient *client = g_malloc0(sizeof(NFSClient));
|
||||
NFSClient *client = g_new0(NFSClient, 1);
|
||||
|
||||
client->aio_context = qemu_get_aio_context();
|
||||
|
||||
|
@ -121,7 +121,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
ret = -EFBIG;
|
||||
goto fail;
|
||||
}
|
||||
s->catalog_bitmap = g_try_malloc(s->catalog_size * 4);
|
||||
s->catalog_bitmap = g_try_new(uint32_t, s->catalog_size);
|
||||
if (s->catalog_size && s->catalog_bitmap == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
|
@ -182,7 +182,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
s->l1_table_offset = header.l1_table_offset;
|
||||
s->l1_table = g_try_malloc(s->l1_size * sizeof(uint64_t));
|
||||
s->l1_table = g_try_new(uint64_t, s->l1_size);
|
||||
if (s->l1_table == NULL) {
|
||||
error_setg(errp, "Could not allocate memory for L1 table");
|
||||
ret = -ENOMEM;
|
||||
|
@ -48,9 +48,12 @@ Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables)
|
||||
Qcow2Cache *c;
|
||||
int i;
|
||||
|
||||
c = g_malloc0(sizeof(*c));
|
||||
c = g_new0(Qcow2Cache, 1);
|
||||
c->size = num_tables;
|
||||
c->entries = g_malloc0(sizeof(*c->entries) * num_tables);
|
||||
c->entries = g_try_new0(Qcow2CachedTable, num_tables);
|
||||
if (!c->entries) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < c->size; i++) {
|
||||
c->entries[i].table = qemu_try_blockalign(bs->file, s->cluster_size);
|
||||
@ -62,8 +65,10 @@ Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables)
|
||||
return c;
|
||||
|
||||
fail:
|
||||
for (i = 0; i < c->size; i++) {
|
||||
qemu_vfree(c->entries[i].table);
|
||||
if (c->entries) {
|
||||
for (i = 0; i < c->size; i++) {
|
||||
qemu_vfree(c->entries[i].table);
|
||||
}
|
||||
}
|
||||
g_free(c->entries);
|
||||
g_free(c);
|
||||
|
@ -711,7 +711,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
|
||||
trace_qcow2_cluster_link_l2(qemu_coroutine_self(), m->nb_clusters);
|
||||
assert(m->nb_clusters > 0);
|
||||
|
||||
old_cluster = g_try_malloc(m->nb_clusters * sizeof(uint64_t));
|
||||
old_cluster = g_try_new(uint64_t, m->nb_clusters);
|
||||
if (old_cluster == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
|
@ -350,7 +350,7 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
||||
uint64_t meta_offset = (blocks_used * refcount_block_clusters) *
|
||||
s->cluster_size;
|
||||
uint64_t table_offset = meta_offset + blocks_clusters * s->cluster_size;
|
||||
uint64_t *new_table = g_try_malloc0(table_size * sizeof(uint64_t));
|
||||
uint64_t *new_table = g_try_new0(uint64_t, table_size);
|
||||
uint16_t *new_blocks = g_try_malloc0(blocks_clusters * s->cluster_size);
|
||||
|
||||
assert(table_size > 0 && blocks_clusters > 0);
|
||||
@ -1524,7 +1524,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
refcount_table = g_try_malloc0(nb_clusters * sizeof(uint16_t));
|
||||
refcount_table = g_try_new0(uint16_t, nb_clusters);
|
||||
if (nb_clusters && refcount_table == NULL) {
|
||||
res->check_errors++;
|
||||
return -ENOMEM;
|
||||
@ -1605,8 +1605,8 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
/* increase refcount_table size if necessary */
|
||||
int old_nb_clusters = nb_clusters;
|
||||
nb_clusters = (new_offset >> s->cluster_bits) + 1;
|
||||
refcount_table = g_realloc(refcount_table,
|
||||
nb_clusters * sizeof(uint16_t));
|
||||
refcount_table = g_renew(uint16_t, refcount_table,
|
||||
nb_clusters);
|
||||
memset(&refcount_table[old_nb_clusters], 0, (nb_clusters
|
||||
- old_nb_clusters) * sizeof(uint16_t));
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
offset = s->snapshots_offset;
|
||||
s->snapshots = g_malloc0(s->nb_snapshots * sizeof(QCowSnapshot));
|
||||
s->snapshots = g_new0(QCowSnapshot, s->nb_snapshots);
|
||||
|
||||
for(i = 0; i < s->nb_snapshots; i++) {
|
||||
/* Read statically sized part of the snapshot header */
|
||||
@ -381,7 +381,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
sn->l1_table_offset = l1_table_offset;
|
||||
sn->l1_size = s->l1_size;
|
||||
|
||||
l1_table = g_try_malloc(s->l1_size * sizeof(uint64_t));
|
||||
l1_table = g_try_new(uint64_t, s->l1_size);
|
||||
if (s->l1_size && l1_table == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
@ -417,7 +417,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
}
|
||||
|
||||
/* Append the new snapshot to the snapshot list */
|
||||
new_snapshot_list = g_malloc((s->nb_snapshots + 1) * sizeof(QCowSnapshot));
|
||||
new_snapshot_list = g_new(QCowSnapshot, s->nb_snapshots + 1);
|
||||
if (s->snapshots) {
|
||||
memcpy(new_snapshot_list, s->snapshots,
|
||||
s->nb_snapshots * sizeof(QCowSnapshot));
|
||||
@ -661,7 +661,7 @@ int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
return s->nb_snapshots;
|
||||
}
|
||||
|
||||
sn_tab = g_malloc0(s->nb_snapshots * sizeof(QEMUSnapshotInfo));
|
||||
sn_tab = g_new0(QEMUSnapshotInfo, s->nb_snapshots);
|
||||
for(i = 0; i < s->nb_snapshots; i++) {
|
||||
sn_info = sn_tab + i;
|
||||
sn = s->snapshots + i;
|
||||
|
120
block/qcow2.c
120
block/qcow2.c
@ -442,6 +442,22 @@ static QemuOptsList qcow2_runtime_opts = {
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Check for unintended writes into an inactive L2 table",
|
||||
},
|
||||
{
|
||||
.name = QCOW2_OPT_CACHE_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Maximum combined metadata (L2 tables and refcount blocks) "
|
||||
"cache size",
|
||||
},
|
||||
{
|
||||
.name = QCOW2_OPT_L2_CACHE_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Maximum L2 table cache size",
|
||||
},
|
||||
{
|
||||
.name = QCOW2_OPT_REFCOUNT_CACHE_SIZE,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "Maximum refcount block cache size",
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
@ -457,6 +473,61 @@ static const char *overlap_bool_option_names[QCOW2_OL_MAX_BITNR] = {
|
||||
[QCOW2_OL_INACTIVE_L2_BITNR] = QCOW2_OPT_OVERLAP_INACTIVE_L2,
|
||||
};
|
||||
|
||||
static void read_cache_sizes(QemuOpts *opts, uint64_t *l2_cache_size,
|
||||
uint64_t *refcount_cache_size, Error **errp)
|
||||
{
|
||||
uint64_t combined_cache_size;
|
||||
bool l2_cache_size_set, refcount_cache_size_set, combined_cache_size_set;
|
||||
|
||||
combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE);
|
||||
l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE);
|
||||
refcount_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_REFCOUNT_CACHE_SIZE);
|
||||
|
||||
combined_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_CACHE_SIZE, 0);
|
||||
*l2_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_L2_CACHE_SIZE, 0);
|
||||
*refcount_cache_size = qemu_opt_get_size(opts,
|
||||
QCOW2_OPT_REFCOUNT_CACHE_SIZE, 0);
|
||||
|
||||
if (combined_cache_size_set) {
|
||||
if (l2_cache_size_set && refcount_cache_size_set) {
|
||||
error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE
|
||||
" and " QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not be set "
|
||||
"the same time");
|
||||
return;
|
||||
} else if (*l2_cache_size > combined_cache_size) {
|
||||
error_setg(errp, QCOW2_OPT_L2_CACHE_SIZE " may not exceed "
|
||||
QCOW2_OPT_CACHE_SIZE);
|
||||
return;
|
||||
} else if (*refcount_cache_size > combined_cache_size) {
|
||||
error_setg(errp, QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not exceed "
|
||||
QCOW2_OPT_CACHE_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (l2_cache_size_set) {
|
||||
*refcount_cache_size = combined_cache_size - *l2_cache_size;
|
||||
} else if (refcount_cache_size_set) {
|
||||
*l2_cache_size = combined_cache_size - *refcount_cache_size;
|
||||
} else {
|
||||
*refcount_cache_size = combined_cache_size
|
||||
/ (DEFAULT_L2_REFCOUNT_SIZE_RATIO + 1);
|
||||
*l2_cache_size = combined_cache_size - *refcount_cache_size;
|
||||
}
|
||||
} else {
|
||||
if (!l2_cache_size_set && !refcount_cache_size_set) {
|
||||
*l2_cache_size = DEFAULT_L2_CACHE_BYTE_SIZE;
|
||||
*refcount_cache_size = *l2_cache_size
|
||||
/ DEFAULT_L2_REFCOUNT_SIZE_RATIO;
|
||||
} else if (!l2_cache_size_set) {
|
||||
*l2_cache_size = *refcount_cache_size
|
||||
* DEFAULT_L2_REFCOUNT_SIZE_RATIO;
|
||||
} else if (!refcount_cache_size_set) {
|
||||
*refcount_cache_size = *l2_cache_size
|
||||
/ DEFAULT_L2_REFCOUNT_SIZE_RATIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
Error **errp)
|
||||
{
|
||||
@ -470,6 +541,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
uint64_t l1_vm_state_index;
|
||||
const char *opt_overlap_check;
|
||||
int overlap_check_template = 0;
|
||||
uint64_t l2_cache_size, refcount_cache_size;
|
||||
|
||||
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
|
||||
if (ret < 0) {
|
||||
@ -706,9 +778,45 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
}
|
||||
|
||||
/* get L2 table/refcount block cache size from command line options */
|
||||
opts = qemu_opts_create(&qcow2_runtime_opts, NULL, 0, &error_abort);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
read_cache_sizes(opts, &l2_cache_size, &refcount_cache_size, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
l2_cache_size /= s->cluster_size;
|
||||
if (l2_cache_size < MIN_L2_CACHE_SIZE) {
|
||||
l2_cache_size = MIN_L2_CACHE_SIZE;
|
||||
}
|
||||
if (l2_cache_size > INT_MAX) {
|
||||
error_setg(errp, "L2 cache size too big");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
refcount_cache_size /= s->cluster_size;
|
||||
if (refcount_cache_size < MIN_REFCOUNT_CACHE_SIZE) {
|
||||
refcount_cache_size = MIN_REFCOUNT_CACHE_SIZE;
|
||||
}
|
||||
if (refcount_cache_size > INT_MAX) {
|
||||
error_setg(errp, "Refcount cache size too big");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* alloc L2 table/refcount block cache */
|
||||
s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE);
|
||||
s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE);
|
||||
s->l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
|
||||
s->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
|
||||
if (s->l2_table_cache == NULL || s->refcount_block_cache == NULL) {
|
||||
error_setg(errp, "Could not allocate metadata caches");
|
||||
ret = -ENOMEM;
|
||||
@ -798,14 +906,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
/* Enable lazy_refcounts according to image and command line options */
|
||||
opts = qemu_opts_create(&qcow2_runtime_opts, NULL, 0, &error_abort);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
|
||||
(s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
|
||||
|
||||
|
@ -64,10 +64,16 @@
|
||||
#define MIN_CLUSTER_BITS 9
|
||||
#define MAX_CLUSTER_BITS 21
|
||||
|
||||
#define L2_CACHE_SIZE 16
|
||||
#define MIN_L2_CACHE_SIZE 1 /* cluster */
|
||||
|
||||
/* Must be at least 4 to cover all cases of refcount table growth */
|
||||
#define REFCOUNT_CACHE_SIZE 4
|
||||
#define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
|
||||
|
||||
#define DEFAULT_L2_CACHE_BYTE_SIZE 1048576 /* bytes */
|
||||
|
||||
/* The refblock cache needs only a fourth of the L2 cache size to cover as many
|
||||
* clusters */
|
||||
#define DEFAULT_L2_REFCOUNT_SIZE_RATIO 4
|
||||
|
||||
#define DEFAULT_CLUSTER_SIZE 65536
|
||||
|
||||
@ -85,6 +91,9 @@
|
||||
#define QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE "overlap-check.snapshot-table"
|
||||
#define QCOW2_OPT_OVERLAP_INACTIVE_L1 "overlap-check.inactive-l1"
|
||||
#define QCOW2_OPT_OVERLAP_INACTIVE_L2 "overlap-check.inactive-l2"
|
||||
#define QCOW2_OPT_CACHE_SIZE "cache-size"
|
||||
#define QCOW2_OPT_L2_CACHE_SIZE "l2-cache-size"
|
||||
#define QCOW2_OPT_REFCOUNT_CACHE_SIZE "refcount-cache-size"
|
||||
|
||||
typedef struct QCowHeader {
|
||||
uint32_t magic;
|
||||
|
@ -227,8 +227,7 @@ int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix)
|
||||
};
|
||||
int ret;
|
||||
|
||||
check.used_clusters = g_try_malloc0(((check.nclusters + 31) / 32) *
|
||||
sizeof(check.used_clusters[0]));
|
||||
check.used_clusters = g_try_new0(uint32_t, (check.nclusters + 31) / 32);
|
||||
if (check.nclusters && check.used_clusters == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -16,7 +16,12 @@
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include "block/block_int.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qapi-event.h"
|
||||
|
||||
#define HASH_LENGTH 32
|
||||
@ -945,6 +950,39 @@ static void quorum_attach_aio_context(BlockDriverState *bs,
|
||||
}
|
||||
}
|
||||
|
||||
static void quorum_refresh_filename(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQuorumState *s = bs->opaque;
|
||||
QDict *opts;
|
||||
QList *children;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
bdrv_refresh_filename(s->bs[i]);
|
||||
if (!s->bs[i]->full_open_options) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
children = qlist_new();
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
QINCREF(s->bs[i]->full_open_options);
|
||||
qlist_append_obj(children, QOBJECT(s->bs[i]->full_open_options));
|
||||
}
|
||||
|
||||
opts = qdict_new();
|
||||
qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("quorum")));
|
||||
qdict_put_obj(opts, QUORUM_OPT_VOTE_THRESHOLD,
|
||||
QOBJECT(qint_from_int(s->threshold)));
|
||||
qdict_put_obj(opts, QUORUM_OPT_BLKVERIFY,
|
||||
QOBJECT(qbool_from_int(s->is_blkverify)));
|
||||
qdict_put_obj(opts, QUORUM_OPT_REWRITE,
|
||||
QOBJECT(qbool_from_int(s->rewrite_corrupted)));
|
||||
qdict_put_obj(opts, "children", QOBJECT(children));
|
||||
|
||||
bs->full_open_options = opts;
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_quorum = {
|
||||
.format_name = "quorum",
|
||||
.protocol_name = "quorum",
|
||||
@ -953,6 +991,7 @@ static BlockDriver bdrv_quorum = {
|
||||
|
||||
.bdrv_file_open = quorum_open,
|
||||
.bdrv_close = quorum_close,
|
||||
.bdrv_refresh_filename = quorum_refresh_filename,
|
||||
|
||||
.bdrv_co_flush_to_disk = quorum_co_flush,
|
||||
|
||||
|
@ -517,7 +517,7 @@ static int raw_reopen_prepare(BDRVReopenState *state,
|
||||
|
||||
s = state->bs->opaque;
|
||||
|
||||
state->opaque = g_malloc0(sizeof(BDRVRawReopenState));
|
||||
state->opaque = g_new0(BDRVRawReopenState, 1);
|
||||
raw_s = state->opaque;
|
||||
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
@ -747,6 +747,15 @@ static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf)
|
||||
}
|
||||
if (len == -1 && errno == EINTR) {
|
||||
continue;
|
||||
} else if (len == -1 && errno == EINVAL &&
|
||||
(aiocb->bs->open_flags & BDRV_O_NOCACHE) &&
|
||||
!(aiocb->aio_type & QEMU_AIO_WRITE) &&
|
||||
offset > 0) {
|
||||
/* O_DIRECT pread() may fail with EINVAL when offset is unaligned
|
||||
* after a short read. Assume that O_DIRECT short reads only occur
|
||||
* at EOF. Therefore this is a short read, not an I/O error.
|
||||
*/
|
||||
break;
|
||||
} else if (len == -1) {
|
||||
offset = -errno;
|
||||
break;
|
||||
|
@ -652,7 +652,7 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
|
||||
off = sector_num * BDRV_SECTOR_SIZE;
|
||||
size = nb_sectors * BDRV_SECTOR_SIZE;
|
||||
|
||||
rcb = g_malloc(sizeof(RADOSCB));
|
||||
rcb = g_new(RADOSCB, 1);
|
||||
rcb->done = 0;
|
||||
rcb->acb = acb;
|
||||
rcb->buf = buf;
|
||||
@ -862,7 +862,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
|
||||
int max_snaps = RBD_MAX_SNAPS;
|
||||
|
||||
do {
|
||||
snaps = g_malloc(sizeof(*snaps) * max_snaps);
|
||||
snaps = g_new(rbd_snap_info_t, max_snaps);
|
||||
snap_count = rbd_snap_list(s->image, snaps, &max_snaps);
|
||||
if (snap_count <= 0) {
|
||||
g_free(snaps);
|
||||
@ -873,7 +873,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
|
||||
goto done;
|
||||
}
|
||||
|
||||
sn_tab = g_malloc0(snap_count * sizeof(QEMUSnapshotInfo));
|
||||
sn_tab = g_new0(QEMUSnapshotInfo, snap_count);
|
||||
|
||||
for (i = 0; i < snap_count; i++) {
|
||||
const char *snap_name = snaps[i].name;
|
||||
|
@ -1682,7 +1682,7 @@ static int sd_create(const char *filename, QemuOpts *opts,
|
||||
uint32_t snapid;
|
||||
bool prealloc = false;
|
||||
|
||||
s = g_malloc0(sizeof(BDRVSheepdogState));
|
||||
s = g_new0(BDRVSheepdogState, 1);
|
||||
|
||||
memset(tag, 0, sizeof(tag));
|
||||
if (strstr(filename, "://")) {
|
||||
@ -2273,7 +2273,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
uint32_t snapid = 0;
|
||||
int ret = 0;
|
||||
|
||||
old_s = g_malloc(sizeof(BDRVSheepdogState));
|
||||
old_s = g_new(BDRVSheepdogState, 1);
|
||||
|
||||
memcpy(old_s, s, sizeof(BDRVSheepdogState));
|
||||
|
||||
@ -2357,7 +2357,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sn_tab = g_malloc0(nr * sizeof(*sn_tab));
|
||||
sn_tab = g_new0(QEMUSnapshotInfo, nr);
|
||||
|
||||
/* calculate a vdi id with hash function */
|
||||
hval = fnv_64a_buf(s->name, strlen(s->name), FNV1A_64_INIT);
|
||||
|
@ -292,7 +292,7 @@ static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res,
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
bmap = g_try_malloc(s->header.blocks_in_image * sizeof(uint32_t));
|
||||
bmap = g_try_new(uint32_t, s->header.blocks_in_image);
|
||||
if (s->header.blocks_in_image && bmap == NULL) {
|
||||
res->check_errors++;
|
||||
return -ENOMEM;
|
||||
|
@ -923,7 +923,7 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
buffer = qemu_blockalign(bs, total_length);
|
||||
memcpy(buffer, &new_hdr, sizeof(new_hdr));
|
||||
|
||||
new_desc = (VHDXLogDescriptor *) (buffer + sizeof(new_hdr));
|
||||
new_desc = buffer + sizeof(new_hdr);
|
||||
data_sector = buffer + (desc_sectors * VHDX_LOG_SECTOR_SIZE);
|
||||
data_tmp = data;
|
||||
|
||||
|
@ -1381,7 +1381,7 @@ static int vhdx_create_new_headers(BlockDriverState *bs, uint64_t image_size,
|
||||
int ret = 0;
|
||||
VHDXHeader *hdr = NULL;
|
||||
|
||||
hdr = g_malloc0(sizeof(VHDXHeader));
|
||||
hdr = g_new0(VHDXHeader, 1);
|
||||
|
||||
hdr->signature = VHDX_HEADER_SIGNATURE;
|
||||
hdr->sequence_number = g_random_int();
|
||||
@ -1654,7 +1654,7 @@ static int vhdx_create_new_region_table(BlockDriverState *bs,
|
||||
|
||||
/* Populate enough of the BDRVVHDXState to be able to use the
|
||||
* pre-existing BAT calculation, translation, and update functions */
|
||||
s = g_malloc0(sizeof(BDRVVHDXState));
|
||||
s = g_new0(BDRVVHDXState, 1);
|
||||
|
||||
s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) *
|
||||
(uint64_t) sector_size / (uint64_t) block_size;
|
||||
|
18
block/vmdk.c
18
block/vmdk.c
@ -233,7 +233,7 @@ static void vmdk_free_last_extent(BlockDriverState *bs)
|
||||
return;
|
||||
}
|
||||
s->num_extents--;
|
||||
s->extents = g_realloc(s->extents, s->num_extents * sizeof(VmdkExtent));
|
||||
s->extents = g_renew(VmdkExtent, s->extents, s->num_extents);
|
||||
}
|
||||
|
||||
static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
|
||||
@ -397,7 +397,7 @@ static int vmdk_add_extent(BlockDriverState *bs,
|
||||
{
|
||||
VmdkExtent *extent;
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
int64_t length;
|
||||
int64_t nb_sectors;
|
||||
|
||||
if (cluster_sectors > 0x200000) {
|
||||
/* 0x200000 * 512Bytes = 1GB for one cluster is unrealistic */
|
||||
@ -413,13 +413,12 @@ static int vmdk_add_extent(BlockDriverState *bs,
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
length = bdrv_getlength(file);
|
||||
if (length < 0) {
|
||||
return length;
|
||||
nb_sectors = bdrv_nb_sectors(file);
|
||||
if (nb_sectors < 0) {
|
||||
return nb_sectors;
|
||||
}
|
||||
|
||||
s->extents = g_realloc(s->extents,
|
||||
(s->num_extents + 1) * sizeof(VmdkExtent));
|
||||
s->extents = g_renew(VmdkExtent, s->extents, s->num_extents + 1);
|
||||
extent = &s->extents[s->num_extents];
|
||||
s->num_extents++;
|
||||
|
||||
@ -433,8 +432,7 @@ static int vmdk_add_extent(BlockDriverState *bs,
|
||||
extent->l1_entry_sectors = l2_size * cluster_sectors;
|
||||
extent->l2_size = l2_size;
|
||||
extent->cluster_sectors = flat ? sectors : cluster_sectors;
|
||||
extent->next_cluster_sector =
|
||||
ROUND_UP(DIV_ROUND_UP(length, BDRV_SECTOR_SIZE), cluster_sectors);
|
||||
extent->next_cluster_sector = ROUND_UP(nb_sectors, cluster_sectors);
|
||||
|
||||
if (s->num_extents > 1) {
|
||||
extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
|
||||
@ -497,7 +495,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
|
||||
}
|
||||
|
||||
extent->l2_cache =
|
||||
g_malloc(extent->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
|
||||
g_new(uint32_t, extent->l2_size * L2_CACHE_SIZE);
|
||||
return 0;
|
||||
fail_l1b:
|
||||
g_free(extent->l1_backup_table);
|
||||
|
@ -52,10 +52,6 @@
|
||||
|
||||
#define DLOG(a) a
|
||||
|
||||
#undef stderr
|
||||
#define stderr STDERR
|
||||
FILE* stderr = NULL;
|
||||
|
||||
static void checkpoint(void);
|
||||
|
||||
#ifdef __MINGW32__
|
||||
@ -732,7 +728,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
|
||||
if(first_cluster == 0 && (is_dotdot || is_dot))
|
||||
continue;
|
||||
|
||||
buffer=(char*)g_malloc(length);
|
||||
buffer = g_malloc(length);
|
||||
snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
|
||||
|
||||
if(stat(buffer,&st)<0) {
|
||||
@ -767,7 +763,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
|
||||
|
||||
/* create mapping for this file */
|
||||
if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
|
||||
s->current_mapping=(mapping_t*)array_get_next(&(s->mapping));
|
||||
s->current_mapping = array_get_next(&(s->mapping));
|
||||
s->current_mapping->begin=0;
|
||||
s->current_mapping->end=st.st_size;
|
||||
/*
|
||||
@ -811,12 +807,12 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
|
||||
}
|
||||
|
||||
/* reget the mapping, since s->mapping was possibly realloc()ed */
|
||||
mapping = (mapping_t*)array_get(&(s->mapping), mapping_index);
|
||||
mapping = array_get(&(s->mapping), mapping_index);
|
||||
first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
|
||||
* 0x20 / s->cluster_size;
|
||||
mapping->end = first_cluster;
|
||||
|
||||
direntry = (direntry_t*)array_get(&(s->directory), mapping->dir_index);
|
||||
direntry = array_get(&(s->directory), mapping->dir_index);
|
||||
set_begin_of_direntry(direntry, mapping->begin);
|
||||
|
||||
return 0;
|
||||
@ -1082,11 +1078,6 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
vvv = s;
|
||||
#endif
|
||||
|
||||
DLOG(if (stderr == NULL) {
|
||||
stderr = fopen("vvfat.log", "a");
|
||||
setbuf(stderr, NULL);
|
||||
})
|
||||
|
||||
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
|
||||
qemu_opts_absorb_qdict(opts, options, &local_err);
|
||||
if (local_err) {
|
||||
@ -2950,7 +2941,7 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
|
||||
|
||||
bdrv_set_backing_hd(s->bs, bdrv_new("", &error_abort));
|
||||
s->bs->backing_hd->drv = &vvfat_write_target;
|
||||
s->bs->backing_hd->opaque = g_malloc(sizeof(void*));
|
||||
s->bs->backing_hd->opaque = g_new(void *, 1);
|
||||
*(void**)s->bs->backing_hd->opaque = s;
|
||||
|
||||
return 0;
|
||||
|
@ -108,7 +108,7 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
|
||||
|
||||
nbd_export_set_name(exp, device);
|
||||
|
||||
n = g_malloc0(sizeof(NBDCloseNotifier));
|
||||
n = g_new0(NBDCloseNotifier, 1);
|
||||
n->n.notify = nbd_close_notifier;
|
||||
n->exp = exp;
|
||||
bdrv_add_close_notifier(bs, &n->n);
|
||||
|
15
blockdev.c
15
blockdev.c
@ -1094,7 +1094,7 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info = g_malloc0(sizeof(SnapshotInfo));
|
||||
info = g_new0(SnapshotInfo, 1);
|
||||
info->id = g_strdup(sn.id_str);
|
||||
info->name = g_strdup(sn.name);
|
||||
info->date_nsec = sn.date_nsec;
|
||||
@ -1799,6 +1799,7 @@ void qmp_block_resize(bool has_device, const char *device,
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BlockDriverState *bs;
|
||||
AioContext *aio_context;
|
||||
int ret;
|
||||
|
||||
bs = bdrv_lookup_bs(has_device ? device : NULL,
|
||||
@ -1809,19 +1810,22 @@ void qmp_block_resize(bool has_device, const char *device,
|
||||
return;
|
||||
}
|
||||
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
if (!bdrv_is_first_non_filter(bs)) {
|
||||
error_set(errp, QERR_FEATURE_DISABLED, "resize");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
error_set(errp, QERR_INVALID_PARAMETER_VALUE, "size", "a >0 size");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_RESIZE, NULL)) {
|
||||
error_set(errp, QERR_DEVICE_IN_USE, device);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* complete all in-flight operations before resizing the device */
|
||||
@ -1847,6 +1851,9 @@ void qmp_block_resize(bool has_device, const char *device,
|
||||
error_setg_errno(errp, -ret, "Could not resize");
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
static void block_job_cb(void *opaque, int ret)
|
||||
|
@ -193,6 +193,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
|
||||
|
||||
error_setg(&s->blocker, "block device is in use by data plane");
|
||||
bdrv_op_block_all(blk->conf.bs, s->blocker);
|
||||
bdrv_op_unblock(blk->conf.bs, BLOCK_OP_TYPE_RESIZE, s->blocker);
|
||||
|
||||
*dataplane = s;
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr,
|
||||
sq->size = size;
|
||||
sq->cqid = cqid;
|
||||
sq->head = sq->tail = 0;
|
||||
sq->io_req = g_malloc(sq->size * sizeof(*sq->io_req));
|
||||
sq->io_req = g_new(NvmeRequest, sq->size);
|
||||
|
||||
QTAILQ_INIT(&sq->req_list);
|
||||
QTAILQ_INIT(&sq->out_req_list);
|
||||
@ -773,9 +773,9 @@ static int nvme_init(PCIDevice *pci_dev)
|
||||
n->reg_size = 1 << qemu_fls(0x1004 + 2 * (n->num_queues + 1) * 4);
|
||||
n->ns_size = bs_size / (uint64_t)n->num_namespaces;
|
||||
|
||||
n->namespaces = g_malloc0(sizeof(*n->namespaces)*n->num_namespaces);
|
||||
n->sq = g_malloc0(sizeof(*n->sq)*n->num_queues);
|
||||
n->cq = g_malloc0(sizeof(*n->cq)*n->num_queues);
|
||||
n->namespaces = g_new0(NvmeNamespace, n->num_namespaces);
|
||||
n->sq = g_new0(NvmeSQueue *, n->num_queues);
|
||||
n->cq = g_new0(NvmeCQueue *, n->num_queues);
|
||||
|
||||
memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n,
|
||||
"nvme", n->reg_size);
|
||||
|
@ -469,8 +469,9 @@ static void virtio_blk_dma_restart_bh(void *opaque)
|
||||
s->rq = NULL;
|
||||
|
||||
while (req) {
|
||||
VirtIOBlockReq *next = req->next;
|
||||
virtio_blk_handle_request(req, &mrb);
|
||||
req = req->next;
|
||||
req = next;
|
||||
}
|
||||
|
||||
virtio_submit_multiwrite(s->bs, &mrb);
|
||||
|
@ -1203,7 +1203,7 @@ void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports)
|
||||
|
||||
s->as = as;
|
||||
s->ports = ports;
|
||||
s->dev = g_malloc0(sizeof(AHCIDevice) * ports);
|
||||
s->dev = g_new0(AHCIDevice, ports);
|
||||
ahci_reg_init(s);
|
||||
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
|
||||
memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s,
|
||||
|
@ -567,7 +567,7 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *dinfo)
|
||||
}
|
||||
md->bus.ifs[0].drive_kind = IDE_CFATA;
|
||||
md->bus.ifs[0].mdata_size = METADATA_SIZE;
|
||||
md->bus.ifs[0].mdata_storage = (uint8_t *) g_malloc0(METADATA_SIZE);
|
||||
md->bus.ifs[0].mdata_storage = g_malloc0(METADATA_SIZE);
|
||||
|
||||
return PCMCIA_CARD(md);
|
||||
}
|
||||
|
@ -274,6 +274,7 @@ int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
||||
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
|
||||
const char *backing_file);
|
||||
int bdrv_get_backing_file_depth(BlockDriverState *bs);
|
||||
void bdrv_refresh_filename(BlockDriverState *bs);
|
||||
int bdrv_truncate(BlockDriverState *bs, int64_t offset);
|
||||
int64_t bdrv_nb_sectors(BlockDriverState *bs);
|
||||
int64_t bdrv_getlength(BlockDriverState *bs);
|
||||
|
@ -123,6 +123,9 @@ struct BlockDriver {
|
||||
int (*bdrv_create)(const char *filename, QemuOpts *opts, Error **errp);
|
||||
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
|
||||
int (*bdrv_make_empty)(BlockDriverState *bs);
|
||||
|
||||
void (*bdrv_refresh_filename)(BlockDriverState *bs);
|
||||
|
||||
/* aio */
|
||||
BlockDriverAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
@ -323,6 +326,9 @@ struct BlockDriverState {
|
||||
this file image */
|
||||
char backing_format[16]; /* if non-zero and backing_file exists */
|
||||
|
||||
QDict *full_open_options;
|
||||
char exact_filename[1024];
|
||||
|
||||
BlockDriverState *backing_hd;
|
||||
BlockDriverState *file;
|
||||
|
||||
|
@ -10,9 +10,9 @@ STEXI
|
||||
ETEXI
|
||||
|
||||
DEF("check", img_check,
|
||||
"check [-q] [-f fmt] [--output=ofmt] [-r [leaks | all]] filename")
|
||||
"check [-q] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename")
|
||||
STEXI
|
||||
@item check [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] @var{filename}
|
||||
@item check [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
|
||||
ETEXI
|
||||
|
||||
DEF("create", img_create,
|
||||
@ -28,15 +28,15 @@ STEXI
|
||||
ETEXI
|
||||
|
||||
DEF("compare", img_compare,
|
||||
"compare [-f fmt] [-F fmt] [-p] [-q] [-s] filename1 filename2")
|
||||
"compare [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2")
|
||||
STEXI
|
||||
@item compare [-f @var{fmt}] [-F @var{fmt}] [-p] [-q] [-s] @var{filename1} @var{filename2}
|
||||
@item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2}
|
||||
ETEXI
|
||||
|
||||
DEF("convert", img_convert,
|
||||
"convert [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename")
|
||||
"convert [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename")
|
||||
STEXI
|
||||
@item convert [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
|
||||
@item convert [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
|
||||
ETEXI
|
||||
|
||||
DEF("info", img_info,
|
||||
@ -58,9 +58,9 @@ STEXI
|
||||
ETEXI
|
||||
|
||||
DEF("rebase", img_rebase,
|
||||
"rebase [-q] [-f fmt] [-t cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
|
||||
"rebase [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
|
||||
STEXI
|
||||
@item rebase [-q] [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
|
||||
@item rebase [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
|
||||
ETEXI
|
||||
|
||||
DEF("resize", img_resize,
|
||||
@ -70,8 +70,8 @@ STEXI
|
||||
ETEXI
|
||||
|
||||
DEF("amend", img_amend,
|
||||
"amend [-q] [-f fmt] -o options filename")
|
||||
"amend [-q] [-f fmt] [-t cache] -o options filename")
|
||||
STEXI
|
||||
@item amend [-q] [-f @var{fmt}] -o @var{options} @var{filename}
|
||||
@item amend [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename}
|
||||
@end table
|
||||
ETEXI
|
||||
|
97
qemu-img.c
97
qemu-img.c
@ -109,6 +109,7 @@ static void QEMU_NORETURN help(void)
|
||||
" 'cache' is the cache mode used to write the output disk image, the valid\n"
|
||||
" options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
|
||||
" 'directsync' and 'unsafe' (default for convert)\n"
|
||||
" 'src_cache' in contrast is the cache mode used to read input disk images\n"
|
||||
" 'size' is the disk image size in bytes. Optional suffixes\n"
|
||||
" 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M),\n"
|
||||
" 'T' (terabyte, 1024G), 'P' (petabyte, 1024T) and 'E' (exabyte, 1024P) are\n"
|
||||
@ -591,7 +592,7 @@ static int img_check(int argc, char **argv)
|
||||
{
|
||||
int c, ret;
|
||||
OutputFormat output_format = OFORMAT_HUMAN;
|
||||
const char *filename, *fmt, *output;
|
||||
const char *filename, *fmt, *output, *cache;
|
||||
BlockDriverState *bs;
|
||||
int fix = 0;
|
||||
int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
|
||||
@ -600,6 +601,7 @@ static int img_check(int argc, char **argv)
|
||||
|
||||
fmt = NULL;
|
||||
output = NULL;
|
||||
cache = BDRV_DEFAULT_CACHE;
|
||||
for(;;) {
|
||||
int option_index = 0;
|
||||
static const struct option long_options[] = {
|
||||
@ -609,7 +611,7 @@ static int img_check(int argc, char **argv)
|
||||
{"output", required_argument, 0, OPTION_OUTPUT},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv, "f:hr:q",
|
||||
c = getopt_long(argc, argv, "hf:r:T:q",
|
||||
long_options, &option_index);
|
||||
if (c == -1) {
|
||||
break;
|
||||
@ -637,6 +639,9 @@ static int img_check(int argc, char **argv)
|
||||
case OPTION_OUTPUT:
|
||||
output = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
cache = optarg;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
@ -656,6 +661,12 @@ static int img_check(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = bdrv_parse_cache_flags(cache, &flags);
|
||||
if (ret < 0) {
|
||||
error_report("Invalid source cache option: %s", cache);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
|
||||
if (!bs) {
|
||||
return 1;
|
||||
@ -948,7 +959,7 @@ static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
|
||||
*/
|
||||
static int img_compare(int argc, char **argv)
|
||||
{
|
||||
const char *fmt1 = NULL, *fmt2 = NULL, *filename1, *filename2;
|
||||
const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
|
||||
BlockDriverState *bs1, *bs2;
|
||||
int64_t total_sectors1, total_sectors2;
|
||||
uint8_t *buf1 = NULL, *buf2 = NULL;
|
||||
@ -956,14 +967,16 @@ static int img_compare(int argc, char **argv)
|
||||
int allocated1, allocated2;
|
||||
int ret = 0; /* return value - 0 Ident, 1 Different, >1 Error */
|
||||
bool progress = false, quiet = false, strict = false;
|
||||
int flags;
|
||||
int64_t total_sectors;
|
||||
int64_t sector_num = 0;
|
||||
int64_t nb_sectors;
|
||||
int c, pnum;
|
||||
uint64_t progress_base;
|
||||
|
||||
cache = BDRV_DEFAULT_CACHE;
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "hpf:F:sq");
|
||||
c = getopt(argc, argv, "hf:F:T:pqs");
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
@ -978,6 +991,9 @@ static int img_compare(int argc, char **argv)
|
||||
case 'F':
|
||||
fmt2 = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
cache = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
progress = true;
|
||||
break;
|
||||
@ -1002,17 +1018,25 @@ static int img_compare(int argc, char **argv)
|
||||
filename1 = argv[optind++];
|
||||
filename2 = argv[optind++];
|
||||
|
||||
flags = BDRV_O_FLAGS;
|
||||
ret = bdrv_parse_cache_flags(cache, &flags);
|
||||
if (ret < 0) {
|
||||
error_report("Invalid source cache option: %s", cache);
|
||||
ret = 2;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
/* Initialize before goto out */
|
||||
qemu_progress_init(progress, 2.0);
|
||||
|
||||
bs1 = bdrv_new_open("image 1", filename1, fmt1, BDRV_O_FLAGS, true, quiet);
|
||||
bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
|
||||
if (!bs1) {
|
||||
error_report("Can't open file %s", filename1);
|
||||
ret = 2;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
bs2 = bdrv_new_open("image 2", filename2, fmt2, BDRV_O_FLAGS, true, quiet);
|
||||
bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
|
||||
if (!bs2) {
|
||||
error_report("Can't open file %s", filename2);
|
||||
ret = 2;
|
||||
@ -1191,8 +1215,8 @@ static int img_convert(int argc, char **argv)
|
||||
{
|
||||
int c, n, n1, bs_n, bs_i, compress, cluster_sectors, skip_create;
|
||||
int64_t ret = 0;
|
||||
int progress = 0, flags;
|
||||
const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
|
||||
int progress = 0, flags, src_flags;
|
||||
const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
|
||||
BlockDriver *drv, *proto_drv;
|
||||
BlockDriverState **bs = NULL, *out_bs = NULL;
|
||||
int64_t total_sectors, nb_sectors, sector_num, bs_offset;
|
||||
@ -1214,11 +1238,12 @@ static int img_convert(int argc, char **argv)
|
||||
fmt = NULL;
|
||||
out_fmt = "raw";
|
||||
cache = "unsafe";
|
||||
src_cache = BDRV_DEFAULT_CACHE;
|
||||
out_baseimg = NULL;
|
||||
compress = 0;
|
||||
skip_create = 0;
|
||||
for(;;) {
|
||||
c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:qnl:");
|
||||
c = getopt(argc, argv, "hf:O:B:ce6o:s:l:S:pt:T:qn");
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
@ -1299,6 +1324,9 @@ static int img_convert(int argc, char **argv)
|
||||
case 't':
|
||||
cache = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
src_cache = optarg;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
@ -1335,6 +1363,13 @@ static int img_convert(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
src_flags = BDRV_O_FLAGS;
|
||||
ret = bdrv_parse_cache_flags(src_cache, &src_flags);
|
||||
if (ret < 0) {
|
||||
error_report("Invalid source cache option: %s", src_cache);
|
||||
goto out;
|
||||
}
|
||||
|
||||
qemu_progress_print(0, 100);
|
||||
|
||||
bs = g_new0(BlockDriverState *, bs_n);
|
||||
@ -1344,7 +1379,7 @@ static int img_convert(int argc, char **argv)
|
||||
for (bs_i = 0; bs_i < bs_n; bs_i++) {
|
||||
char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
|
||||
: g_strdup("source");
|
||||
bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, BDRV_O_FLAGS,
|
||||
bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
|
||||
true, quiet);
|
||||
g_free(id);
|
||||
if (!bs[bs_i]) {
|
||||
@ -2291,8 +2326,8 @@ static int img_rebase(int argc, char **argv)
|
||||
BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
|
||||
BlockDriver *old_backing_drv, *new_backing_drv;
|
||||
char *filename;
|
||||
const char *fmt, *cache, *out_basefmt, *out_baseimg;
|
||||
int c, flags, ret;
|
||||
const char *fmt, *cache, *src_cache, *out_basefmt, *out_baseimg;
|
||||
int c, flags, src_flags, ret;
|
||||
int unsafe = 0;
|
||||
int progress = 0;
|
||||
bool quiet = false;
|
||||
@ -2301,10 +2336,11 @@ static int img_rebase(int argc, char **argv)
|
||||
/* Parse commandline parameters */
|
||||
fmt = NULL;
|
||||
cache = BDRV_DEFAULT_CACHE;
|
||||
src_cache = BDRV_DEFAULT_CACHE;
|
||||
out_baseimg = NULL;
|
||||
out_basefmt = NULL;
|
||||
for(;;) {
|
||||
c = getopt(argc, argv, "uhf:F:b:pt:q");
|
||||
c = getopt(argc, argv, "hf:F:b:upt:T:q");
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
@ -2331,6 +2367,9 @@ static int img_rebase(int argc, char **argv)
|
||||
case 't':
|
||||
cache = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
src_cache = optarg;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
@ -2359,6 +2398,13 @@ static int img_rebase(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
src_flags = BDRV_O_FLAGS;
|
||||
ret = bdrv_parse_cache_flags(src_cache, &src_flags);
|
||||
if (ret < 0) {
|
||||
error_report("Invalid source cache option: %s", src_cache);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the images.
|
||||
*
|
||||
@ -2402,7 +2448,7 @@ static int img_rebase(int argc, char **argv)
|
||||
|
||||
bs_old_backing = bdrv_new("old_backing", &error_abort);
|
||||
bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
|
||||
ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, BDRV_O_FLAGS,
|
||||
ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
|
||||
old_backing_drv, &local_err);
|
||||
if (ret) {
|
||||
error_report("Could not open old backing file '%s': %s",
|
||||
@ -2412,8 +2458,8 @@ static int img_rebase(int argc, char **argv)
|
||||
}
|
||||
if (out_baseimg[0]) {
|
||||
bs_new_backing = bdrv_new("new_backing", &error_abort);
|
||||
ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL,
|
||||
BDRV_O_FLAGS, new_backing_drv, &local_err);
|
||||
ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
|
||||
new_backing_drv, &local_err);
|
||||
if (ret) {
|
||||
error_report("Could not open new backing file '%s': %s",
|
||||
out_baseimg, error_get_pretty(local_err));
|
||||
@ -2732,12 +2778,14 @@ static int img_amend(int argc, char **argv)
|
||||
char *options = NULL;
|
||||
QemuOptsList *create_opts = NULL;
|
||||
QemuOpts *opts = NULL;
|
||||
const char *fmt = NULL, *filename;
|
||||
const char *fmt = NULL, *filename, *cache;
|
||||
int flags;
|
||||
bool quiet = false;
|
||||
BlockDriverState *bs = NULL;
|
||||
|
||||
cache = BDRV_DEFAULT_CACHE;
|
||||
for (;;) {
|
||||
c = getopt(argc, argv, "hqf:o:");
|
||||
c = getopt(argc, argv, "ho:f:t:q");
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
@ -2764,6 +2812,9 @@ static int img_amend(int argc, char **argv)
|
||||
case 'f':
|
||||
fmt = optarg;
|
||||
break;
|
||||
case 't':
|
||||
cache = optarg;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
@ -2786,8 +2837,14 @@ static int img_amend(int argc, char **argv)
|
||||
error_exit("Expecting one image file name");
|
||||
}
|
||||
|
||||
bs = bdrv_new_open("image", filename, fmt,
|
||||
BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
|
||||
flags = BDRV_O_FLAGS | BDRV_O_RDWR;
|
||||
ret = bdrv_parse_cache_flags(cache, &flags);
|
||||
if (ret < 0) {
|
||||
error_report("Invalid cache option: %s", cache);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
|
||||
if (!bs) {
|
||||
error_report("Could not open image '%s'", filename);
|
||||
ret = -1;
|
||||
|
@ -72,6 +72,9 @@ down to the nearest 512 bytes. You may use the common size suffixes like
|
||||
specifies the cache mode that should be used with the (destination) file. See
|
||||
the documentation of the emulator's @code{-drive cache=...} option for allowed
|
||||
values.
|
||||
@item -T @var{src_cache}
|
||||
in contrast specifies the cache mode that should be used with the source
|
||||
file(s).
|
||||
@end table
|
||||
|
||||
Parameters to snapshot subcommand:
|
||||
@ -113,7 +116,7 @@ Skip the creation of the target volume
|
||||
Command description:
|
||||
|
||||
@table @option
|
||||
@item check [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] @var{filename}
|
||||
@item check [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
|
||||
|
||||
Perform a consistency check on the disk image @var{filename}. The command can
|
||||
output in the format @var{ofmt} which is either @code{human} or @code{json}.
|
||||
@ -172,7 +175,7 @@ the backing file, the backing file will not be truncated. If you want the
|
||||
backing file to match the size of the smaller snapshot, you can safely truncate
|
||||
it yourself once the commit operation successfully completes.
|
||||
|
||||
@item compare [-f @var{fmt}] [-F @var{fmt}] [-p] [-s] [-q] @var{filename1} @var{filename2}
|
||||
@item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-s] [-q] @var{filename1} @var{filename2}
|
||||
|
||||
Check if two images have the same content. You can compare images with
|
||||
different format or settings.
|
||||
@ -213,7 +216,7 @@ Error on reading data
|
||||
|
||||
@end table
|
||||
|
||||
@item convert [-c] [-p] [-n] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
|
||||
@item convert [-c] [-p] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
|
||||
|
||||
Convert the disk image @var{filename} or a snapshot @var{snapshot_param}(@var{snapshot_id_or_name} is deprecated)
|
||||
to disk image @var{output_filename} using format @var{output_fmt}. It can be optionally compressed (@code{-c}
|
||||
@ -325,7 +328,7 @@ source code.
|
||||
|
||||
List, apply, create or delete snapshots in image @var{filename}.
|
||||
|
||||
@item rebase [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
|
||||
@item rebase [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
|
||||
|
||||
Changes the backing file of an image. Only the formats @code{qcow2} and
|
||||
@code{qed} support changing the backing file.
|
||||
@ -336,6 +339,9 @@ The backing file is changed to @var{backing_file} and (if the image format of
|
||||
string), then the image is rebased onto no backing file (i.e. it will exist
|
||||
independently of any backing file).
|
||||
|
||||
@var{cache} specifies the cache mode to be used for @var{filename}, whereas
|
||||
@var{src_cache} specifies the cache mode for reading the new backing file.
|
||||
|
||||
There are two different modes in which @code{rebase} can operate:
|
||||
@table @option
|
||||
@item Safe mode
|
||||
@ -391,7 +397,7 @@ After using this command to grow a disk image, you must use file system and
|
||||
partitioning tools inside the VM to actually begin using the new space on the
|
||||
device.
|
||||
|
||||
@item amend [-f @var{fmt}] -o @var{options} @var{filename}
|
||||
@item amend [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename}
|
||||
|
||||
Amends the image format specific @var{options} for the image file
|
||||
@var{filename}. Not all file formats support this operation.
|
||||
|
@ -29,7 +29,7 @@ static int compare_cmdname(const void *a, const void *b)
|
||||
|
||||
void qemuio_add_command(const cmdinfo_t *ci)
|
||||
{
|
||||
cmdtab = g_realloc(cmdtab, ++ncmds * sizeof(*cmdtab));
|
||||
cmdtab = g_renew(cmdinfo_t, cmdtab, ++ncmds);
|
||||
cmdtab[ncmds - 1] = *ci;
|
||||
qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
|
||||
}
|
||||
@ -114,23 +114,14 @@ static char **breakline(char *input, int *count)
|
||||
{
|
||||
int c = 0;
|
||||
char *p;
|
||||
char **rval = g_malloc0(sizeof(char *));
|
||||
char **tmp;
|
||||
char **rval = g_new0(char *, 1);
|
||||
|
||||
while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
|
||||
if (!*p) {
|
||||
continue;
|
||||
}
|
||||
c++;
|
||||
tmp = g_realloc(rval, sizeof(*rval) * (c + 1));
|
||||
if (!tmp) {
|
||||
g_free(rval);
|
||||
rval = NULL;
|
||||
c = 0;
|
||||
break;
|
||||
} else {
|
||||
rval = tmp;
|
||||
}
|
||||
rval = g_renew(char *, rval, (c + 1));
|
||||
rval[c - 1] = p;
|
||||
rval[c] = NULL;
|
||||
}
|
||||
@ -1264,9 +1255,9 @@ static int multiwrite_f(BlockDriverState *bs, int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
reqs = g_malloc0(nr_reqs * sizeof(*reqs));
|
||||
buf = g_malloc0(nr_reqs * sizeof(*buf));
|
||||
qiovs = g_malloc(nr_reqs * sizeof(*qiovs));
|
||||
reqs = g_new0(BlockRequest, nr_reqs);
|
||||
buf = g_new0(char *, nr_reqs);
|
||||
qiovs = g_new(QEMUIOVector, nr_reqs);
|
||||
|
||||
for (i = 0; i < nr_reqs && optind < argc; i++) {
|
||||
int j;
|
||||
|
@ -356,7 +356,7 @@ static void command_loop(void)
|
||||
|
||||
static void add_user_command(char *optarg)
|
||||
{
|
||||
cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
|
||||
cmdline = g_renew(char *, cmdline, ++ncmdline);
|
||||
cmdline[ncmdline-1] = optarg;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ import subprocess
|
||||
import random
|
||||
import shutil
|
||||
from itertools import count
|
||||
import time
|
||||
import getopt
|
||||
import StringIO
|
||||
import resource
|
||||
@ -64,14 +65,35 @@ def run_app(fd, q_args):
|
||||
"""Start an application with specified arguments and return its exit code
|
||||
or kill signal depending on the result of execution.
|
||||
"""
|
||||
|
||||
class Alarm(Exception):
|
||||
"""Exception for signal.alarm events."""
|
||||
pass
|
||||
|
||||
def handler(*arg):
|
||||
"""Notify that an alarm event occurred."""
|
||||
raise Alarm
|
||||
|
||||
signal.signal(signal.SIGALRM, handler)
|
||||
signal.alarm(600)
|
||||
term_signal = signal.SIGKILL
|
||||
devnull = open('/dev/null', 'r+')
|
||||
process = subprocess.Popen(q_args, stdin=devnull,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
out, err = process.communicate()
|
||||
fd.write(out)
|
||||
fd.write(err)
|
||||
return process.returncode
|
||||
try:
|
||||
out, err = process.communicate()
|
||||
signal.alarm(0)
|
||||
fd.write(out)
|
||||
fd.write(err)
|
||||
fd.flush()
|
||||
return process.returncode
|
||||
|
||||
except Alarm:
|
||||
os.kill(process.pid, term_signal)
|
||||
fd.write('The command was terminated by timeout.\n')
|
||||
fd.flush()
|
||||
return -term_signal
|
||||
|
||||
|
||||
class TestException(Exception):
|
||||
@ -269,6 +291,7 @@ if __name__ == '__main__':
|
||||
|
||||
Optional arguments:
|
||||
-h, --help display this help and exit
|
||||
-d, --duration=NUMBER finish tests after NUMBER of seconds
|
||||
-c, --command=JSON run tests for all commands specified in
|
||||
the JSON array
|
||||
-s, --seed=STRING seed for a test image generation,
|
||||
@ -325,10 +348,15 @@ if __name__ == '__main__':
|
||||
finally:
|
||||
test.finish()
|
||||
|
||||
def should_continue(duration, start_time):
|
||||
"""Return True if a new test can be started and False otherwise."""
|
||||
current_time = int(time.time())
|
||||
return (duration is None) or (current_time - start_time < duration)
|
||||
|
||||
try:
|
||||
opts, args = getopt.gnu_getopt(sys.argv[1:], 'c:hs:kv',
|
||||
opts, args = getopt.gnu_getopt(sys.argv[1:], 'c:hs:kvd:',
|
||||
['command=', 'help', 'seed=', 'config=',
|
||||
'keep_passed', 'verbose'])
|
||||
'keep_passed', 'verbose', 'duration='])
|
||||
except getopt.error, e:
|
||||
print >>sys.stderr, \
|
||||
"Error: %s\n\nTry 'runner.py --help' for more information" % e
|
||||
@ -339,6 +367,8 @@ if __name__ == '__main__':
|
||||
log_all = False
|
||||
seed = None
|
||||
config = None
|
||||
duration = None
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt in ('-h', '--help'):
|
||||
usage()
|
||||
@ -357,6 +387,8 @@ if __name__ == '__main__':
|
||||
log_all = True
|
||||
elif opt in ('-s', '--seed'):
|
||||
seed = arg
|
||||
elif opt in ('-d', '--duration'):
|
||||
duration = int(arg)
|
||||
elif opt == '--config':
|
||||
try:
|
||||
config = json.loads(arg)
|
||||
@ -394,9 +426,11 @@ if __name__ == '__main__':
|
||||
resource.setrlimit(resource.RLIMIT_CORE, (-1, -1))
|
||||
# If a seed is specified, only one test will be executed.
|
||||
# Otherwise runner will terminate after a keyboard interruption
|
||||
for test_id in count(1):
|
||||
start_time = int(time.time())
|
||||
test_id = count(1)
|
||||
while should_continue(duration, start_time):
|
||||
try:
|
||||
run_test(str(test_id), seed, work_dir, run_log, cleanup,
|
||||
run_test(str(test_id.next()), seed, work_dir, run_log, cleanup,
|
||||
log_all, command, config)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
sys.exit(1)
|
||||
|
@ -113,6 +113,7 @@ QEMU_COMM_TIMEOUT=1
|
||||
# Silence output since it contains the disk image path and QEMU's readline
|
||||
# character echoing makes it very hard to filter the output
|
||||
_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)" >/dev/null
|
||||
_send_qemu_cmd $h "" "Formatting" | _filter_img_create
|
||||
qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
|
||||
_send_qemu_cmd $h 'quit' ""
|
||||
|
||||
|
@ -468,7 +468,8 @@ No errors were found on the image.
|
||||
|
||||
block-backup
|
||||
|
||||
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=4294968832 backing_file='TEST_DIR/t.qcow2.base' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off
|
||||
Formatting 'TEST_DIR/t.IMGFMT.copy', fmt=IMGFMT size=4294968832 backing_file='TEST_DIR/t.IMGFMT.base' backing_fmt='IMGFMT'
|
||||
(qemu)
|
||||
(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block-[K[D[D[D[D[D[D[D[D[D[D[Dinfo block-j[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jo[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-job[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jobs[K
|
||||
Type backup, device disk: Completed 0 of 4294968832 bytes, speed limit 0 bytes/s
|
||||
i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block-[K[D[D[D[D[D[D[D[D[D[D[Dinfo block-j[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jo[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-job[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jobs[K
|
||||
|
116
tests/qemu-iotests/099
Executable file
116
tests/qemu-iotests/099
Executable file
@ -0,0 +1,116 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Test valid filenames for blkdebug and blkverify representatively for
|
||||
# other protocols (such as NBD) when queried
|
||||
#
|
||||
# Copyright (C) 2014 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# creator
|
||||
owner=mreitz@redhat.com
|
||||
|
||||
seq="$(basename $0)"
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here="$PWD"
|
||||
tmp=/tmp/$$
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
# Basically all formats, but "raw" has issues with _filter_imgfmt regarding the
|
||||
# raw comparison image for blkverify; also, all images have to support creation
|
||||
_supported_fmt cow qcow qcow2 qed vdi vhdx vmdk vpc
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
|
||||
function do_run_qemu()
|
||||
{
|
||||
$QEMU -nographic -qmp stdio -serial none "$@"
|
||||
}
|
||||
|
||||
function run_qemu()
|
||||
{
|
||||
# Get the "file": "foo" entry ($foo may only contain escaped double quotes,
|
||||
# which is how we can extract it)
|
||||
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_imgfmt | _filter_qmp \
|
||||
| grep "drv0" \
|
||||
| sed -e 's/^.*"file": "\(\(\\"\|[^"]\)*\)".*$/\1/' -e 's/\\"/"/g'
|
||||
}
|
||||
|
||||
function test_qemu()
|
||||
{
|
||||
run_qemu -drive "if=none,id=drv0,$1" <<EOF
|
||||
{ 'execute': 'qmp_capabilities' }
|
||||
{ 'execute': 'query-block' }
|
||||
{ 'execute': 'quit' }
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
|
||||
IMG_SIZE=128K
|
||||
|
||||
_make_test_img $IMG_SIZE
|
||||
$QEMU_IMG create -f raw "$TEST_IMG.compare" $IMG_SIZE \
|
||||
| _filter_testdir | _filter_imgfmt
|
||||
|
||||
echo
|
||||
echo '=== Testing simple filename for blkverify ==='
|
||||
echo
|
||||
|
||||
# This should return simply the filename itself
|
||||
test_qemu "file=blkverify:$TEST_IMG.compare:$TEST_IMG"
|
||||
|
||||
echo
|
||||
echo '=== Testing filename reconstruction for blkverify ==='
|
||||
echo
|
||||
|
||||
# This should return the same filename as above
|
||||
test_qemu "file.driver=blkverify,file.raw.filename=$TEST_IMG.compare,file.test.file.filename=$TEST_IMG"
|
||||
|
||||
echo
|
||||
echo '=== Testing JSON filename for blkdebug ==='
|
||||
echo
|
||||
|
||||
# blkdebug cannot create a configuration file, therefore it is unable to
|
||||
# generate a plain filename here; thus this should return a JSON filename
|
||||
test_qemu "file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=l1_update"
|
||||
|
||||
echo
|
||||
echo '=== Testing indirectly enforced JSON filename ==='
|
||||
echo
|
||||
|
||||
# Because blkdebug cannot return a plain filename, blkverify is forced to
|
||||
# generate a JSON object here as well
|
||||
test_qemu "file.driver=blkverify,file.raw.filename=$TEST_IMG.compare,file.test.file.driver=blkdebug,file.test.file.image.filename=$TEST_IMG,file.test.file.inject-error.0.event=l1_update"
|
||||
|
||||
|
||||
rm -f "$TEST_IMG.compare"
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
20
tests/qemu-iotests/099.out
Normal file
20
tests/qemu-iotests/099.out
Normal file
@ -0,0 +1,20 @@
|
||||
QA output created by 099
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072
|
||||
Formatting 'TEST_DIR/t.IMGFMT.compare', fmt=raw size=131072
|
||||
|
||||
=== Testing simple filename for blkverify ===
|
||||
|
||||
blkverify:TEST_DIR/t.IMGFMT.compare:TEST_DIR/t.IMGFMT
|
||||
|
||||
=== Testing filename reconstruction for blkverify ===
|
||||
|
||||
blkverify:TEST_DIR/t.IMGFMT.compare:TEST_DIR/t.IMGFMT
|
||||
|
||||
=== Testing JSON filename for blkdebug ===
|
||||
|
||||
json:{"driver": "IMGFMT", "file": {"inject-error": [{"immediately": false, "once": false, "state": 0, "sector": -1, "event": "l1_update", "errno": 5}], "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug"}}
|
||||
|
||||
=== Testing indirectly enforced JSON filename ===
|
||||
|
||||
json:{"driver": "raw", "file": {"test": {"driver": "IMGFMT", "file": {"inject-error": [{"immediately": false, "once": false, "state": 0, "sector": -1, "event": "l1_update", "errno": 5}], "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug"}}, "driver": "blkverify", "raw": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.compare"}}}
|
||||
*** done
|
58
tests/qemu-iotests/101
Executable file
58
tests/qemu-iotests/101
Executable file
@ -0,0 +1,58 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Test short file I/O
|
||||
#
|
||||
# Copyright (C) 2014 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# creator
|
||||
owner=stefanha@redhat.com
|
||||
|
||||
seq=`basename $0`
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here=`pwd`
|
||||
tmp=/tmp/$$
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt raw
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
|
||||
echo
|
||||
echo "== creating short image file =="
|
||||
dd if=/dev/zero of="$TEST_IMG" bs=1 count=320
|
||||
|
||||
echo
|
||||
echo "== reading bytes beyond EOF gives zeroes =="
|
||||
$QEMU_IO -c "read -P 0 0 512" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
10
tests/qemu-iotests/101.out
Normal file
10
tests/qemu-iotests/101.out
Normal file
@ -0,0 +1,10 @@
|
||||
QA output created by 101
|
||||
|
||||
== creating short image file ==
|
||||
320+0 records in
|
||||
320+0 records out
|
||||
|
||||
== reading bytes beyond EOF gives zeroes ==
|
||||
read 512/512 bytes at offset 0
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
*** done
|
99
tests/qemu-iotests/103
Executable file
99
tests/qemu-iotests/103
Executable file
@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Test case for qcow2 metadata cache size specification
|
||||
#
|
||||
# Copyright (C) 2014 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# creator
|
||||
owner=mreitz@redhat.com
|
||||
|
||||
seq=$(basename $0)
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here=$PWD
|
||||
tmp=/tmp/$$
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
IMG_SIZE=64K
|
||||
|
||||
_make_test_img $IMG_SIZE
|
||||
$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo '=== Testing invalid option combinations ==='
|
||||
echo
|
||||
|
||||
# all sizes set at the same time
|
||||
$QEMU_IO -c "open -o cache-size=1.25M,l2-cache-size=1M,refcount-cache-size=0.25M $TEST_IMG" \
|
||||
2>&1 | _filter_testdir | _filter_imgfmt
|
||||
# l2-cache-size may not exceed cache-size
|
||||
$QEMU_IO -c "open -o cache-size=1M,l2-cache-size=2M $TEST_IMG" 2>&1 \
|
||||
| _filter_testdir | _filter_imgfmt
|
||||
# refcount-cache-size may not exceed cache-size
|
||||
$QEMU_IO -c "open -o cache-size=1M,refcount-cache-size=2M $TEST_IMG" 2>&1 \
|
||||
| _filter_testdir | _filter_imgfmt
|
||||
# 0 should be a valid size (e.g. for enforcing the minimum), so this should not
|
||||
# work
|
||||
$QEMU_IO -c "open -o cache-size=0,l2-cache-size=0,refcount-cache-size=0 $TEST_IMG" \
|
||||
2>&1 | _filter_testdir | _filter_imgfmt
|
||||
|
||||
echo
|
||||
echo '=== Testing valid option combinations ==='
|
||||
echo
|
||||
|
||||
# There should be a reasonable and working minimum
|
||||
$QEMU_IO -c "open -o cache-size=0 $TEST_IMG" -c 'read -P 42 0 64k' \
|
||||
| _filter_qemu_io
|
||||
$QEMU_IO -c "open -o l2-cache-size=0 $TEST_IMG" -c 'read -P 42 0 64k' \
|
||||
| _filter_qemu_io
|
||||
$QEMU_IO -c "open -o refcount-cache-size=0 $TEST_IMG" -c 'read -P 42 0 64k' \
|
||||
| _filter_qemu_io
|
||||
|
||||
# Derive cache sizes from combined size (with a reasonable ratio, but we cannot
|
||||
# test that)
|
||||
$QEMU_IO -c "open -o cache-size=2M $TEST_IMG" -c 'read -P 42 0 64k' \
|
||||
| _filter_qemu_io
|
||||
# Fix one cache, derive the other
|
||||
$QEMU_IO -c "open -o cache-size=2M,l2-cache-size=1M $TEST_IMG" \
|
||||
-c 'read -P 42 0 64k' \
|
||||
| _filter_qemu_io
|
||||
$QEMU_IO -c "open -o cache-size=2M,refcount-cache-size=1M $TEST_IMG" \
|
||||
-c 'read -P 42 0 64k' \
|
||||
| _filter_qemu_io
|
||||
# Directly set both caches
|
||||
$QEMU_IO -c "open -o l2-cache-size=1M,refcount-cache-size=0.25M $TEST_IMG" \
|
||||
-c 'read -P 42 0 64k' \
|
||||
| _filter_qemu_io
|
||||
|
||||
# success, all done
|
||||
echo '*** done'
|
||||
rm -f $seq.full
|
||||
status=0
|
29
tests/qemu-iotests/103.out
Normal file
29
tests/qemu-iotests/103.out
Normal file
@ -0,0 +1,29 @@
|
||||
QA output created by 103
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
=== Testing invalid option combinations ===
|
||||
|
||||
qemu-io: can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set the same time
|
||||
qemu-io: can't open device TEST_DIR/t.IMGFMT: l2-cache-size may not exceed cache-size
|
||||
qemu-io: can't open device TEST_DIR/t.IMGFMT: refcount-cache-size may not exceed cache-size
|
||||
qemu-io: can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set the same time
|
||||
|
||||
=== Testing valid option combinations ===
|
||||
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
*** done
|
@ -170,5 +170,27 @@ _filter_qmp()
|
||||
-e 's#^{"QMP":.*}$#QMP_VERSION#'
|
||||
}
|
||||
|
||||
# replace driver-specific options in the "Formatting..." line
|
||||
_filter_img_create()
|
||||
{
|
||||
sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
|
||||
-e "s#$TEST_DIR#TEST_DIR#g" \
|
||||
-e "s#$IMGFMT#IMGFMT#g" \
|
||||
-e "s# encryption=off##g" \
|
||||
-e "s# cluster_size=[0-9]\\+##g" \
|
||||
-e "s# table_size=[0-9]\\+##g" \
|
||||
-e "s# compat='[^']*'##g" \
|
||||
-e "s# compat6=\\(on\\|off\\)##g" \
|
||||
-e "s# static=\\(on\\|off\\)##g" \
|
||||
-e "s# zeroed_grain=\\(on\\|off\\)##g" \
|
||||
-e "s# subformat='[^']*'##g" \
|
||||
-e "s# adapter_type='[^']*'##g" \
|
||||
-e "s# lazy_refcounts=\\(on\\|off\\)##g" \
|
||||
-e "s# block_size=[0-9]\\+##g" \
|
||||
-e "s# block_state_zero=\\(on\\|off\\)##g" \
|
||||
-e "s# log_size=[0-9]\\+##g" \
|
||||
-e "s/archipelago:a/TEST_DIR\//g"
|
||||
}
|
||||
|
||||
# make sure this script returns success
|
||||
/bin/true
|
||||
|
@ -149,24 +149,7 @@ _make_test_img()
|
||||
else
|
||||
$QEMU_IMG create -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1
|
||||
fi
|
||||
) | \
|
||||
sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
|
||||
-e "s#$TEST_DIR#TEST_DIR#g" \
|
||||
-e "s#$IMGFMT#IMGFMT#g" \
|
||||
-e "s# encryption=off##g" \
|
||||
-e "s# cluster_size=[0-9]\\+##g" \
|
||||
-e "s# table_size=[0-9]\\+##g" \
|
||||
-e "s# compat='[^']*'##g" \
|
||||
-e "s# compat6=\\(on\\|off\\)##g" \
|
||||
-e "s# static=\\(on\\|off\\)##g" \
|
||||
-e "s# zeroed_grain=\\(on\\|off\\)##g" \
|
||||
-e "s# subformat='[^']*'##g" \
|
||||
-e "s# adapter_type='[^']*'##g" \
|
||||
-e "s# lazy_refcounts=\\(on\\|off\\)##g" \
|
||||
-e "s# block_size=[0-9]\\+##g" \
|
||||
-e "s# block_state_zero=\\(on\\|off\\)##g" \
|
||||
-e "s# log_size=[0-9]\\+##g" \
|
||||
-e "s/archipelago:a/TEST_DIR\//g"
|
||||
) | _filter_img_create
|
||||
|
||||
# Start an NBD server on the image file, which is what we'll be talking to
|
||||
if [ $IMGPROTO = "nbd" ]; then
|
||||
|
@ -100,3 +100,6 @@
|
||||
091 rw auto quick
|
||||
092 rw auto quick
|
||||
095 rw auto quick
|
||||
099 rw auto quick
|
||||
101 rw auto quick
|
||||
103 rw auto quick
|
||||
|
@ -311,6 +311,35 @@ static void perf_baseline(void)
|
||||
maxcycles, duration);
|
||||
}
|
||||
|
||||
static __attribute__((noinline)) void perf_cost_func(void *opaque)
|
||||
{
|
||||
qemu_coroutine_yield();
|
||||
}
|
||||
|
||||
static void perf_cost(void)
|
||||
{
|
||||
const unsigned long maxcycles = 40000000;
|
||||
unsigned long i = 0;
|
||||
double duration;
|
||||
unsigned long ops;
|
||||
Coroutine *co;
|
||||
|
||||
g_test_timer_start();
|
||||
while (i++ < maxcycles) {
|
||||
co = qemu_coroutine_create(perf_cost_func);
|
||||
qemu_coroutine_enter(co, &i);
|
||||
qemu_coroutine_enter(co, NULL);
|
||||
}
|
||||
duration = g_test_timer_elapsed();
|
||||
ops = (long)(maxcycles / (duration * 1000));
|
||||
|
||||
g_test_message("Run operation %lu iterations %f s, %luK operations/s, "
|
||||
"%luns per coroutine",
|
||||
maxcycles,
|
||||
duration, ops,
|
||||
(unsigned long)(1000000000 * duration) / maxcycles);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
@ -325,6 +354,7 @@ int main(int argc, char **argv)
|
||||
g_test_add_func("/perf/nesting", perf_nesting);
|
||||
g_test_add_func("/perf/yield", perf_yield);
|
||||
g_test_add_func("/perf/function-call", perf_baseline);
|
||||
g_test_add_func("/perf/cost", perf_cost);
|
||||
}
|
||||
return g_test_run();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user