#include "sysemu/block-backend.h"
#include "block/block_int.h"
+#include "sysemu/blockdev.h"
struct BlockBackend {
char *name;
int refcnt;
BlockDriverState *bs;
+ DriveInfo *legacy_dinfo;
QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
};
QTAILQ_REMOVE(&blk_backends, blk, link);
}
g_free(blk->name);
+ drive_info_del(blk->legacy_dinfo);
g_free(blk);
}
return blk->bs;
}
+/*
+ * Return @blk's DriveInfo if any, else null.
+ */
+DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
+{
+ return blk->legacy_dinfo;
+}
+
+/*
+ * Set @blk's DriveInfo to @dinfo, and return it.
+ * @blk must not have a DriveInfo set already.
+ * No other BlockBackend may have the same DriveInfo set.
+ */
+DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
+{
+ assert(!blk->legacy_dinfo);
+ return blk->legacy_dinfo = dinfo;
+}
+
+/*
+ * Return the BlockBackend with DriveInfo @dinfo.
+ * It must exist.
+ */
+BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
+{
+ BlockBackend *blk;
+
+ QTAILQ_FOREACH(blk, &blk_backends, link) {
+ if (blk->legacy_dinfo == dinfo) {
+ return blk;
+ }
+ }
+ abort();
+}
+
/*
* Hide @blk.
* @blk must not have been hidden already.
#include "trace.h"
#include "sysemu/arch_init.h"
-static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
-
static const char *const if_name[IF_COUNT] = {
[IF_NONE] = "none",
[IF_IDE] = "ide",
*/
void override_max_devs(BlockInterfaceType type, int max_devs)
{
+ BlockBackend *blk;
DriveInfo *dinfo;
if (max_devs <= 0) {
return;
}
- QTAILQ_FOREACH(dinfo, &drives, next) {
+ for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+ dinfo = blk_legacy_dinfo(blk);
if (dinfo->type == type) {
fprintf(stderr, "Cannot override units-per-bus property of"
" the %s interface, because a drive of that type has"
*/
void blockdev_mark_auto_del(BlockDriverState *bs)
{
- DriveInfo *dinfo = drive_get_by_blockdev(bs);
+ BlockBackend *blk = bs->blk;
+ DriveInfo *dinfo = blk_legacy_dinfo(blk);
if (dinfo && !dinfo->enable_auto_del) {
return;
void blockdev_auto_del(BlockDriverState *bs)
{
- DriveInfo *dinfo = drive_get_by_blockdev(bs);
+ BlockBackend *blk = bs->blk;
+ DriveInfo *dinfo = blk_legacy_dinfo(blk);
if (dinfo && dinfo->auto_del) {
drive_del(dinfo);
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
{
+ BlockBackend *blk;
DriveInfo *dinfo;
- /* seek interface, bus and unit */
-
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (dinfo->type == type &&
- dinfo->bus == bus &&
- dinfo->unit == unit)
+ for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+ dinfo = blk_legacy_dinfo(blk);
+ if (dinfo && dinfo->type == type
+ && dinfo->bus == bus && dinfo->unit == unit) {
return dinfo;
+ }
}
return NULL;
bool drive_check_orphaned(void)
{
+ BlockBackend *blk;
DriveInfo *dinfo;
bool rs = false;
- QTAILQ_FOREACH(dinfo, &drives, next) {
+ for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+ dinfo = blk_legacy_dinfo(blk);
/* If dinfo->bdrv->dev is NULL, it has no device attached. */
/* Unless this is a default drive, this may be an oversight. */
if (!dinfo->bdrv->dev && !dinfo->is_default &&
int drive_get_max_bus(BlockInterfaceType type)
{
int max_bus;
+ BlockBackend *blk;
DriveInfo *dinfo;
max_bus = -1;
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if(dinfo->type == type &&
- dinfo->bus > max_bus)
+ for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+ dinfo = blk_legacy_dinfo(blk);
+ if (dinfo && dinfo->type == type && dinfo->bus > max_bus) {
max_bus = dinfo->bus;
+ }
}
return max_bus;
}
DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
{
- DriveInfo *dinfo;
-
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (dinfo->bdrv == bs) {
- return dinfo;
- }
- }
- return NULL;
+ return bs->blk ? blk_legacy_dinfo(bs->blk) : NULL;
}
static void bdrv_format_print(void *opaque, const char *name)
}
qemu_opts_del(dinfo->opts);
g_free(dinfo->id);
- QTAILQ_REMOVE(&drives, dinfo, next);
g_free(dinfo->serial);
g_free(dinfo);
}
typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
/* Takes the ownership of bs_opts */
-static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
- Error **errp)
+static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
+ Error **errp)
{
const char *buf;
int ro = 0;
dinfo = g_malloc0(sizeof(*dinfo));
dinfo->id = g_strdup(qemu_opts_id(opts));
dinfo->bdrv = bs;
- QTAILQ_INSERT_TAIL(&drives, dinfo, next);
+ blk_set_legacy_dinfo(blk, dinfo);
if (!file || !*file) {
if (has_driver_specific_opts) {
} else {
QDECREF(bs_opts);
qemu_opts_del(opts);
- return dinfo;
+ return blk;
}
}
if (snapshot) {
QDECREF(bs_opts);
qemu_opts_del(opts);
- return dinfo;
+ return blk;
err:
bdrv_unref(bs);
DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
{
const char *value;
+ BlockBackend *blk;
DriveInfo *dinfo = NULL;
QDict *bs_opts;
QemuOpts *legacy_opts;
}
/* Actual block device init: Functionality shared with blockdev-add */
- dinfo = blockdev_init(filename, bs_opts, &local_err);
+ blk = blockdev_init(filename, bs_opts, &local_err);
bs_opts = NULL;
- if (dinfo == NULL) {
+ if (!blk) {
if (local_err) {
error_report("%s", error_get_pretty(local_err));
error_free(local_err);
}
/* Set legacy DriveInfo fields */
+ dinfo = blk_legacy_dinfo(blk);
dinfo->enable_auto_del = true;
dinfo->opts = all_opts;
}
bs = blk_bs(blk);
- dinfo = drive_get_by_blockdev(bs);
+ dinfo = blk_legacy_dinfo(blk);
if (dinfo && !dinfo->enable_auto_del) {
error_report("Deleting device added with blockdev-add"
" is not supported");
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
{
QmpOutputVisitor *ov = qmp_output_visitor_new();
- DriveInfo *dinfo;
+ BlockBackend *blk;
QObject *obj;
QDict *qdict;
Error *local_err = NULL;
qdict_flatten(qdict);
- dinfo = blockdev_init(NULL, qdict, &local_err);
+ blk = blockdev_init(NULL, qdict, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto fail;
}
- if (bdrv_key_required(dinfo->bdrv)) {
- drive_del(dinfo);
+ if (bdrv_key_required(blk_bs(blk))) {
+ bdrv_unref(blk_bs(blk));
+ blk_unref(blk);
error_setg(errp, "blockdev-add doesn't support encrypted devices");
goto fail;
}