2020-09-24 17:26:50 +02:00
|
|
|
/*
|
|
|
|
* Common block export infrastructure
|
|
|
|
*
|
|
|
|
* Copyright (c) 2012, 2020 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Paolo Bonzini <pbonzini@redhat.com>
|
|
|
|
* Kevin Wolf <kwolf@redhat.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
|
|
|
* later. See the COPYING file in the top-level directory.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "qemu/osdep.h"
|
|
|
|
|
2020-09-24 17:26:53 +02:00
|
|
|
#include "block/block.h"
|
|
|
|
#include "sysemu/block-backend.h"
|
2020-09-24 17:26:50 +02:00
|
|
|
#include "block/export.h"
|
|
|
|
#include "block/nbd.h"
|
|
|
|
#include "qapi/error.h"
|
|
|
|
#include "qapi/qapi-commands-block-export.h"
|
|
|
|
|
|
|
|
static const BlockExportDriver *blk_exp_drivers[] = {
|
|
|
|
&blk_exp_nbd,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const BlockExportDriver *blk_exp_find_driver(BlockExportType type)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(blk_exp_drivers); i++) {
|
|
|
|
if (blk_exp_drivers[i]->type == type) {
|
|
|
|
return blk_exp_drivers[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-09-24 17:26:53 +02:00
|
|
|
BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
|
2020-09-24 17:26:50 +02:00
|
|
|
{
|
|
|
|
const BlockExportDriver *drv;
|
2020-09-24 17:27:02 +02:00
|
|
|
BlockExport *exp;
|
|
|
|
int ret;
|
2020-09-24 17:26:50 +02:00
|
|
|
|
|
|
|
drv = blk_exp_find_driver(export->type);
|
|
|
|
if (!drv) {
|
|
|
|
error_setg(errp, "No driver found for the requested export type");
|
2020-09-24 17:26:53 +02:00
|
|
|
return NULL;
|
2020-09-24 17:26:50 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 17:27:02 +02:00
|
|
|
assert(drv->instance_size >= sizeof(BlockExport));
|
|
|
|
exp = g_malloc0(drv->instance_size);
|
|
|
|
*exp = (BlockExport) {
|
|
|
|
.drv = drv,
|
|
|
|
.refcount = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
ret = drv->create(exp, export, errp);
|
|
|
|
if (ret < 0) {
|
|
|
|
g_free(exp);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return exp;
|
2020-09-24 17:26:53 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 17:27:00 +02:00
|
|
|
/* Callers must hold exp->ctx lock */
|
2020-09-24 17:26:59 +02:00
|
|
|
void blk_exp_ref(BlockExport *exp)
|
|
|
|
{
|
|
|
|
assert(exp->refcount > 0);
|
|
|
|
exp->refcount++;
|
|
|
|
}
|
|
|
|
|
2020-09-24 17:27:00 +02:00
|
|
|
/* Callers must hold exp->ctx lock */
|
2020-09-24 17:26:59 +02:00
|
|
|
void blk_exp_unref(BlockExport *exp)
|
|
|
|
{
|
|
|
|
assert(exp->refcount > 0);
|
|
|
|
if (--exp->refcount == 0) {
|
|
|
|
exp->drv->delete(exp);
|
2020-09-24 17:27:02 +02:00
|
|
|
g_free(exp);
|
2020-09-24 17:26:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-24 17:26:53 +02:00
|
|
|
void qmp_block_export_add(BlockExportOptions *export, Error **errp)
|
|
|
|
{
|
|
|
|
blk_exp_add(export, errp);
|
2020-09-24 17:26:50 +02:00
|
|
|
}
|