Block layer patches

- Fix missing block_acct_setup() with -blockdev
 - Keep auto_backing_file post-migration
 - file-posix: Fixed O_DIRECT memory alignment
 - ide: Fix state after EXECUTE DEVICE DIAGNOSTIC and implement
   INITIALIZE DEVICE PARAMETERS
 - qemu-img: Wean documentation and help output off '?' for help
 - qcow2: fix memory leak and compiler warning
 - Code cleanups
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmM3Hm4RHGt3b2xmQHJl
 ZGhhdC5jb20ACgkQfwmycsiPL9ZhqA//WGN9tlx3Pf1D6SG3PtIG6/2DOJ6/gVNw
 R17BwoGTw36Nmt9xDzrHih753dcguLS19Kd6EySTg6j8mPogmFszquORMgGmcYcW
 0KtneRR7Y9XsamIGgentek1zsWajsP5muvZQF+hFJyZ24MZtWB+5Ucw2VuUTWnRl
 YaKP/tGMP5sC8nK3Npste/o7yh9Wgv4cv/mdKuyKoxjZhELeTTpHoTC2IZK9bV5I
 Bh19zjPRUPodm37nzONruUVzn53xKK3Qn26ZT5Hgx39HOdccPEu9N8wawQyqLr/x
 2whcn8kFfpFBLLxVbMYjwcWNo41SCn1itRcgV38PilBvG2UInUFK2QCmVgYxWluB
 9I5sRasfD3/BPPmw3n+j2TRJ+uvrLkkwXqIhAg+mAeiS0MccWUnLhJLW2S1Yai5L
 nkjkLmuV7KCLQTY39WvKBq0TPgj3QR0WJtEYHuUDtduvzKxAWd47Ff1tEPvFm5Ys
 RpmLSUQdPZiOkiwnV1qVg6a3gbIjUcT0Pai/Knc3iYrwCWLdNSCGoPkVemOg5wvN
 GxsQcKnfayQqIdZU6lBQehUjPamm3ffAEELeqLQXCbZe9lsbhNBXLJjVnA3cOu3f
 1PX6w+4MNeTg5ZekUJGS1fnYlq9CDOWGSv37+csB8dBhi6vQTc6YjABWU1IrB0S5
 1ihOYtc8fOo=
 =IIJz
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of git://repo.or.cz/qemu/kevin into staging

Block layer patches

- Fix missing block_acct_setup() with -blockdev
- Keep auto_backing_file post-migration
- file-posix: Fixed O_DIRECT memory alignment
- ide: Fix state after EXECUTE DEVICE DIAGNOSTIC and implement
  INITIALIZE DEVICE PARAMETERS
- qemu-img: Wean documentation and help output off '?' for help
- qcow2: fix memory leak and compiler warning
- Code cleanups

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmM3Hm4RHGt3b2xmQHJl
# ZGhhdC5jb20ACgkQfwmycsiPL9ZhqA//WGN9tlx3Pf1D6SG3PtIG6/2DOJ6/gVNw
# R17BwoGTw36Nmt9xDzrHih753dcguLS19Kd6EySTg6j8mPogmFszquORMgGmcYcW
# 0KtneRR7Y9XsamIGgentek1zsWajsP5muvZQF+hFJyZ24MZtWB+5Ucw2VuUTWnRl
# YaKP/tGMP5sC8nK3Npste/o7yh9Wgv4cv/mdKuyKoxjZhELeTTpHoTC2IZK9bV5I
# Bh19zjPRUPodm37nzONruUVzn53xKK3Qn26ZT5Hgx39HOdccPEu9N8wawQyqLr/x
# 2whcn8kFfpFBLLxVbMYjwcWNo41SCn1itRcgV38PilBvG2UInUFK2QCmVgYxWluB
# 9I5sRasfD3/BPPmw3n+j2TRJ+uvrLkkwXqIhAg+mAeiS0MccWUnLhJLW2S1Yai5L
# nkjkLmuV7KCLQTY39WvKBq0TPgj3QR0WJtEYHuUDtduvzKxAWd47Ff1tEPvFm5Ys
# RpmLSUQdPZiOkiwnV1qVg6a3gbIjUcT0Pai/Knc3iYrwCWLdNSCGoPkVemOg5wvN
# GxsQcKnfayQqIdZU6lBQehUjPamm3ffAEELeqLQXCbZe9lsbhNBXLJjVnA3cOu3f
# 1PX6w+4MNeTg5ZekUJGS1fnYlq9CDOWGSv37+csB8dBhi6vQTc6YjABWU1IrB0S5
# 1ihOYtc8fOo=
# =IIJz
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 30 Sep 2022 12:50:54 EDT
# gpg:                using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6
# gpg:                issuer "kwolf@redhat.com"
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* tag 'for-upstream' of git://repo.or.cz/qemu/kevin:
  hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command
  tests/qtest/ide-test: Verify that DIAGNOSTIC clears DEV to zero
  hw/ide/core: Clear LBA and drive bits for EXECUTE DEVICE DIAGNOSTIC
  tests/qtest/ide-test.c: Create disk image for use as a secondary
  piix_ide_reset: Use pci_set_* functions instead of direct access
  block: use the request length for iov alignment
  block: move bdrv_qiov_is_aligned to file-posix
  iotests/backing-file-invalidation: Add new test
  block/qed: Keep auto_backing_file if possible
  block/qcow2: Keep auto_backing_file if possible
  gluster: stop using .bdrv_needs_filename
  block: make serializing requests functions 'void'
  block: use bdrv_is_sg() helper instead of raw bs->sg reading
  block: add missed block_acct_setup with new block device init procedure
  block: pass OnOffAuto instead of bool to block_acct_setup()
  qemu-img: Wean documentation and help output off '?' for help
  block/qcow2-bitmap: Add missing cast to silent GCC error
  qcow2: fix memory leak in qcow2_read_extensions

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2022-10-03 15:06:07 -04:00
commit efbf38d73e
25 changed files with 447 additions and 101 deletions

View file

@ -38,13 +38,31 @@ void block_acct_init(BlockAcctStats *stats)
if (qtest_enabled()) { if (qtest_enabled()) {
clock_type = QEMU_CLOCK_VIRTUAL; clock_type = QEMU_CLOCK_VIRTUAL;
} }
stats->account_invalid = true;
stats->account_failed = true;
} }
void block_acct_setup(BlockAcctStats *stats, bool account_invalid, static bool bool_from_onoffauto(OnOffAuto val, bool def)
bool account_failed)
{ {
stats->account_invalid = account_invalid; switch (val) {
stats->account_failed = account_failed; case ON_OFF_AUTO_AUTO:
return def;
case ON_OFF_AUTO_ON:
return true;
case ON_OFF_AUTO_OFF:
return false;
default:
abort();
}
}
void block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid,
enum OnOffAuto account_failed)
{
stats->account_invalid = bool_from_onoffauto(account_invalid,
stats->account_invalid);
stats->account_failed = bool_from_onoffauto(account_failed,
stats->account_failed);
} }
void block_acct_cleanup(BlockAcctStats *stats) void block_acct_cleanup(BlockAcctStats *stats)

View file

@ -1295,7 +1295,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
} }
#endif #endif
if (bs->sg || S_ISBLK(st.st_mode)) { if (bdrv_is_sg(bs) || S_ISBLK(st.st_mode)) {
int ret = hdev_get_max_hw_transfer(s->fd, &st); int ret = hdev_get_max_hw_transfer(s->fd, &st);
if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) { if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) {
@ -2061,6 +2061,28 @@ static int coroutine_fn raw_thread_pool_submit(BlockDriverState *bs,
return thread_pool_submit_co(pool, func, arg); return thread_pool_submit_co(pool, func, arg);
} }
/*
* Check if all memory in this vector is sector aligned.
*/
static bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
{
int i;
size_t alignment = bdrv_min_mem_align(bs);
size_t len = bs->bl.request_alignment;
IO_CODE();
for (i = 0; i < qiov->niov; i++) {
if ((uintptr_t) qiov->iov[i].iov_base % alignment) {
return false;
}
if (qiov->iov[i].iov_len % len) {
return false;
}
}
return true;
}
static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset, static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov, int type) uint64_t bytes, QEMUIOVector *qiov, int type)
{ {

View file

@ -1555,7 +1555,6 @@ static BlockDriver bdrv_gluster = {
.format_name = "gluster", .format_name = "gluster",
.protocol_name = "gluster", .protocol_name = "gluster",
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_needs_filename = false,
.bdrv_file_open = qemu_gluster_open, .bdrv_file_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit, .bdrv_reopen_commit = qemu_gluster_reopen_commit,
@ -1585,7 +1584,6 @@ static BlockDriver bdrv_gluster_tcp = {
.format_name = "gluster", .format_name = "gluster",
.protocol_name = "gluster+tcp", .protocol_name = "gluster+tcp",
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_needs_filename = false,
.bdrv_file_open = qemu_gluster_open, .bdrv_file_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit, .bdrv_reopen_commit = qemu_gluster_reopen_commit,
@ -1615,7 +1613,6 @@ static BlockDriver bdrv_gluster_unix = {
.format_name = "gluster", .format_name = "gluster",
.protocol_name = "gluster+unix", .protocol_name = "gluster+unix",
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_needs_filename = true,
.bdrv_file_open = qemu_gluster_open, .bdrv_file_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit, .bdrv_reopen_commit = qemu_gluster_reopen_commit,
@ -1651,7 +1648,6 @@ static BlockDriver bdrv_gluster_rdma = {
.format_name = "gluster", .format_name = "gluster",
.protocol_name = "gluster+rdma", .protocol_name = "gluster+rdma",
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_needs_filename = true,
.bdrv_file_open = qemu_gluster_open, .bdrv_file_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit, .bdrv_reopen_commit = qemu_gluster_reopen_commit,

View file

@ -828,20 +828,16 @@ bdrv_find_conflicting_request(BdrvTrackedRequest *self)
} }
/* Called with self->bs->reqs_lock held */ /* Called with self->bs->reqs_lock held */
static bool coroutine_fn static void coroutine_fn
bdrv_wait_serialising_requests_locked(BdrvTrackedRequest *self) bdrv_wait_serialising_requests_locked(BdrvTrackedRequest *self)
{ {
BdrvTrackedRequest *req; BdrvTrackedRequest *req;
bool waited = false;
while ((req = bdrv_find_conflicting_request(self))) { while ((req = bdrv_find_conflicting_request(self))) {
self->waiting_for = req; self->waiting_for = req;
qemu_co_queue_wait(&req->wait_queue, &self->bs->reqs_lock); qemu_co_queue_wait(&req->wait_queue, &self->bs->reqs_lock);
self->waiting_for = NULL; self->waiting_for = NULL;
waited = true;
} }
return waited;
} }
/* Called with req->bs->reqs_lock held */ /* Called with req->bs->reqs_lock held */
@ -934,36 +930,31 @@ void bdrv_dec_in_flight(BlockDriverState *bs)
bdrv_wakeup(bs); bdrv_wakeup(bs);
} }
static bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self) static void coroutine_fn
bdrv_wait_serialising_requests(BdrvTrackedRequest *self)
{ {
BlockDriverState *bs = self->bs; BlockDriverState *bs = self->bs;
bool waited = false;
if (!qatomic_read(&bs->serialising_in_flight)) { if (!qatomic_read(&bs->serialising_in_flight)) {
return false; return;
} }
qemu_co_mutex_lock(&bs->reqs_lock); qemu_co_mutex_lock(&bs->reqs_lock);
waited = bdrv_wait_serialising_requests_locked(self); bdrv_wait_serialising_requests_locked(self);
qemu_co_mutex_unlock(&bs->reqs_lock); qemu_co_mutex_unlock(&bs->reqs_lock);
return waited;
} }
bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req, void coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req,
uint64_t align) uint64_t align)
{ {
bool waited;
IO_CODE(); IO_CODE();
qemu_co_mutex_lock(&req->bs->reqs_lock); qemu_co_mutex_lock(&req->bs->reqs_lock);
tracked_request_set_serialising(req, align); tracked_request_set_serialising(req, align);
waited = bdrv_wait_serialising_requests_locked(req); bdrv_wait_serialising_requests_locked(req);
qemu_co_mutex_unlock(&req->bs->reqs_lock); qemu_co_mutex_unlock(&req->bs->reqs_lock);
return waited;
} }
int bdrv_check_qiov_request(int64_t offset, int64_t bytes, int bdrv_check_qiov_request(int64_t offset, int64_t bytes,
@ -3236,27 +3227,6 @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
return mem; return mem;
} }
/*
* Check if all memory in this vector is sector aligned.
*/
bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
{
int i;
size_t alignment = bdrv_min_mem_align(bs);
IO_CODE();
for (i = 0; i < qiov->niov; i++) {
if ((uintptr_t) qiov->iov[i].iov_base % alignment) {
return false;
}
if (qiov->iov[i].iov_len % alignment) {
return false;
}
}
return true;
}
void bdrv_io_plug(BlockDriverState *bs) void bdrv_io_plug(BlockDriverState *bs)
{ {
BdrvChild *child; BdrvChild *child;

View file

@ -2065,7 +2065,7 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
uint64_t max_xfer_len = iscsilun->use_16_for_rw ? 0xffffffff : 0xffff; uint64_t max_xfer_len = iscsilun->use_16_for_rw ? 0xffffffff : 0xffff;
unsigned int block_size = MAX(BDRV_SECTOR_SIZE, iscsilun->block_size); unsigned int block_size = MAX(BDRV_SECTOR_SIZE, iscsilun->block_size);
assert(iscsilun->block_size >= BDRV_SECTOR_SIZE || bs->sg); assert(iscsilun->block_size >= BDRV_SECTOR_SIZE || bdrv_is_sg(bs));
bs->bl.request_alignment = block_size; bs->bl.request_alignment = block_size;

View file

@ -1208,7 +1208,7 @@ int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp)
} }
} }
g_slist_foreach(ro_dirty_bitmaps, set_readonly_helper, false); g_slist_foreach(ro_dirty_bitmaps, set_readonly_helper, (gpointer)false);
ret = 0; ret = 0;
out: out:

View file

@ -275,6 +275,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
if (ret < 0) { if (ret < 0) {
error_setg_errno(errp, -ret, "ERROR: ext_feature_table: " error_setg_errno(errp, -ret, "ERROR: ext_feature_table: "
"Could not read table"); "Could not read table");
g_free(feature_table);
return ret; return ret;
} }
@ -1696,16 +1697,27 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
s->image_backing_file = g_malloc(len + 1);
ret = bdrv_pread(bs->file, header.backing_file_offset, len, ret = bdrv_pread(bs->file, header.backing_file_offset, len,
bs->auto_backing_file, 0); s->image_backing_file, 0);
if (ret < 0) { if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read backing file name"); error_setg_errno(errp, -ret, "Could not read backing file name");
goto fail; goto fail;
} }
bs->auto_backing_file[len] = '\0'; s->image_backing_file[len] = '\0';
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
bs->auto_backing_file); /*
s->image_backing_file = g_strdup(bs->auto_backing_file); * Update only when something has changed. This function is called by
* qcow2_co_invalidate_cache(), and we do not want to reset
* auto_backing_file unless necessary.
*/
if (!g_str_equal(s->image_backing_file, bs->backing_file)) {
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
s->image_backing_file);
pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
s->image_backing_file);
}
} }
/* /*

View file

@ -445,6 +445,8 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
} }
if ((s->header.features & QED_F_BACKING_FILE)) { if ((s->header.features & QED_F_BACKING_FILE)) {
g_autofree char *backing_file_str = NULL;
if ((uint64_t)s->header.backing_filename_offset + if ((uint64_t)s->header.backing_filename_offset +
s->header.backing_filename_size > s->header.backing_filename_size >
s->header.cluster_size * s->header.header_size) { s->header.cluster_size * s->header.header_size) {
@ -452,16 +454,21 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
return -EINVAL; return -EINVAL;
} }
backing_file_str = g_malloc(sizeof(bs->backing_file));
ret = qed_read_string(bs->file, s->header.backing_filename_offset, ret = qed_read_string(bs->file, s->header.backing_filename_offset,
s->header.backing_filename_size, s->header.backing_filename_size,
bs->auto_backing_file, backing_file_str, sizeof(bs->backing_file));
sizeof(bs->auto_backing_file));
if (ret < 0) { if (ret < 0) {
error_setg(errp, "Failed to read backing filename"); error_setg(errp, "Failed to read backing filename");
return ret; return ret;
} }
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
bs->auto_backing_file); if (!g_str_equal(backing_file_str, bs->backing_file)) {
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
backing_file_str);
pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
backing_file_str);
}
if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) { if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {
pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw"); pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");

View file

@ -463,7 +463,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
return -EINVAL; return -EINVAL;
} }
bs->sg = bs->file->bs->sg; bs->sg = bdrv_is_sg(bs->file->bs);
bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
(BDRV_REQ_FUA & bs->file->bs->supported_write_flags); (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
@ -489,7 +489,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
return ret; return ret;
} }
if (bs->sg && (s->offset || s->has_size)) { if (bdrv_is_sg(bs) && (s->offset || s->has_size)) {
error_setg(errp, "Cannot use offset/size with SCSI generic devices"); error_setg(errp, "Cannot use offset/size with SCSI generic devices");
return -EINVAL; return -EINVAL;
} }

View file

@ -455,6 +455,17 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
} }
} }
static OnOffAuto account_get_opt(QemuOpts *opts, const char *name)
{
if (!qemu_opt_find(opts, name)) {
return ON_OFF_AUTO_AUTO;
}
if (qemu_opt_get_bool(opts, name, true)) {
return ON_OFF_AUTO_ON;
}
return ON_OFF_AUTO_OFF;
}
/* Takes the ownership of bs_opts */ /* Takes the ownership of bs_opts */
static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
Error **errp) Error **errp)
@ -462,7 +473,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
const char *buf; const char *buf;
int bdrv_flags = 0; int bdrv_flags = 0;
int on_read_error, on_write_error; int on_read_error, on_write_error;
bool account_invalid, account_failed; OnOffAuto account_invalid, account_failed;
bool writethrough, read_only; bool writethrough, read_only;
BlockBackend *blk; BlockBackend *blk;
BlockDriverState *bs; BlockDriverState *bs;
@ -496,8 +507,8 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
/* extract parameters */ /* extract parameters */
snapshot = qemu_opt_get_bool(opts, "snapshot", 0); snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
account_invalid = qemu_opt_get_bool(opts, "stats-account-invalid", true); account_invalid = account_get_opt(opts, "stats-account-invalid");
account_failed = qemu_opt_get_bool(opts, "stats-account-failed", true); account_failed = account_get_opt(opts, "stats-account-failed");
writethrough = !qemu_opt_get_bool(opts, BDRV_OPT_CACHE_WB, true); writethrough = !qemu_opt_get_bool(opts, BDRV_OPT_CACHE_WB, true);

View file

@ -57,7 +57,7 @@ cases. See below for a description of the supported disk formats.
*OUTPUT_FMT* is the destination format. *OUTPUT_FMT* is the destination format.
*OPTIONS* is a comma separated list of format specific options in a *OPTIONS* is a comma separated list of format specific options in a
name=value format. Use ``-o ?`` for an overview of the options supported name=value format. Use ``-o help`` for an overview of the options supported
by the used format or see the format descriptions below for details. by the used format or see the format descriptions below for details.
*SNAPSHOT_PARAM* is param used for internal snapshot, format is *SNAPSHOT_PARAM* is param used for internal snapshot, format is

View file

@ -205,6 +205,8 @@ bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
blk_set_enable_write_cache(blk, wce); blk_set_enable_write_cache(blk, wce);
blk_set_on_error(blk, rerror, werror); blk_set_on_error(blk, rerror, werror);
block_acct_setup(blk_get_stats(blk), conf->account_invalid,
conf->account_failed);
return true; return true;
} }

View file

@ -1340,6 +1340,11 @@ static void ide_reset(IDEState *s)
s->pio_aiocb = NULL; s->pio_aiocb = NULL;
} }
if (s->reset_reverts) {
s->reset_reverts = false;
s->heads = s->drive_heads;
s->sectors = s->drive_sectors;
}
if (s->drive_kind == IDE_CFATA) if (s->drive_kind == IDE_CFATA)
s->mult_sectors = 0; s->mult_sectors = 0;
else else
@ -1618,6 +1623,20 @@ static bool cmd_check_power_mode(IDEState *s, uint8_t cmd)
return true; return true;
} }
/* INITIALIZE DEVICE PARAMETERS */
static bool cmd_specify(IDEState *s, uint8_t cmd)
{
if (s->blk && s->drive_kind != IDE_CD) {
s->heads = (s->select & (ATA_DEV_HS)) + 1;
s->sectors = s->nsector;
ide_set_irq(s->bus);
} else {
ide_abort_command(s);
}
return true;
}
static bool cmd_set_features(IDEState *s, uint8_t cmd) static bool cmd_set_features(IDEState *s, uint8_t cmd)
{ {
uint16_t *identify_data; uint16_t *identify_data;
@ -1641,7 +1660,11 @@ static bool cmd_set_features(IDEState *s, uint8_t cmd)
ide_flush_cache(s); ide_flush_cache(s);
return false; return false;
case 0xcc: /* reverting to power-on defaults enable */ case 0xcc: /* reverting to power-on defaults enable */
s->reset_reverts = true;
return true;
case 0x66: /* reverting to power-on defaults disable */ case 0x66: /* reverting to power-on defaults disable */
s->reset_reverts = false;
return true;
case 0xaa: /* read look-ahead enable */ case 0xaa: /* read look-ahead enable */
case 0x55: /* read look-ahead disable */ case 0x55: /* read look-ahead disable */
case 0x05: /* set advanced power management mode */ case 0x05: /* set advanced power management mode */
@ -1704,8 +1727,14 @@ static bool cmd_identify_packet(IDEState *s, uint8_t cmd)
return false; return false;
} }
/* EXECUTE DEVICE DIAGNOSTIC */
static bool cmd_exec_dev_diagnostic(IDEState *s, uint8_t cmd) static bool cmd_exec_dev_diagnostic(IDEState *s, uint8_t cmd)
{ {
/*
* Clear the device register per the ATA (v6) specification,
* because ide_set_signature does not clear LBA or drive bits.
*/
s->select = (ATA_DEV_ALWAYS_ON);
ide_set_signature(s); ide_set_signature(s);
if (s->drive_kind == IDE_CD) { if (s->drive_kind == IDE_CD) {
@ -2045,7 +2074,7 @@ static const struct {
[WIN_SEEK] = { cmd_seek, HD_CFA_OK | SET_DSC }, [WIN_SEEK] = { cmd_seek, HD_CFA_OK | SET_DSC },
[CFA_TRANSLATE_SECTOR] = { cmd_cfa_translate_sector, CFA_OK }, [CFA_TRANSLATE_SECTOR] = { cmd_cfa_translate_sector, CFA_OK },
[WIN_DIAGNOSE] = { cmd_exec_dev_diagnostic, ALL_OK }, [WIN_DIAGNOSE] = { cmd_exec_dev_diagnostic, ALL_OK },
[WIN_SPECIFY] = { cmd_nop, HD_CFA_OK | SET_DSC }, [WIN_SPECIFY] = { cmd_specify, HD_CFA_OK | SET_DSC },
[WIN_STANDBYNOW2] = { cmd_nop, HD_CFA_OK }, [WIN_STANDBYNOW2] = { cmd_nop, HD_CFA_OK },
[WIN_IDLEIMMEDIATE2] = { cmd_nop, HD_CFA_OK }, [WIN_IDLEIMMEDIATE2] = { cmd_nop, HD_CFA_OK },
[WIN_STANDBY2] = { cmd_nop, HD_CFA_OK }, [WIN_STANDBY2] = { cmd_nop, HD_CFA_OK },
@ -2535,8 +2564,8 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
blk_get_geometry(blk, &nb_sectors); blk_get_geometry(blk, &nb_sectors);
s->cylinders = cylinders; s->cylinders = cylinders;
s->heads = heads; s->heads = s->drive_heads = heads;
s->sectors = secs; s->sectors = s->drive_sectors = secs;
s->chs_trans = chs_trans; s->chs_trans = chs_trans;
s->nb_sectors = nb_sectors; s->nb_sectors = nb_sectors;
s->wwn = wwn; s->wwn = wwn;

View file

@ -21,6 +21,10 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*
* References:
* [1] 82371FB (PIIX) AND 82371SB (PIIX3) PCI ISA IDE XCELERATOR,
* 290550-002, Intel Corporation, April 1997.
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
@ -114,14 +118,11 @@ static void piix_ide_reset(DeviceState *dev)
ide_bus_reset(&d->bus[i]); ide_bus_reset(&d->bus[i]);
} }
/* TODO: this is the default. do not override. */ /* PCI command register default value (0000h) per [1, p.48]. */
pci_conf[PCI_COMMAND] = 0x00; pci_set_word(pci_conf + PCI_COMMAND, 0x0000);
/* TODO: this is the default. do not override. */ pci_set_word(pci_conf + PCI_STATUS,
pci_conf[PCI_COMMAND + 1] = 0x00; PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_FAST_BACK);
/* TODO: use pci_set_word */ pci_set_byte(pci_conf + 0x20, 0x01); /* BMIBA: 20-23h */
pci_conf[PCI_STATUS] = PCI_STATUS_FAST_BACK;
pci_conf[PCI_STATUS + 1] = PCI_STATUS_DEVSEL_MEDIUM >> 8;
pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */
} }
static int pci_piix_init_ports(PCIIDEState *d) static int pci_piix_init_ports(PCIIDEState *d)

View file

@ -27,7 +27,7 @@
#include "qemu/timed-average.h" #include "qemu/timed-average.h"
#include "qemu/thread.h" #include "qemu/thread.h"
#include "qapi/qapi-builtin-types.h" #include "qapi/qapi-types-common.h"
typedef struct BlockAcctTimedStats BlockAcctTimedStats; typedef struct BlockAcctTimedStats BlockAcctTimedStats;
typedef struct BlockAcctStats BlockAcctStats; typedef struct BlockAcctStats BlockAcctStats;
@ -100,8 +100,8 @@ typedef struct BlockAcctCookie {
} BlockAcctCookie; } BlockAcctCookie;
void block_acct_init(BlockAcctStats *stats); void block_acct_init(BlockAcctStats *stats);
void block_acct_setup(BlockAcctStats *stats, bool account_invalid, void block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid,
bool account_failed); enum OnOffAuto account_failed);
void block_acct_cleanup(BlockAcctStats *stats); void block_acct_cleanup(BlockAcctStats *stats);
void block_acct_add_interval(BlockAcctStats *stats, unsigned interval_length); void block_acct_add_interval(BlockAcctStats *stats, unsigned interval_length);
BlockAcctTimedStats *block_acct_interval_next(BlockAcctStats *stats, BlockAcctTimedStats *block_acct_interval_next(BlockAcctStats *stats,

View file

@ -150,7 +150,6 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size);
void *qemu_blockalign0(BlockDriverState *bs, size_t size); void *qemu_blockalign0(BlockDriverState *bs, size_t size);
void *qemu_try_blockalign(BlockDriverState *bs, size_t size); void *qemu_try_blockalign(BlockDriverState *bs, size_t size);
void *qemu_try_blockalign0(BlockDriverState *bs, size_t size); void *qemu_try_blockalign0(BlockDriverState *bs, size_t size);
bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov);
void bdrv_enable_copy_on_read(BlockDriverState *bs); void bdrv_enable_copy_on_read(BlockDriverState *bs);
void bdrv_disable_copy_on_read(BlockDriverState *bs); void bdrv_disable_copy_on_read(BlockDriverState *bs);

View file

@ -73,7 +73,7 @@ static inline int coroutine_fn bdrv_co_pwrite(BdrvChild *child,
return bdrv_co_pwritev(child, offset, bytes, &qiov, flags); return bdrv_co_pwritev(child, offset, bytes, &qiov, flags);
} }
bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req, void coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req,
uint64_t align); uint64_t align);
BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs); BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs);

View file

@ -31,6 +31,7 @@ typedef struct BlockConf {
uint32_t lcyls, lheads, lsecs; uint32_t lcyls, lheads, lsecs;
OnOffAuto wce; OnOffAuto wce;
bool share_rw; bool share_rw;
OnOffAuto account_invalid, account_failed;
BlockdevOnError rerror; BlockdevOnError rerror;
BlockdevOnError werror; BlockdevOnError werror;
} BlockConf; } BlockConf;
@ -61,7 +62,11 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
_conf.discard_granularity, -1), \ _conf.discard_granularity, -1), \
DEFINE_PROP_ON_OFF_AUTO("write-cache", _state, _conf.wce, \ DEFINE_PROP_ON_OFF_AUTO("write-cache", _state, _conf.wce, \
ON_OFF_AUTO_AUTO), \ ON_OFF_AUTO_AUTO), \
DEFINE_PROP_BOOL("share-rw", _state, _conf.share_rw, false) DEFINE_PROP_BOOL("share-rw", _state, _conf.share_rw, false), \
DEFINE_PROP_ON_OFF_AUTO("account-invalid", _state, \
_conf.account_invalid, ON_OFF_AUTO_AUTO), \
DEFINE_PROP_ON_OFF_AUTO("account-failed", _state, \
_conf.account_failed, ON_OFF_AUTO_AUTO)
#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ #define DEFINE_BLOCK_PROPERTIES(_state, _conf) \
DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \ DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \

View file

@ -375,6 +375,7 @@ struct IDEState {
uint8_t unit; uint8_t unit;
/* ide config */ /* ide config */
IDEDriveKind drive_kind; IDEDriveKind drive_kind;
int drive_heads, drive_sectors;
int cylinders, heads, sectors, chs_trans; int cylinders, heads, sectors, chs_trans;
int64_t nb_sectors; int64_t nb_sectors;
int mult_sectors; int mult_sectors;
@ -401,6 +402,8 @@ struct IDEState {
uint8_t select; uint8_t select;
uint8_t status; uint8_t status;
bool reset_reverts;
/* set for lba48 access */ /* set for lba48 access */
uint8_t lba48; uint8_t lba48;
BlockBackend *blk; BlockBackend *blk;

View file

@ -164,8 +164,8 @@ void help(void)
" 'output_filename' is the destination disk image filename\n" " 'output_filename' is the destination disk image filename\n"
" 'output_fmt' is the destination format\n" " 'output_fmt' is the destination format\n"
" 'options' is a comma separated list of format specific options in a\n" " 'options' is a comma separated list of format specific options in a\n"
" name=value format. Use -o ? for an overview of the options supported by the\n" " name=value format. Use -o help for an overview of the options supported by\n"
" used format\n" " the used format\n"
" 'snapshot_param' is param used for internal snapshot, format\n" " 'snapshot_param' is param used for internal snapshot, format\n"
" is 'snapshot.id=[ID],snapshot.name=[NAME]', or\n" " is 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
" '[ID_OR_NAME]'\n" " '[ID_OR_NAME]'\n"

View file

@ -28,6 +28,8 @@ Testing:
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "288" drive-type = "288"
@ -55,6 +57,8 @@ Testing: -fda TEST_DIR/t.qcow2
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -92,6 +96,8 @@ Testing: -fdb TEST_DIR/t.qcow2
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 0 (0x0) unit = 0 (0x0)
@ -104,6 +110,8 @@ Testing: -fdb TEST_DIR/t.qcow2
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "288" drive-type = "288"
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -145,6 +153,8 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 0 (0x0) unit = 0 (0x0)
@ -157,6 +167,8 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -199,6 +211,8 @@ Testing: -fdb
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "288" drive-type = "288"
dev: floppy, id "" dev: floppy, id ""
unit = 0 (0x0) unit = 0 (0x0)
@ -211,6 +225,8 @@ Testing: -fdb
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "288" drive-type = "288"
@ -238,6 +254,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -275,6 +293,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 0 (0x0) unit = 0 (0x0)
@ -287,6 +307,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "288" drive-type = "288"
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -328,6 +350,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 0 (0x0) unit = 0 (0x0)
@ -340,6 +364,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -385,6 +411,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/peripheral-anon/device[N] Attached to: /machine/peripheral-anon/device[N]
@ -422,6 +450,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/peripheral-anon/device[N] Attached to: /machine/peripheral-anon/device[N]
@ -459,6 +489,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 0 (0x0) unit = 0 (0x0)
@ -471,6 +503,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/peripheral-anon/device[N] Attached to: /machine/peripheral-anon/device[N]
@ -522,6 +556,8 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 0 (0x0) unit = 0 (0x0)
@ -534,6 +570,8 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -576,6 +614,8 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 0 (0x0) unit = 0 (0x0)
@ -588,6 +628,8 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -630,6 +672,8 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 1 (0x1) unit = 1 (0x1)
@ -642,6 +686,8 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -684,6 +730,8 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 1 (0x1) unit = 1 (0x1)
@ -696,6 +744,8 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -747,6 +797,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 0 (0x0) unit = 0 (0x0)
@ -759,6 +811,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -801,6 +855,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
dev: floppy, id "" dev: floppy, id ""
unit = 0 (0x0) unit = 0 (0x0)
@ -813,6 +869,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/unattached/device[N] Attached to: /machine/unattached/device[N]
@ -861,6 +919,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global floppy.drive=none0 -device
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/peripheral-anon/device[N] Attached to: /machine/peripheral-anon/device[N]
@ -928,6 +988,8 @@ Testing: -device floppy
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "288" drive-type = "288"
Testing: -device floppy,drive-type=120 Testing: -device floppy,drive-type=120
@ -952,6 +1014,8 @@ Testing: -device floppy,drive-type=120
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "120" drive-type = "120"
Testing: -device floppy,drive-type=144 Testing: -device floppy,drive-type=144
@ -976,6 +1040,8 @@ Testing: -device floppy,drive-type=144
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
Testing: -device floppy,drive-type=288 Testing: -device floppy,drive-type=288
@ -1000,6 +1066,8 @@ Testing: -device floppy,drive-type=288
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "288" drive-type = "288"
@ -1027,6 +1095,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "120" drive-type = "120"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/peripheral-anon/device[N] Attached to: /machine/peripheral-anon/device[N]
@ -1064,6 +1134,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "288" drive-type = "288"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/peripheral-anon/device[N] Attached to: /machine/peripheral-anon/device[N]
@ -1104,6 +1176,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/peripheral-anon/device[N] Attached to: /machine/peripheral-anon/device[N]
@ -1141,6 +1215,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica
discard_granularity = 4294967295 (4 GiB) discard_granularity = 4294967295 (4 GiB)
write-cache = "auto" write-cache = "auto"
share-rw = false share-rw = false
account-invalid = "auto"
account-failed = "auto"
drive-type = "144" drive-type = "144"
none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Attached to: /machine/peripheral-anon/device[N] Attached to: /machine/peripheral-anon/device[N]

View file

@ -188,7 +188,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b
], ],
"failed_unmap_operations": 0, "failed_unmap_operations": 0,
"failed_flush_operations": 0, "failed_flush_operations": 0,
"account_invalid": false, "account_invalid": true,
"rd_total_time_ns": 0, "rd_total_time_ns": 0,
"invalid_unmap_operations": 0, "invalid_unmap_operations": 0,
"flush_operations": 0, "flush_operations": 0,
@ -198,7 +198,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b
"rd_bytes": 0, "rd_bytes": 0,
"unmap_total_time_ns": 0, "unmap_total_time_ns": 0,
"invalid_flush_operations": 0, "invalid_flush_operations": 0,
"account_failed": false, "account_failed": true,
"rd_operations": 0, "rd_operations": 0,
"invalid_wr_operations": 0, "invalid_wr_operations": 0,
"invalid_rd_operations": 0 "invalid_rd_operations": 0

View file

@ -0,0 +1,152 @@
#!/usr/bin/env python3
# group: rw migration
#
# Migrate a VM with a BDS with backing nodes, which runs
# bdrv_invalidate_cache(), which for qcow2 and qed triggers reading the
# backing file string from the image header. Check whether this
# interferes with bdrv_backing_overridden().
#
# Copyright (C) 2022 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/>.
#
import json
import os
from typing import Optional
import iotests
from iotests import qemu_img_create, qemu_img_info
image_size = 1 * 1024 * 1024
imgs = [os.path.join(iotests.test_dir, f'{i}.img') for i in range(0, 4)]
mig_sock = os.path.join(iotests.sock_dir, 'mig.sock')
class TestPostMigrateFilename(iotests.QMPTestCase):
vm_s: Optional[iotests.VM] = None
vm_d: Optional[iotests.VM] = None
def setUp(self) -> None:
# Create backing chain of three images, where the backing file strings
# are json:{} filenames
qemu_img_create('-f', iotests.imgfmt, imgs[0], str(image_size))
for i in range(1, 3):
backing = {
'driver': iotests.imgfmt,
'file': {
'driver': 'file',
'filename': imgs[i - 1]
}
}
qemu_img_create('-f', iotests.imgfmt, '-F', iotests.imgfmt,
'-b', 'json:' + json.dumps(backing),
imgs[i], str(image_size))
def tearDown(self) -> None:
if self.vm_s is not None:
self.vm_s.shutdown()
if self.vm_d is not None:
self.vm_d.shutdown()
for img in imgs:
try:
os.remove(img)
except OSError:
pass
try:
os.remove(mig_sock)
except OSError:
pass
def test_migration(self) -> None:
"""
Migrate a VM with the backing chain created in setUp() attached. At
the end of the migration process, the destination will run
bdrv_invalidate_cache(), which for some image formats (qcow2 and qed)
means the backing file string is re-read from the image header. If
this overwrites bs->auto_backing_file, doing so may cause
bdrv_backing_overridden() to become true: The image header reports a
json:{} filename, but when opening it, bdrv_refresh_filename() will
simplify it to a plain simple filename; and when bs->auto_backing_file
and bs->backing->bs->filename differ, bdrv_backing_overridden() becomes
true.
If bdrv_backing_overridden() is true, the BDS will be forced to get a
json:{} filename, which in general is not the end of the world, but not
great. Check whether that happens, i.e. whether migration changes the
node's filename.
"""
blockdev = {
'node-name': 'node0',
'driver': iotests.imgfmt,
'file': {
'driver': 'file',
'filename': imgs[2]
}
}
self.vm_s = iotests.VM(path_suffix='a') \
.add_blockdev(json.dumps(blockdev))
self.vm_d = iotests.VM(path_suffix='b') \
.add_blockdev(json.dumps(blockdev)) \
.add_incoming(f'unix:{mig_sock}')
assert self.vm_s is not None
assert self.vm_d is not None
self.vm_s.launch()
self.vm_d.launch()
pre_mig_filename = self.vm_s.node_info('node0')['file']
self.vm_s.qmp('migrate', uri=f'unix:{mig_sock}')
# Wait for migration to be done
self.vm_s.event_wait('STOP')
self.vm_d.event_wait('RESUME')
post_mig_filename = self.vm_d.node_info('node0')['file']
# Verify that the filename hasn't changed from before the migration
self.assertEqual(pre_mig_filename, post_mig_filename)
self.vm_s.shutdown()
self.vm_s = None
# For good measure, try creating an overlay and check its backing
# chain below. This is how the issue was originally found.
result = self.vm_d.qmp('blockdev-snapshot-sync',
format=iotests.imgfmt,
snapshot_file=imgs[3],
node_name='node0',
snapshot_node_name='node0-overlay')
self.assert_qmp(result, 'return', {})
self.vm_d.shutdown()
self.vm_d = None
# Check the newly created overlay's backing chain
chain = qemu_img_info('--backing-chain', imgs[3])
for index, image in enumerate(chain):
self.assertEqual(image['filename'], imgs[3 - index])
if __name__ == '__main__':
# These are the image formats that run their open() function from their
# .bdrv_co_invaliate_cache() implementations, so test them
iotests.main(supported_fmts=['qcow2', 'qed'],
supported_protocols=['file'])

View file

@ -0,0 +1,5 @@
.
----------------------------------------------------------------------
Ran 1 tests
OK

View file

@ -90,6 +90,7 @@ enum {
enum { enum {
CMD_DSM = 0x06, CMD_DSM = 0x06,
CMD_DIAGNOSE = 0x90,
CMD_READ_DMA = 0xc8, CMD_READ_DMA = 0xc8,
CMD_WRITE_DMA = 0xca, CMD_WRITE_DMA = 0xca,
CMD_FLUSH_CACHE = 0xe7, CMD_FLUSH_CACHE = 0xe7,
@ -121,7 +122,7 @@ enum {
static QPCIBus *pcibus = NULL; static QPCIBus *pcibus = NULL;
static QGuestAllocator guest_malloc; static QGuestAllocator guest_malloc;
static char *tmp_path; static char *tmp_path[2];
static char *debug_path; static char *debug_path;
static QTestState *ide_test_start(const char *cmdline_fmt, ...) static QTestState *ide_test_start(const char *cmdline_fmt, ...)
@ -310,7 +311,7 @@ static QTestState *test_bmdma_setup(void)
qts = ide_test_start( qts = ide_test_start(
"-drive file=%s,if=ide,cache=writeback,format=raw " "-drive file=%s,if=ide,cache=writeback,format=raw "
"-global ide-hd.serial=%s -global ide-hd.ver=%s", "-global ide-hd.serial=%s -global ide-hd.ver=%s",
tmp_path, "testdisk", "version"); tmp_path[0], "testdisk", "version");
qtest_irq_intercept_in(qts, "ioapic"); qtest_irq_intercept_in(qts, "ioapic");
return qts; return qts;
@ -574,7 +575,7 @@ static void test_identify(void)
qts = ide_test_start( qts = ide_test_start(
"-drive file=%s,if=ide,cache=writeback,format=raw " "-drive file=%s,if=ide,cache=writeback,format=raw "
"-global ide-hd.serial=%s -global ide-hd.ver=%s", "-global ide-hd.serial=%s -global ide-hd.ver=%s",
tmp_path, "testdisk", "version"); tmp_path[0], "testdisk", "version");
dev = get_pci_device(qts, &bmdma_bar, &ide_bar); dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
@ -614,6 +615,36 @@ static void test_identify(void)
free_pci_device(dev); free_pci_device(dev);
} }
static void test_diagnostic(void)
{
QTestState *qts;
QPCIDevice *dev;
QPCIBar bmdma_bar, ide_bar;
uint8_t data;
qts = ide_test_start(
"-blockdev driver=file,node-name=hda,filename=%s "
"-blockdev driver=file,node-name=hdb,filename=%s "
"-device ide-hd,drive=hda,bus=ide.0,unit=0 "
"-device ide-hd,drive=hdb,bus=ide.0,unit=1 ",
tmp_path[0], tmp_path[1]);
dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
/* DIAGNOSE command on device 1 */
qpci_io_writeb(dev, ide_bar, reg_device, DEV);
data = qpci_io_readb(dev, ide_bar, reg_device);
g_assert_cmphex(data & DEV, ==, DEV);
qpci_io_writeb(dev, ide_bar, reg_command, CMD_DIAGNOSE);
/* Verify that DEVICE is now 0 */
data = qpci_io_readb(dev, ide_bar, reg_device);
g_assert_cmphex(data & DEV, ==, 0);
ide_test_quit(qts);
free_pci_device(dev);
}
/* /*
* Write sector 1 with random data to make IDE storage dirty * Write sector 1 with random data to make IDE storage dirty
* Needed for flush tests so that flushes actually go though the block layer * Needed for flush tests so that flushes actually go though the block layer
@ -662,7 +693,7 @@ static void test_flush(void)
qts = ide_test_start( qts = ide_test_start(
"-drive file=blkdebug::%s,if=ide,cache=writeback,format=raw", "-drive file=blkdebug::%s,if=ide,cache=writeback,format=raw",
tmp_path); tmp_path[0]);
dev = get_pci_device(qts, &bmdma_bar, &ide_bar); dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
@ -713,7 +744,7 @@ static void test_pci_retry_flush(void)
qts = ide_test_start( qts = ide_test_start(
"-drive file=blkdebug:%s:%s,if=ide,cache=writeback,format=raw," "-drive file=blkdebug:%s:%s,if=ide,cache=writeback,format=raw,"
"rerror=stop,werror=stop", "rerror=stop,werror=stop",
debug_path, tmp_path); debug_path, tmp_path[0]);
dev = get_pci_device(qts, &bmdma_bar, &ide_bar); dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
@ -892,14 +923,14 @@ static void cdrom_pio_impl(int nblocks)
/* Prepopulate the CDROM with an interesting pattern */ /* Prepopulate the CDROM with an interesting pattern */
generate_pattern(pattern, patt_len, ATAPI_BLOCK_SIZE); generate_pattern(pattern, patt_len, ATAPI_BLOCK_SIZE);
fh = fopen(tmp_path, "wb+"); fh = fopen(tmp_path[0], "wb+");
ret = fwrite(pattern, ATAPI_BLOCK_SIZE, patt_blocks, fh); ret = fwrite(pattern, ATAPI_BLOCK_SIZE, patt_blocks, fh);
g_assert_cmpint(ret, ==, patt_blocks); g_assert_cmpint(ret, ==, patt_blocks);
fclose(fh); fclose(fh);
qts = ide_test_start( qts = ide_test_start(
"-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 " "-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 "
"-device ide-cd,drive=sr0,bus=ide.0", tmp_path); "-device ide-cd,drive=sr0,bus=ide.0", tmp_path[0]);
dev = get_pci_device(qts, &bmdma_bar, &ide_bar); dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
qtest_irq_intercept_in(qts, "ioapic"); qtest_irq_intercept_in(qts, "ioapic");
@ -985,7 +1016,7 @@ static void test_cdrom_dma(void)
qts = ide_test_start( qts = ide_test_start(
"-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 " "-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 "
"-device ide-cd,drive=sr0,bus=ide.0", tmp_path); "-device ide-cd,drive=sr0,bus=ide.0", tmp_path[0]);
qtest_irq_intercept_in(qts, "ioapic"); qtest_irq_intercept_in(qts, "ioapic");
guest_buf = guest_alloc(&guest_malloc, len); guest_buf = guest_alloc(&guest_malloc, len);
@ -993,7 +1024,7 @@ static void test_cdrom_dma(void)
prdt[0].size = cpu_to_le32(len | PRDT_EOT); prdt[0].size = cpu_to_le32(len | PRDT_EOT);
generate_pattern(pattern, ATAPI_BLOCK_SIZE * 16, ATAPI_BLOCK_SIZE); generate_pattern(pattern, ATAPI_BLOCK_SIZE * 16, ATAPI_BLOCK_SIZE);
fh = fopen(tmp_path, "wb+"); fh = fopen(tmp_path[0], "wb+");
ret = fwrite(pattern, ATAPI_BLOCK_SIZE, 16, fh); ret = fwrite(pattern, ATAPI_BLOCK_SIZE, 16, fh);
g_assert_cmpint(ret, ==, 16); g_assert_cmpint(ret, ==, 16);
fclose(fh); fclose(fh);
@ -1012,6 +1043,7 @@ static void test_cdrom_dma(void)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
const char *base; const char *base;
int i;
int fd; int fd;
int ret; int ret;
@ -1035,18 +1067,22 @@ int main(int argc, char **argv)
close(fd); close(fd);
/* Create a temporary raw image */ /* Create a temporary raw image */
tmp_path = g_strdup_printf("%s/qtest.XXXXXX", base); for (i = 0; i < 2; ++i) {
fd = g_mkstemp(tmp_path); tmp_path[i] = g_strdup_printf("%s/qtest.XXXXXX", base);
g_assert(fd >= 0); fd = g_mkstemp(tmp_path[i]);
ret = ftruncate(fd, TEST_IMAGE_SIZE); g_assert(fd >= 0);
g_assert(ret == 0); ret = ftruncate(fd, TEST_IMAGE_SIZE);
close(fd); g_assert(ret == 0);
close(fd);
}
/* Run the tests */ /* Run the tests */
g_test_init(&argc, &argv, NULL); g_test_init(&argc, &argv, NULL);
qtest_add_func("/ide/identify", test_identify); qtest_add_func("/ide/identify", test_identify);
qtest_add_func("/ide/diagnostic", test_diagnostic);
qtest_add_func("/ide/bmdma/simple_rw", test_bmdma_simple_rw); qtest_add_func("/ide/bmdma/simple_rw", test_bmdma_simple_rw);
qtest_add_func("/ide/bmdma/trim", test_bmdma_trim); qtest_add_func("/ide/bmdma/trim", test_bmdma_trim);
qtest_add_func("/ide/bmdma/various_prdts", test_bmdma_various_prdts); qtest_add_func("/ide/bmdma/various_prdts", test_bmdma_various_prdts);
@ -1064,8 +1100,10 @@ int main(int argc, char **argv)
ret = g_test_run(); ret = g_test_run();
/* Cleanup */ /* Cleanup */
unlink(tmp_path); for (i = 0; i < 2; ++i) {
g_free(tmp_path); unlink(tmp_path[i]);
g_free(tmp_path[i]);
}
unlink(debug_path); unlink(debug_path);
g_free(debug_path); g_free(debug_path);