Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-reques…
Browse files Browse the repository at this point in the history
…t' into staging

Block pull request

# gpg: Signature made Fri 18 Jul 2014 13:39:43 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <[email protected]>"
# gpg:                 aka "Stefan Hajnoczi <[email protected]>"

* remotes/stefanha/tags/block-pull-request:
  qemu-iotests: fix 028 failure due to disk image path
  raw-posix: Fail gracefully if no working alignment is found
  block: Add Error argument to bdrv_refresh_limits()
  qcow2: Fix error path for unknown incompatible features

Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
pm215 committed Jul 18, 2014
2 parents 4d121a5 + 8283c5c commit e0097ea
Show file tree
Hide file tree
Showing 15 changed files with 174 additions and 51 deletions.
33 changes: 23 additions & 10 deletions block.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,27 +508,36 @@ int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp)
return ret;
}

int bdrv_refresh_limits(BlockDriverState *bs)
void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
{
BlockDriver *drv = bs->drv;
Error *local_err = NULL;

memset(&bs->bl, 0, sizeof(bs->bl));

if (!drv) {
return 0;
return;
}

/* Take some limits from the children as a default */
if (bs->file) {
bdrv_refresh_limits(bs->file);
bdrv_refresh_limits(bs->file, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
bs->bl.opt_transfer_length = bs->file->bl.opt_transfer_length;
bs->bl.opt_mem_alignment = bs->file->bl.opt_mem_alignment;
} else {
bs->bl.opt_mem_alignment = 512;
}

if (bs->backing_hd) {
bdrv_refresh_limits(bs->backing_hd);
bdrv_refresh_limits(bs->backing_hd, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
bs->bl.opt_transfer_length =
MAX(bs->bl.opt_transfer_length,
bs->backing_hd->bl.opt_transfer_length);
Expand All @@ -539,10 +548,8 @@ int bdrv_refresh_limits(BlockDriverState *bs)

/* Then let the driver override it */
if (drv->bdrv_refresh_limits) {
return drv->bdrv_refresh_limits(bs);
drv->bdrv_refresh_limits(bs, errp);
}

return 0;
}

/*
Expand Down Expand Up @@ -993,7 +1000,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
goto free_and_fail;
}

bdrv_refresh_limits(bs);
bdrv_refresh_limits(bs, &local_err);
if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto free_and_fail;
}

assert(bdrv_opt_mem_align(bs) != 0);
assert((bs->request_alignment != 0) || bs->sg);
return 0;
Expand Down Expand Up @@ -1154,7 +1167,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_COMMIT,
bs->backing_blocker);
out:
bdrv_refresh_limits(bs);
bdrv_refresh_limits(bs, NULL);
}

/*
Expand Down Expand Up @@ -1778,7 +1791,7 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
BDRV_O_CACHE_WB);
reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);

bdrv_refresh_limits(reopen_state->bs);
bdrv_refresh_limits(reopen_state->bs, NULL);
}

/*
Expand Down
3 changes: 1 addition & 2 deletions block/iscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1450,7 +1450,7 @@ static void iscsi_close(BlockDriverState *bs)
memset(iscsilun, 0, sizeof(IscsiLun));
}

static int iscsi_refresh_limits(BlockDriverState *bs)
static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
{
IscsiLun *iscsilun = bs->opaque;

Expand All @@ -1475,7 +1475,6 @@ static int iscsi_refresh_limits(BlockDriverState *bs)
}
bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len,
iscsilun);
return 0;
}

/* Since iscsi_open() ignores bdrv_flags, there is nothing to do here in
Expand Down
25 changes: 17 additions & 8 deletions block/qcow2.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,20 +210,31 @@ static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs,
static void report_unsupported_feature(BlockDriverState *bs,
Error **errp, Qcow2Feature *table, uint64_t mask)
{
char *features = g_strdup("");
char *old;

while (table && table->name[0] != '\0') {
if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) {
if (mask & (1 << table->bit)) {
report_unsupported(bs, errp, "%.46s", table->name);
mask &= ~(1 << table->bit);
if (mask & (1ULL << table->bit)) {
old = features;
features = g_strdup_printf("%s%s%.46s", old, *old ? ", " : "",
table->name);
g_free(old);
mask &= ~(1ULL << table->bit);
}
}
table++;
}

if (mask) {
report_unsupported(bs, errp, "Unknown incompatible feature: %" PRIx64,
mask);
old = features;
features = g_strdup_printf("%s%sUnknown incompatible feature: %" PRIx64,
old, *old ? ", " : "", mask);
g_free(old);
}

report_unsupported(bs, errp, "%s", features);
g_free(features);
}

/*
Expand Down Expand Up @@ -855,13 +866,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}

static int qcow2_refresh_limits(BlockDriverState *bs)
static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
{
BDRVQcowState *s = bs->opaque;

bs->bl.write_zeroes_alignment = s->cluster_sectors;

return 0;
}

static int qcow2_set_key(BlockDriverState *bs, const char *key)
Expand Down
4 changes: 1 addition & 3 deletions block/qed.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,13 +528,11 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}

static int bdrv_qed_refresh_limits(BlockDriverState *bs)
static void bdrv_qed_refresh_limits(BlockDriverState *bs, Error **errp)
{
BDRVQEDState *s = bs->opaque;

bs->bl.write_zeroes_alignment = s->header.cluster_size >> BDRV_SECTOR_BITS;

return 0;
}

/* We have nothing to do for QED reopen, stubs just return
Expand Down
39 changes: 28 additions & 11 deletions block/raw-posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ static int raw_normalize_devicepath(const char **filename)
}
#endif

static void raw_probe_alignment(BlockDriverState *bs)
static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
{
BDRVRawState *s = bs->opaque;
char *buf;
Expand All @@ -240,24 +240,24 @@ static void raw_probe_alignment(BlockDriverState *bs)
s->buf_align = 0;

#ifdef BLKSSZGET
if (ioctl(s->fd, BLKSSZGET, &sector_size) >= 0) {
if (ioctl(fd, BLKSSZGET, &sector_size) >= 0) {
bs->request_alignment = sector_size;
}
#endif
#ifdef DKIOCGETBLOCKSIZE
if (ioctl(s->fd, DKIOCGETBLOCKSIZE, &sector_size) >= 0) {
if (ioctl(fd, DKIOCGETBLOCKSIZE, &sector_size) >= 0) {
bs->request_alignment = sector_size;
}
#endif
#ifdef DIOCGSECTORSIZE
if (ioctl(s->fd, DIOCGSECTORSIZE, &sector_size) >= 0) {
if (ioctl(fd, DIOCGSECTORSIZE, &sector_size) >= 0) {
bs->request_alignment = sector_size;
}
#endif
#ifdef CONFIG_XFS
if (s->is_xfs) {
struct dioattr da;
if (xfsctl(NULL, s->fd, XFS_IOC_DIOINFO, &da) >= 0) {
if (xfsctl(NULL, fd, XFS_IOC_DIOINFO, &da) >= 0) {
bs->request_alignment = da.d_miniosz;
/* The kernel returns wrong information for d_mem */
/* s->buf_align = da.d_mem; */
Expand All @@ -270,7 +270,7 @@ static void raw_probe_alignment(BlockDriverState *bs)
size_t align;
buf = qemu_memalign(MAX_BLOCKSIZE, 2 * MAX_BLOCKSIZE);
for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) {
if (pread(s->fd, buf + align, MAX_BLOCKSIZE, 0) >= 0) {
if (pread(fd, buf + align, MAX_BLOCKSIZE, 0) >= 0) {
s->buf_align = align;
break;
}
Expand All @@ -282,13 +282,18 @@ static void raw_probe_alignment(BlockDriverState *bs)
size_t align;
buf = qemu_memalign(s->buf_align, MAX_BLOCKSIZE);
for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) {
if (pread(s->fd, buf, align, 0) >= 0) {
if (pread(fd, buf, align, 0) >= 0) {
bs->request_alignment = align;
break;
}
}
qemu_vfree(buf);
}

if (!s->buf_align || !bs->request_alignment) {
error_setg(errp, "Could not find working O_DIRECT alignment. "
"Try cache.direct=off.");
}
}

static void raw_parse_flags(int bdrv_flags, int *open_flags)
Expand Down Expand Up @@ -505,6 +510,7 @@ static int raw_reopen_prepare(BDRVReopenState *state,
BDRVRawState *s;
BDRVRawReopenState *raw_s;
int ret = 0;
Error *local_err = NULL;

assert(state != NULL);
assert(state->bs != NULL);
Expand Down Expand Up @@ -577,6 +583,19 @@ static int raw_reopen_prepare(BDRVReopenState *state,
ret = -1;
}
}

/* Fail already reopen_prepare() if we can't get a working O_DIRECT
* alignment with the new fd. */
if (raw_s->fd != -1) {
raw_probe_alignment(state->bs, raw_s->fd, &local_err);
if (local_err) {
qemu_close(raw_s->fd);
raw_s->fd = -1;
error_propagate(errp, local_err);
ret = -EINVAL;
}
}

return ret;
}

Expand Down Expand Up @@ -615,14 +634,12 @@ static void raw_reopen_abort(BDRVReopenState *state)
state->opaque = NULL;
}

static int raw_refresh_limits(BlockDriverState *bs)
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
{
BDRVRawState *s = bs->opaque;

raw_probe_alignment(bs);
raw_probe_alignment(bs, s->fd, errp);
bs->bl.opt_mem_alignment = s->buf_align;

return 0;
}

static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
Expand Down
3 changes: 1 addition & 2 deletions block/raw_bsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,9 @@ static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
return bdrv_get_info(bs->file, bdi);
}

static int raw_refresh_limits(BlockDriverState *bs)
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
{
bs->bl = bs->file->bl;
return 0;
}

static int raw_truncate(BlockDriverState *bs, int64_t offset)
Expand Down
2 changes: 1 addition & 1 deletion block/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base,
bdrv_unref(unused);
}

bdrv_refresh_limits(top);
bdrv_refresh_limits(top, NULL);
}

static void coroutine_fn stream_run(void *opaque)
Expand Down
4 changes: 1 addition & 3 deletions block/vmdk.c
Original file line number Diff line number Diff line change
Expand Up @@ -938,7 +938,7 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
}


static int vmdk_refresh_limits(BlockDriverState *bs)
static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
{
BDRVVmdkState *s = bs->opaque;
int i;
Expand All @@ -950,8 +950,6 @@ static int vmdk_refresh_limits(BlockDriverState *bs)
s->extents[i].cluster_sectors);
}
}

return 0;
}

static int get_whole_cluster(BlockDriverState *bs,
Expand Down
2 changes: 1 addition & 1 deletion include/block/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset);
int64_t bdrv_getlength(BlockDriverState *bs);
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
int bdrv_refresh_limits(BlockDriverState *bs);
void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
int bdrv_commit(BlockDriverState *bs);
int bdrv_commit_all(void);
int bdrv_change_backing_file(BlockDriverState *bs,
Expand Down
2 changes: 1 addition & 1 deletion include/block/block_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ struct BlockDriver {
int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag);
bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag);

int (*bdrv_refresh_limits)(BlockDriverState *bs);
void (*bdrv_refresh_limits)(BlockDriverState *bs, Error **errp);

/*
* Returns 1 if newly created images are guaranteed to contain only
Expand Down
4 changes: 3 additions & 1 deletion tests/qemu-iotests/028
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ _launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk
h=$QEMU_HANDLE
QEMU_COMM_TIMEOUT=1

_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)"
# 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
qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
_send_qemu_cmd $h 'quit' ""

Expand Down
Loading

0 comments on commit e0097ea

Please sign in to comment.