}
/* check if the path starts with "<protocol>:" */
-static int path_has_protocol(const char *path)
+int path_has_protocol(const char *path)
{
const char *p;
return;
}
bs->bl.opt_transfer_length = bs->file->bl.opt_transfer_length;
+ bs->bl.max_transfer_length = bs->file->bl.max_transfer_length;
bs->bl.opt_mem_alignment = bs->file->bl.opt_mem_alignment;
} else {
bs->bl.opt_mem_alignment = 512;
bs->bl.opt_transfer_length =
MAX(bs->bl.opt_transfer_length,
bs->backing_hd->bl.opt_transfer_length);
+ bs->bl.max_transfer_length =
+ MIN_NON_ZERO(bs->bl.max_transfer_length,
+ bs->backing_hd->bl.max_transfer_length);
bs->bl.opt_mem_alignment =
MAX(bs->bl.opt_mem_alignment,
bs->backing_hd->bl.opt_mem_alignment);
}
if (!path_has_protocol(filename) || !allow_protocol_prefix) {
- return bdrv_find_format("file");
+ return &bdrv_file;
}
p = strchr(filename, ':');
return NULL;
}
+/*
+ * Guess image format by probing its contents.
+ * This is not a good idea when your image is raw (CVE-2008-2004), but
+ * we do it anyway for backward compatibility.
+ *
+ * @buf contains the image's first @buf_size bytes.
+ * @buf_size is the buffer size in bytes (generally BLOCK_PROBE_BUF_SIZE,
+ * but can be smaller if the image file is smaller)
+ * @filename is its filename.
+ *
+ * For all block drivers, call the bdrv_probe() method to get its
+ * probing score.
+ * Return the first block driver with the highest probing score.
+ */
+BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
+ const char *filename)
+{
+ int score_max = 0, score;
+ BlockDriver *drv = NULL, *d;
+
+ QLIST_FOREACH(d, &bdrv_drivers, list) {
+ if (d->bdrv_probe) {
+ score = d->bdrv_probe(buf, buf_size, filename);
+ if (score > score_max) {
+ score_max = score;
+ drv = d;
+ }
+ }
+ }
+
+ return drv;
+}
+
static int find_image_format(BlockDriverState *bs, const char *filename,
BlockDriver **pdrv, Error **errp)
{
- int score, score_max;
- BlockDriver *drv1, *drv;
- uint8_t buf[2048];
+ BlockDriver *drv;
+ uint8_t buf[BLOCK_PROBE_BUF_SIZE];
int ret = 0;
/* Return the raw BlockDriver * to scsi-generic devices or empty drives */
if (bs->sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) {
- drv = bdrv_find_format("raw");
- if (!drv) {
- error_setg(errp, "Could not find raw image format");
- ret = -ENOENT;
- }
- *pdrv = drv;
+ *pdrv = &bdrv_raw;
return ret;
}
return ret;
}
- score_max = 0;
- drv = NULL;
- QLIST_FOREACH(drv1, &bdrv_drivers, list) {
- if (drv1->bdrv_probe) {
- score = drv1->bdrv_probe(buf, ret, filename);
- if (score > score_max) {
- score_max = score;
- drv = drv1;
- }
- }
- }
+ drv = bdrv_probe_all(buf, ret, filename);
if (!drv) {
error_setg(errp, "Could not determine image format: No compatible "
"driver found");
{
char *backing_filename = g_malloc0(PATH_MAX);
int ret = 0;
- BlockDriver *back_drv = NULL;
BlockDriverState *backing_hd;
Error *local_err = NULL;
backing_hd = bdrv_new();
- if (bs->backing_format[0] != '\0') {
- back_drv = bdrv_find_format(bs->backing_format);
+ if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) {
+ qdict_put(options, "driver", qstring_from_str(bs->backing_format));
}
assert(bs->backing_hd == NULL);
ret = bdrv_open(&backing_hd,
*backing_filename ? backing_filename : NULL, NULL, options,
- bdrv_backing_flags(bs->open_flags), back_drv, &local_err);
+ bdrv_backing_flags(bs->open_flags), NULL, &local_err);
if (ret < 0) {
bdrv_unref(backing_hd);
backing_hd = NULL;
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
char *tmp_filename = g_malloc0(PATH_MAX + 1);
int64_t total_size;
- BlockDriver *bdrv_qcow2;
QemuOpts *opts = NULL;
QDict *snapshot_options;
BlockDriverState *bs_snapshot;
goto out;
}
- bdrv_qcow2 = bdrv_find_format("qcow2");
- opts = qemu_opts_create(bdrv_qcow2->create_opts, NULL, 0,
+ opts = qemu_opts_create(bdrv_qcow2.create_opts, NULL, 0,
&error_abort);
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_size);
- ret = bdrv_create(bdrv_qcow2, tmp_filename, opts, &local_err);
+ ret = bdrv_create(&bdrv_qcow2, tmp_filename, opts, &local_err);
qemu_opts_del(opts);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not create temporary overlay "
bs_snapshot = bdrv_new();
ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
- flags, bdrv_qcow2, &local_err);
+ flags, &bdrv_qcow2, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
goto out;
}
/* Image format probing */
+ bs->probed = !drv;
if (!drv && file) {
ret = find_image_format(file, filename, &drv, &local_err);
if (ret < 0) {
return false;
}
+static bool bdrv_drain_one(BlockDriverState *bs)
+{
+ bool bs_busy;
+
+ bdrv_flush_io_queue(bs);
+ bdrv_start_throttled_reqs(bs);
+ bs_busy = bdrv_requests_pending(bs);
+ bs_busy |= aio_poll(bdrv_get_aio_context(bs), bs_busy);
+ return bs_busy;
+}
+
+/*
+ * Wait for pending requests to complete on a single BlockDriverState subtree
+ *
+ * See the warning in bdrv_drain_all(). This function can only be called if
+ * you are sure nothing can generate I/O because you have op blockers
+ * installed.
+ *
+ * Note that unlike bdrv_drain_all(), the caller must hold the BlockDriverState
+ * AioContext.
+ */
+void bdrv_drain(BlockDriverState *bs)
+{
+ while (bdrv_drain_one(bs)) {
+ /* Keep iterating */
+ }
+}
+
/*
* Wait for pending requests to complete across all BlockDriverStates
*
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
AioContext *aio_context = bdrv_get_aio_context(bs);
- bool bs_busy;
aio_context_acquire(aio_context);
- bdrv_flush_io_queue(bs);
- bdrv_start_throttled_reqs(bs);
- bs_busy = bdrv_requests_pending(bs);
- bs_busy |= aio_poll(aio_context, bs_busy);
+ busy |= bdrv_drain_one(bs);
aio_context_release(aio_context);
-
- busy |= bs_busy;
}
}
}
if (nb_sectors <= 0) {
return 0;
}
- if (nb_sectors > INT_MAX) {
- nb_sectors = INT_MAX;
+ if (nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
+ nb_sectors = INT_MAX / BDRV_SECTOR_SIZE;
}
ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &n);
if (ret < 0) {
BlockErrorAction action,
bool is_read, int error)
{
- BlockErrorAction ac;
+ IoOperationType optype;
- ac = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
- qapi_event_send_block_io_error(bdrv_get_device_name(bs), ac, action,
+ optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
+ qapi_event_send_block_io_error(bdrv_get_device_name(bs), optype, action,
bdrv_iostatus_is_enabled(bs),
error == ENOSPC, strerror(error),
&error_abort);
return top != NULL;
}
+BlockDriverState *bdrv_next_node(BlockDriverState *bs)
+{
+ if (!bs) {
+ return QTAILQ_FIRST(&graph_bdrv_states);
+ }
+ return QTAILQ_NEXT(bs, node_list);
+}
+
BlockDriverState *bdrv_next(BlockDriverState *bs)
{
if (!bs) {
return QTAILQ_NEXT(bs, device_list);
}
+const char *bdrv_get_node_name(const BlockDriverState *bs)
+{
+ return bs->node_name;
+}
+
/* TODO check what callers really want: bs->node_name or blk_name() */
const char *bdrv_get_device_name(const BlockDriverState *bs)
{
merge = 0;
}
+ if (bs->bl.max_transfer_length && reqs[outidx].nb_sectors +
+ reqs[i].nb_sectors > bs->bl.max_transfer_length) {
+ merge = 0;
+ }
+
if (merge) {
size_t size;
QEMUIOVector *qiov = g_malloc0(sizeof(*qiov));
return;
}
+ if (!drv->create_opts) {
+ error_setg(errp, "Format driver '%s' does not support image creation",
+ drv->format_name);
+ return;
+ }
+
+ if (!proto_drv->create_opts) {
+ error_setg(errp, "Protocol driver '%s' does not support image creation",
+ proto_drv->format_name);
+ return;
+ }
+
create_opts = qemu_opts_append(create_opts, drv->create_opts);
create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
ret = bdrv_open(&bs, backing_file, NULL, NULL, back_flags,
backing_drv, &local_err);
if (ret < 0) {
- error_setg_errno(errp, -ret, "Could not open '%s': %s",
- backing_file,
- error_get_pretty(local_err));
- error_free(local_err);
- local_err = NULL;
goto out;
}
size = bdrv_getlength(bs);
}
if (!quiet) {
- printf("Formatting '%s', fmt=%s ", filename, fmt);
- qemu_opts_print(opts);
+ printf("Formatting '%s', fmt=%s", filename, fmt);
+ qemu_opts_print(opts, " ");
puts("");
}
notifier_with_return_list_add(&bs->before_write_notifiers, notifier);
}
-int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts)
+int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts,
+ BlockDriverAmendStatusCB *status_cb)
{
if (!bs->drv->bdrv_amend_options) {
return -ENOTSUP;
}
- return bs->drv->bdrv_amend_options(bs, opts);
+ return bs->drv->bdrv_amend_options(bs, opts, status_cb);
}
/* This function will be called by the bdrv_recurse_is_first_non_filter method
BlockDriverState *check_to_replace_node(const char *node_name, Error **errp)
{
BlockDriverState *to_replace_bs = bdrv_find_node(node_name);
+ AioContext *aio_context;
+
if (!to_replace_bs) {
error_setg(errp, "Node name '%s' not found", node_name);
return NULL;
}
+ aio_context = bdrv_get_aio_context(to_replace_bs);
+ aio_context_acquire(aio_context);
+
if (bdrv_op_is_blocked(to_replace_bs, BLOCK_OP_TYPE_REPLACE, errp)) {
- return NULL;
+ to_replace_bs = NULL;
+ goto out;
}
/* We don't want arbitrary node of the BDS chain to be replaced only the top
*/
if (!bdrv_is_first_non_filter(to_replace_bs)) {
error_setg(errp, "Only top most non filter can be replaced");
- return NULL;
+ to_replace_bs = NULL;
+ goto out;
}
+out:
+ aio_context_release(aio_context);
return to_replace_bs;
}