Block pull request
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJS/lHGAAoJEJykq7OBq3PIws0H/0dBfSHgw2MGuQa3iTFyccA8 2aR17BAMPzcYU3sezVsDVYk4FGb5qQWHHeWdmIse4caKXg1jMi/XI0JewjO/88oF qcfL+ThWEeDRd2HdwF3KvVbm4p2iLkug3ekhBSAZ9SVEqWXhCki52x60Zki66Uh5 zwRQps93m5Vzd+uIb8JWPoyiN55yi5PjJ1nhrUhwCZ8WKDkD3XGc523u6VAcCTop saSkwbUFs6oiFC1PKt/8YmxgWHYH1NwvgdcmxJkc13r0erytdU04GNRAGCc7vwla Q+V0qkMAybQsP915y5bpW6NBQJyFRTYQmBtlMZ/TJ6VVsn1cLKfkPGW2schdqh0= =sg1v -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging Block pull request # gpg: Signature made Fri 14 Feb 2014 17:26:30 GMT using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8 * remotes/stefanha/tags/block-pull-request: block: Open by reference will try device then node_name. block: Relax bdrv_lookup_bs constraints. blockdev: Fix wrong usage of QDECREF causing snapshoted quorum to crash on close. block: mirror - use local_err to avoid NULL errp qemu-iotests: Don't run 005 on vmdk split formats block: qemu-iotests - add vhdx log replay tests for qemu-img block: qemu-iotests - fix test 070 (vhdx) block: Don't throw away errno via error_setg block: Add notes to iSCSI's .bdrv_open and .bdrv_reopen_prepare blockdev: Remove 'type' parameter from blockdev_init() sdhci: Drop unnecessary #include Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
44e3a39f30
36
block.c
36
block.c
|
@ -796,6 +796,13 @@ static int bdrv_assign_node_name(BlockDriverState *bs,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* takes care of avoiding namespaces collisions */
|
||||
if (bdrv_find(node_name)) {
|
||||
error_setg(errp, "node-name=%s is conflicting with a device id",
|
||||
node_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* takes care of avoiding duplicates node names */
|
||||
if (bdrv_find_node(node_name)) {
|
||||
error_setg(errp, "Duplicate node name");
|
||||
|
@ -977,9 +984,8 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
|
|||
}
|
||||
QDECREF(options);
|
||||
|
||||
bs = bdrv_find(reference);
|
||||
bs = bdrv_lookup_bs(reference, reference, errp);
|
||||
if (!bs) {
|
||||
error_setg(errp, "Cannot find block device '%s'", reference);
|
||||
return -ENODEV;
|
||||
}
|
||||
bdrv_ref(bs);
|
||||
|
@ -3574,30 +3580,26 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
|
|||
{
|
||||
BlockDriverState *bs = NULL;
|
||||
|
||||
if ((!device && !node_name) || (device && node_name)) {
|
||||
error_setg(errp, "Use either device or node-name but not both");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (device) {
|
||||
bs = bdrv_find(device);
|
||||
|
||||
if (!bs) {
|
||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||
return NULL;
|
||||
if (bs) {
|
||||
return bs;
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
|
||||
bs = bdrv_find_node(node_name);
|
||||
if (node_name) {
|
||||
bs = bdrv_find_node(node_name);
|
||||
|
||||
if (!bs) {
|
||||
error_set(errp, QERR_DEVICE_NOT_FOUND, node_name);
|
||||
return NULL;
|
||||
if (bs) {
|
||||
return bs;
|
||||
}
|
||||
}
|
||||
|
||||
return bs;
|
||||
error_setg(errp, "Cannot find device=%s nor node_name=%s",
|
||||
device ? device : "",
|
||||
node_name ? node_name : "");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BlockDriverState *bdrv_next(BlockDriverState *bs)
|
||||
|
|
|
@ -1099,6 +1099,10 @@ fail:
|
|||
/*
|
||||
* We support iscsi url's on the form
|
||||
* iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
|
||||
*
|
||||
* Note: flags are currently not used by iscsi_open. If this function
|
||||
* is changed such that flags are used, please examine iscsi_reopen_prepare()
|
||||
* to see if needs to be changed as well.
|
||||
*/
|
||||
static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
Error **errp)
|
||||
|
@ -1336,11 +1340,13 @@ static int iscsi_refresh_limits(BlockDriverState *bs)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* We have nothing to do for iSCSI reopen, stub just returns
|
||||
* success */
|
||||
/* Since iscsi_open() ignores bdrv_flags, there is nothing to do here in
|
||||
* prepare. Note that this will not re-establish a connection with an iSCSI
|
||||
* target - it is effectively a NOP. */
|
||||
static int iscsi_reopen_prepare(BDRVReopenState *state,
|
||||
BlockReopenQueue *queue, Error **errp)
|
||||
{
|
||||
/* NOP */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -633,6 +633,8 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
|
|||
{
|
||||
int64_t length, base_length;
|
||||
int orig_base_flags;
|
||||
int ret;
|
||||
Error *local_err = NULL;
|
||||
|
||||
orig_base_flags = bdrv_get_flags(base);
|
||||
|
||||
|
@ -642,19 +644,23 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
|
|||
|
||||
length = bdrv_getlength(bs);
|
||||
if (length < 0) {
|
||||
error_setg(errp, "Unable to determine length of %s", bs->filename);
|
||||
error_setg_errno(errp, -length,
|
||||
"Unable to determine length of %s", bs->filename);
|
||||
goto error_restore_flags;
|
||||
}
|
||||
|
||||
base_length = bdrv_getlength(base);
|
||||
if (base_length < 0) {
|
||||
error_setg(errp, "Unable to determine length of %s", base->filename);
|
||||
error_setg_errno(errp, -base_length,
|
||||
"Unable to determine length of %s", base->filename);
|
||||
goto error_restore_flags;
|
||||
}
|
||||
|
||||
if (length > base_length) {
|
||||
if (bdrv_truncate(base, length) < 0) {
|
||||
error_setg(errp, "Top image %s is larger than base image %s, and "
|
||||
ret = bdrv_truncate(base, length);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret,
|
||||
"Top image %s is larger than base image %s, and "
|
||||
"resize of base image failed",
|
||||
bs->filename, base->filename);
|
||||
goto error_restore_flags;
|
||||
|
@ -663,9 +669,10 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
|
|||
|
||||
bdrv_ref(base);
|
||||
mirror_start_job(bs, base, speed, 0, 0,
|
||||
on_error, on_error, cb, opaque, errp,
|
||||
on_error, on_error, cb, opaque, &local_err,
|
||||
&commit_active_job_driver, false, base);
|
||||
if (error_is_set(errp)) {
|
||||
if (error_is_set(&local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
goto error_restore_flags;
|
||||
}
|
||||
|
||||
|
|
|
@ -606,7 +606,8 @@ int qcow2_snapshot_delete(BlockDriverState *bs,
|
|||
s->nb_snapshots--;
|
||||
ret = qcow2_write_snapshots(bs);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Failed to remove snapshot from snapshot list");
|
||||
error_setg_errno(errp, -ret,
|
||||
"Failed to remove snapshot from snapshot list");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -624,7 +625,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs,
|
|||
ret = qcow2_update_snapshot_refcount(bs, sn.l1_table_offset,
|
||||
sn.l1_size, -1);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Failed to free the cluster and L1 table");
|
||||
error_setg_errno(errp, -ret, "Failed to free the cluster and L1 table");
|
||||
return ret;
|
||||
}
|
||||
qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t),
|
||||
|
@ -633,7 +634,8 @@ int qcow2_snapshot_delete(BlockDriverState *bs,
|
|||
/* must update the copied flag on the current cluster offsets */
|
||||
ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Failed to update snapshot status in disk");
|
||||
error_setg_errno(errp, -ret,
|
||||
"Failed to update snapshot status in disk");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1502,7 +1502,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
|
|||
if (flat) {
|
||||
ret = bdrv_truncate(bs, filesize);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Could not truncate file");
|
||||
error_setg_errno(errp, -ret, "Could not truncate file");
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
|
@ -1562,7 +1562,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
|
|||
|
||||
ret = bdrv_truncate(bs, le64_to_cpu(header.grain_offset) << 9);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Could not truncate file");
|
||||
error_setg_errno(errp, -ret, "Could not truncate file");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1846,7 +1846,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
|
|||
if (desc_offset == 0) {
|
||||
ret = bdrv_truncate(new_bs, desc_len);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Could not truncate file");
|
||||
error_setg_errno(errp, -ret, "Could not truncate file");
|
||||
}
|
||||
}
|
||||
exit:
|
||||
|
|
55
blockdev.c
55
blockdev.c
|
@ -308,7 +308,6 @@ typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
|
|||
|
||||
/* Takes the ownership of bs_opts */
|
||||
static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
||||
BlockInterfaceType type,
|
||||
Error **errp)
|
||||
{
|
||||
const char *buf;
|
||||
|
@ -437,11 +436,6 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||
|
||||
on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
|
||||
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
|
||||
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
|
||||
error_setg(errp, "werror is not supported by this bus type");
|
||||
goto early_err;
|
||||
}
|
||||
|
||||
on_write_error = parse_block_error_action(buf, 0, &error);
|
||||
if (error_is_set(&error)) {
|
||||
error_propagate(errp, error);
|
||||
|
@ -451,11 +445,6 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||
|
||||
on_read_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||
if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
|
||||
if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
|
||||
error_report("rerror is not supported by this bus type");
|
||||
goto early_err;
|
||||
}
|
||||
|
||||
on_read_error = parse_block_error_action(buf, 1, &error);
|
||||
if (error_is_set(&error)) {
|
||||
error_propagate(errp, error);
|
||||
|
@ -463,13 +452,18 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
|
|||
}
|
||||
}
|
||||
|
||||
if (bdrv_find_node(qemu_opts_id(opts))) {
|
||||
error_setg(errp, "device id=%s is conflicting with a node-name",
|
||||
qemu_opts_id(opts));
|
||||
goto early_err;
|
||||
}
|
||||
|
||||
/* init */
|
||||
dinfo = g_malloc0(sizeof(*dinfo));
|
||||
dinfo->id = g_strdup(qemu_opts_id(opts));
|
||||
dinfo->bdrv = bdrv_new(dinfo->id);
|
||||
dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
|
||||
dinfo->bdrv->read_only = ro;
|
||||
dinfo->type = type;
|
||||
dinfo->refcount = 1;
|
||||
if (serial != NULL) {
|
||||
dinfo->serial = g_strdup(serial);
|
||||
|
@ -608,6 +602,14 @@ QemuOptsList qemu_legacy_drive_opts = {
|
|||
.name = "read-only",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "open drive file as read-only",
|
||||
},{
|
||||
.name = "rerror",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "read error action",
|
||||
},{
|
||||
.name = "werror",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "write error action",
|
||||
},{
|
||||
.name = "copy-on-read",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
|
@ -629,6 +631,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
|||
int cyls, heads, secs, translation;
|
||||
int max_devs, bus_id, unit_id, index;
|
||||
const char *devaddr;
|
||||
const char *werror, *rerror;
|
||||
bool read_only = false;
|
||||
bool copy_on_read;
|
||||
const char *filename;
|
||||
|
@ -872,8 +875,29 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
|||
|
||||
filename = qemu_opt_get(legacy_opts, "file");
|
||||
|
||||
/* Check werror/rerror compatibility with if=... */
|
||||
werror = qemu_opt_get(legacy_opts, "werror");
|
||||
if (werror != NULL) {
|
||||
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO &&
|
||||
type != IF_NONE) {
|
||||
error_report("werror is not supported by this bus type");
|
||||
goto fail;
|
||||
}
|
||||
qdict_put(bs_opts, "werror", qstring_from_str(werror));
|
||||
}
|
||||
|
||||
rerror = qemu_opt_get(legacy_opts, "rerror");
|
||||
if (rerror != NULL) {
|
||||
if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI &&
|
||||
type != IF_NONE) {
|
||||
error_report("rerror is not supported by this bus type");
|
||||
goto fail;
|
||||
}
|
||||
qdict_put(bs_opts, "rerror", qstring_from_str(rerror));
|
||||
}
|
||||
|
||||
/* Actual block device init: Functionality shared with blockdev-add */
|
||||
dinfo = blockdev_init(filename, bs_opts, type, &local_err);
|
||||
dinfo = blockdev_init(filename, bs_opts, &local_err);
|
||||
if (dinfo == NULL) {
|
||||
if (error_is_set(&local_err)) {
|
||||
qerror_report_err(local_err);
|
||||
|
@ -893,6 +917,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
|||
dinfo->secs = secs;
|
||||
dinfo->trans = translation;
|
||||
|
||||
dinfo->type = type;
|
||||
dinfo->bus = bus_id;
|
||||
dinfo->unit = unit_id;
|
||||
dinfo->devaddr = devaddr;
|
||||
|
@ -1310,8 +1335,6 @@ static void external_snapshot_prepare(BlkTransactionState *common,
|
|||
if (ret != 0) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
QDECREF(options);
|
||||
}
|
||||
|
||||
static void external_snapshot_commit(BlkTransactionState *common)
|
||||
|
@ -2276,7 +2299,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
|||
|
||||
qdict_flatten(qdict);
|
||||
|
||||
blockdev_init(NULL, qdict, IF_NONE, &local_err);
|
||||
blockdev_init(NULL, qdict, &local_err);
|
||||
if (error_is_set(&local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
goto fail;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/dma.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/bitops.h"
|
||||
|
||||
#include "sdhci.h"
|
||||
|
|
|
@ -44,6 +44,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|||
_supported_fmt generic
|
||||
_supported_proto generic
|
||||
_supported_os Linux
|
||||
_unsupported_imgopts "subformat=twoGbMaxExtentFlat" \
|
||||
"subformat=twoGbMaxExtentSparse"
|
||||
|
||||
# vpc is limited to 127GB, so we can't test it here
|
||||
if [ "$IMGFMT" = "vpc" ]; then
|
||||
|
|
|
@ -56,11 +56,22 @@ _use_sample_img iotest-dirtylog-10G-4M.vhdx.bz2
|
|||
|
||||
echo
|
||||
echo "=== Verify open image read-only fails, due to dirty log ==="
|
||||
$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | grep -o "Permission denied"
|
||||
$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | _filter_testdir \
|
||||
| _filter_qemu_io
|
||||
|
||||
echo "=== Verify open image replays log ==="
|
||||
$QEMU_IO -c "read -pP 0xa5 0 18M" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
# extract fresh sample image again
|
||||
_use_sample_img iotest-dirtylog-10G-4M.vhdx.bz2
|
||||
|
||||
echo "=== Verify qemu-img check -r all replays log ==="
|
||||
$QEMU_IMG check -r all "$TEST_IMG" 2>&1 | _filter_testdir | _filter_qemu
|
||||
|
||||
echo "=== Verify open image read-only succeeds after log replay ==="
|
||||
$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | _filter_testdir \
|
||||
| _filter_qemu_io
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
QA output created by 070
|
||||
|
||||
=== Verify open image read-only fails, due to dirty log ===
|
||||
Permission denied
|
||||
qemu-io: can't open device TEST_DIR/iotest-dirtylog-10G-4M.vhdx: VHDX image file 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx' opened read-only, but contains a log that needs to be replayed. To replay the log, execute:
|
||||
qemu-img check -r all 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx': Operation not permitted
|
||||
no file open, try 'help open'
|
||||
=== Verify open image replays log ===
|
||||
read 18874368/18874368 bytes at offset 0
|
||||
18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
=== Verify qemu-img check -r all replays log ===
|
||||
The following inconsistencies were found and repaired:
|
||||
|
||||
0 leaked clusters
|
||||
1 corruptions
|
||||
|
||||
Double checking the fixed image now...
|
||||
No errors were found on the image.
|
||||
=== Verify open image read-only succeeds after log replay ===
|
||||
read 18874368/18874368 bytes at offset 0
|
||||
18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
*** done
|
||||
|
|
Loading…
Reference in a new issue