Merge remote-tracking branch 'kwolf/for-anthony' into staging
# By Kevin Wolf (12) and Peter Lieven (2) # Via Kevin Wolf * kwolf/for-anthony: nbd: Check against invalid option combinations nbd: Use default port if only host is specified block: Allow omitting the file name when using driver-specific options block: Make find_image_format safe with NULL filename block: Rename variable to avoid shadowing block: Introduce .bdrv_parse_filename callback nbd: Accept -drive options for the network connection nbd: Remove unused functions nbd: Keep hostname and port separate qemu-socket: Make socket_optslist public block: Pass bdrv_file_open() options to block drivers block: Add options QDict to bdrv_file_open() prototypes block: complete all IOs before resizing a device Revert "block: complete all IOs before .bdrv_truncate"
This commit is contained in:
commit
3f08ffb4a4
145
block.c
145
block.c
@ -676,7 +676,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
|||||||
|
|
||||||
assert(drv != NULL);
|
assert(drv != NULL);
|
||||||
assert(bs->file == NULL);
|
assert(bs->file == NULL);
|
||||||
assert(options == NULL || bs->options != options);
|
assert(options != NULL && bs->options != options);
|
||||||
|
|
||||||
trace_bdrv_open_common(bs, filename, flags, drv->format_name);
|
trace_bdrv_open_common(bs, filename, flags, drv->format_name);
|
||||||
|
|
||||||
@ -688,7 +688,11 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
|||||||
bdrv_enable_copy_on_read(bs);
|
bdrv_enable_copy_on_read(bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
pstrcpy(bs->filename, sizeof(bs->filename), filename);
|
if (filename != NULL) {
|
||||||
|
pstrcpy(bs->filename, sizeof(bs->filename), filename);
|
||||||
|
} else {
|
||||||
|
bs->filename[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
|
if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
@ -708,7 +712,8 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
|||||||
bdrv_swap(file, bs);
|
bdrv_swap(file, bs);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
ret = drv->bdrv_file_open(bs, filename, open_flags);
|
assert(drv->bdrv_parse_filename || filename != NULL);
|
||||||
|
ret = drv->bdrv_file_open(bs, filename, options, open_flags);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(file != NULL);
|
assert(file != NULL);
|
||||||
@ -727,6 +732,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
|
|||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
if (bs->is_temporary) {
|
if (bs->is_temporary) {
|
||||||
|
assert(filename != NULL);
|
||||||
unlink(filename);
|
unlink(filename);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -742,27 +748,92 @@ free_and_fail:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Opens a file using a protocol (file, host_device, nbd, ...)
|
* Opens a file using a protocol (file, host_device, nbd, ...)
|
||||||
|
*
|
||||||
|
* options is a QDict of options to pass to the block drivers, or NULL for an
|
||||||
|
* empty set of options. The reference to the QDict belongs to the block layer
|
||||||
|
* after the call (even on failure), so if the caller intends to reuse the
|
||||||
|
* dictionary, it needs to use QINCREF() before calling bdrv_file_open.
|
||||||
*/
|
*/
|
||||||
int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
|
int bdrv_file_open(BlockDriverState **pbs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriver *drv;
|
BlockDriver *drv;
|
||||||
|
const char *drvname;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
drv = bdrv_find_protocol(filename);
|
/* NULL means an empty set of options */
|
||||||
if (!drv) {
|
if (options == NULL) {
|
||||||
return -ENOENT;
|
options = qdict_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_new("");
|
bs = bdrv_new("");
|
||||||
ret = bdrv_open_common(bs, NULL, filename, NULL, flags, drv);
|
bs->options = options;
|
||||||
if (ret < 0) {
|
options = qdict_clone_shallow(options);
|
||||||
bdrv_delete(bs);
|
|
||||||
return ret;
|
/* Find the right block driver */
|
||||||
|
drvname = qdict_get_try_str(options, "driver");
|
||||||
|
if (drvname) {
|
||||||
|
drv = bdrv_find_whitelisted_format(drvname);
|
||||||
|
qdict_del(options, "driver");
|
||||||
|
} else if (filename) {
|
||||||
|
drv = bdrv_find_protocol(filename);
|
||||||
|
} else {
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||||
|
"Must specify either driver or file");
|
||||||
|
drv = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!drv) {
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse the filename and open it */
|
||||||
|
if (drv->bdrv_parse_filename && filename) {
|
||||||
|
Error *local_err = NULL;
|
||||||
|
drv->bdrv_parse_filename(filename, options, &local_err);
|
||||||
|
if (error_is_set(&local_err)) {
|
||||||
|
qerror_report_err(local_err);
|
||||||
|
error_free(local_err);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else if (!drv->bdrv_parse_filename && !filename) {
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||||
|
"The '%s' block driver requires a file name",
|
||||||
|
drv->format_name);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = bdrv_open_common(bs, NULL, filename, options, flags, drv);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if any unknown options were used */
|
||||||
|
if (qdict_size(options) != 0) {
|
||||||
|
const QDictEntry *entry = qdict_first(options);
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block protocol '%s' doesn't "
|
||||||
|
"support the option '%s'",
|
||||||
|
drv->format_name, entry->key);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
QDECREF(options);
|
||||||
|
|
||||||
bs->growable = 1;
|
bs->growable = 1;
|
||||||
*pbs = bs;
|
*pbs = bs;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
QDECREF(options);
|
||||||
|
if (!bs->drv) {
|
||||||
|
QDECREF(bs->options);
|
||||||
|
}
|
||||||
|
bdrv_delete(bs);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdrv_open_backing_file(BlockDriverState *bs)
|
int bdrv_open_backing_file(BlockDriverState *bs)
|
||||||
@ -802,6 +873,25 @@ int bdrv_open_backing_file(BlockDriverState *bs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void extract_subqdict(QDict *src, QDict **dst, const char *start)
|
||||||
|
{
|
||||||
|
const QDictEntry *entry, *next;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
*dst = qdict_new();
|
||||||
|
entry = qdict_first(src);
|
||||||
|
|
||||||
|
while (entry != NULL) {
|
||||||
|
next = qdict_next(src, entry);
|
||||||
|
if (strstart(entry->key, start, &p)) {
|
||||||
|
qobject_incref(entry->value);
|
||||||
|
qdict_put_obj(*dst, p, entry->value);
|
||||||
|
qdict_del(src, entry->key);
|
||||||
|
}
|
||||||
|
entry = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Opens a disk image (raw, qcow2, vmdk, ...)
|
* Opens a disk image (raw, qcow2, vmdk, ...)
|
||||||
*
|
*
|
||||||
@ -817,6 +907,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
|
|||||||
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
|
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
|
||||||
char tmp_filename[PATH_MAX + 1];
|
char tmp_filename[PATH_MAX + 1];
|
||||||
BlockDriverState *file = NULL;
|
BlockDriverState *file = NULL;
|
||||||
|
QDict *file_options = NULL;
|
||||||
|
|
||||||
/* NULL means an empty set of options */
|
/* NULL means an empty set of options */
|
||||||
if (options == NULL) {
|
if (options == NULL) {
|
||||||
@ -831,9 +922,16 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
|
|||||||
BlockDriverState *bs1;
|
BlockDriverState *bs1;
|
||||||
int64_t total_size;
|
int64_t total_size;
|
||||||
BlockDriver *bdrv_qcow2;
|
BlockDriver *bdrv_qcow2;
|
||||||
QEMUOptionParameter *options;
|
QEMUOptionParameter *create_options;
|
||||||
char backing_filename[PATH_MAX];
|
char backing_filename[PATH_MAX];
|
||||||
|
|
||||||
|
if (qdict_size(options) != 0) {
|
||||||
|
error_report("Can't use snapshot=on with driver-specific options");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
/* if snapshot, we create a temporary backing file and open it
|
/* if snapshot, we create a temporary backing file and open it
|
||||||
instead of opening 'filename' directly */
|
instead of opening 'filename' directly */
|
||||||
|
|
||||||
@ -863,17 +961,19 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bdrv_qcow2 = bdrv_find_format("qcow2");
|
bdrv_qcow2 = bdrv_find_format("qcow2");
|
||||||
options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
|
create_options = parse_option_parameters("", bdrv_qcow2->create_options,
|
||||||
|
NULL);
|
||||||
|
|
||||||
set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
|
set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
|
||||||
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
|
set_option_parameter(create_options, BLOCK_OPT_BACKING_FILE,
|
||||||
|
backing_filename);
|
||||||
if (drv) {
|
if (drv) {
|
||||||
set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
|
set_option_parameter(create_options, BLOCK_OPT_BACKING_FMT,
|
||||||
drv->format_name);
|
drv->format_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
|
ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options);
|
||||||
free_option_parameters(options);
|
free_option_parameters(create_options);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -888,7 +988,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
|
|||||||
flags |= BDRV_O_ALLOW_RDWR;
|
flags |= BDRV_O_ALLOW_RDWR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_file_open(&file, filename, bdrv_open_flags(bs, flags));
|
extract_subqdict(options, &file_options, "file.");
|
||||||
|
|
||||||
|
ret = bdrv_file_open(&file, filename, file_options,
|
||||||
|
bdrv_open_flags(bs, flags));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -2487,10 +2590,6 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
|
|||||||
return -EACCES;
|
return -EACCES;
|
||||||
if (bdrv_in_use(bs))
|
if (bdrv_in_use(bs))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
/* There better not be any in-flight IOs when we truncate the device. */
|
|
||||||
bdrv_drain_all();
|
|
||||||
|
|
||||||
ret = drv->bdrv_truncate(bs, offset);
|
ret = drv->bdrv_truncate(bs, offset);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
|
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
|
||||||
|
@ -304,7 +304,8 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Valid blkdebug filenames look like blkdebug:path/to/config:path/to/image */
|
/* Valid blkdebug filenames look like blkdebug:path/to/config:path/to/image */
|
||||||
static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
|
static int blkdebug_open(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BDRVBlkdebugState *s = bs->opaque;
|
BDRVBlkdebugState *s = bs->opaque;
|
||||||
int ret;
|
int ret;
|
||||||
@ -335,7 +336,7 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
|
|||||||
s->state = 1;
|
s->state = 1;
|
||||||
|
|
||||||
/* Open the backing file */
|
/* Open the backing file */
|
||||||
ret = bdrv_file_open(&bs->file, filename, flags);
|
ret = bdrv_file_open(&bs->file, filename, NULL, flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,8 @@ static void GCC_FMT_ATTR(2, 3) blkverify_err(BlkverifyAIOCB *acb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Valid blkverify filenames look like blkverify:path/to/raw_image:path/to/image */
|
/* Valid blkverify filenames look like blkverify:path/to/raw_image:path/to/image */
|
||||||
static int blkverify_open(BlockDriverState *bs, const char *filename, int flags)
|
static int blkverify_open(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BDRVBlkverifyState *s = bs->opaque;
|
BDRVBlkverifyState *s = bs->opaque;
|
||||||
int ret;
|
int ret;
|
||||||
@ -89,7 +90,7 @@ static int blkverify_open(BlockDriverState *bs, const char *filename, int flags)
|
|||||||
|
|
||||||
raw = g_strdup(filename);
|
raw = g_strdup(filename);
|
||||||
raw[c - filename] = '\0';
|
raw[c - filename] = '\0';
|
||||||
ret = bdrv_file_open(&bs->file, raw, flags);
|
ret = bdrv_file_open(&bs->file, raw, NULL, flags);
|
||||||
g_free(raw);
|
g_free(raw);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -279,7 +279,7 @@ static int cow_create(const char *filename, QEMUOptionParameter *options)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_file_open(&cow_bs, filename, BDRV_O_RDWR);
|
ret = bdrv_file_open(&cow_bs, filename, NULL, BDRV_O_RDWR);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -335,7 +335,8 @@ static void curl_clean_state(CURLState *s)
|
|||||||
s->in_use = 0;
|
s->in_use = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int curl_open(BlockDriverState *bs, const char *filename, int flags)
|
static int curl_open(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BDRVCURLState *s = bs->opaque;
|
BDRVCURLState *s = bs->opaque;
|
||||||
CURLState *state = NULL;
|
CURLState *state = NULL;
|
||||||
|
13
block/dmg.c
13
block/dmg.c
@ -51,9 +51,16 @@ typedef struct BDRVDMGState {
|
|||||||
|
|
||||||
static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
|
static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||||
{
|
{
|
||||||
int len=strlen(filename);
|
int len;
|
||||||
if(len>4 && !strcmp(filename+len-4,".dmg"))
|
|
||||||
return 2;
|
if (!filename) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(filename);
|
||||||
|
if (len > 4 && !strcmp(filename + len - 4, ".dmg")) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ static int qemu_gluster_aio_flush_cb(void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int qemu_gluster_open(BlockDriverState *bs, const char *filename,
|
static int qemu_gluster_open(BlockDriverState *bs, const char *filename,
|
||||||
int bdrv_flags)
|
QDict *options, int bdrv_flags)
|
||||||
{
|
{
|
||||||
BDRVGlusterState *s = bs->opaque;
|
BDRVGlusterState *s = bs->opaque;
|
||||||
int open_flags = O_BINARY;
|
int open_flags = O_BINARY;
|
||||||
|
@ -1007,7 +1007,8 @@ out:
|
|||||||
* We support iscsi url's on the form
|
* We support iscsi url's on the form
|
||||||
* iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
|
* iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
|
||||||
*/
|
*/
|
||||||
static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
|
static int iscsi_open(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
IscsiLun *iscsilun = bs->opaque;
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
struct iscsi_context *iscsi = NULL;
|
struct iscsi_context *iscsi = NULL;
|
||||||
@ -1203,7 +1204,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options)
|
|||||||
bs.opaque = g_malloc0(sizeof(struct IscsiLun));
|
bs.opaque = g_malloc0(sizeof(struct IscsiLun));
|
||||||
iscsilun = bs.opaque;
|
iscsilun = bs.opaque;
|
||||||
|
|
||||||
ret = iscsi_open(&bs, filename, 0);
|
ret = iscsi_open(&bs, filename, NULL, 0);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
137
block/nbd.c
137
block/nbd.c
@ -32,6 +32,8 @@
|
|||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
|
#include "qapi/qmp/qjson.h"
|
||||||
|
#include "qapi/qmp/qint.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -65,17 +67,19 @@ typedef struct BDRVNBDState {
|
|||||||
Coroutine *recv_coroutine[MAX_NBD_REQUESTS];
|
Coroutine *recv_coroutine[MAX_NBD_REQUESTS];
|
||||||
struct nbd_reply reply;
|
struct nbd_reply reply;
|
||||||
|
|
||||||
int is_unix;
|
bool is_unix;
|
||||||
char *host_spec;
|
QemuOpts *socket_opts;
|
||||||
|
|
||||||
char *export_name; /* An NBD server may export several devices */
|
char *export_name; /* An NBD server may export several devices */
|
||||||
} BDRVNBDState;
|
} BDRVNBDState;
|
||||||
|
|
||||||
static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
|
static int nbd_parse_uri(const char *filename, QDict *options)
|
||||||
{
|
{
|
||||||
URI *uri;
|
URI *uri;
|
||||||
const char *p;
|
const char *p;
|
||||||
QueryParams *qp = NULL;
|
QueryParams *qp = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
bool is_unix;
|
||||||
|
|
||||||
uri = uri_parse(filename);
|
uri = uri_parse(filename);
|
||||||
if (!uri) {
|
if (!uri) {
|
||||||
@ -84,11 +88,11 @@ static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
|
|||||||
|
|
||||||
/* transport */
|
/* transport */
|
||||||
if (!strcmp(uri->scheme, "nbd")) {
|
if (!strcmp(uri->scheme, "nbd")) {
|
||||||
s->is_unix = false;
|
is_unix = false;
|
||||||
} else if (!strcmp(uri->scheme, "nbd+tcp")) {
|
} else if (!strcmp(uri->scheme, "nbd+tcp")) {
|
||||||
s->is_unix = false;
|
is_unix = false;
|
||||||
} else if (!strcmp(uri->scheme, "nbd+unix")) {
|
} else if (!strcmp(uri->scheme, "nbd+unix")) {
|
||||||
s->is_unix = true;
|
is_unix = true;
|
||||||
} else {
|
} else {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
@ -97,32 +101,35 @@ static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
|
|||||||
p = uri->path ? uri->path : "/";
|
p = uri->path ? uri->path : "/";
|
||||||
p += strspn(p, "/");
|
p += strspn(p, "/");
|
||||||
if (p[0]) {
|
if (p[0]) {
|
||||||
s->export_name = g_strdup(p);
|
qdict_put(options, "export", qstring_from_str(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
qp = query_params_parse(uri->query);
|
qp = query_params_parse(uri->query);
|
||||||
if (qp->n > 1 || (s->is_unix && !qp->n) || (!s->is_unix && qp->n)) {
|
if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->is_unix) {
|
if (is_unix) {
|
||||||
/* nbd+unix:///export?socket=path */
|
/* nbd+unix:///export?socket=path */
|
||||||
if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
|
if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
s->host_spec = g_strdup(qp->p[0].value);
|
qdict_put(options, "path", qstring_from_str(qp->p[0].value));
|
||||||
} else {
|
} else {
|
||||||
/* nbd[+tcp]://host:port/export */
|
/* nbd[+tcp]://host[:port]/export */
|
||||||
if (!uri->server) {
|
if (!uri->server) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!uri->port) {
|
|
||||||
uri->port = NBD_DEFAULT_PORT;
|
qdict_put(options, "host", qstring_from_str(uri->server));
|
||||||
|
if (uri->port) {
|
||||||
|
char* port_str = g_strdup_printf("%d", uri->port);
|
||||||
|
qdict_put(options, "port", qstring_from_str(port_str));
|
||||||
|
g_free(port_str);
|
||||||
}
|
}
|
||||||
s->host_spec = g_strdup_printf("%s:%d", uri->server, uri->port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -133,16 +140,29 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nbd_config(BDRVNBDState *s, const char *filename)
|
static void nbd_parse_filename(const char *filename, QDict *options,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
char *file;
|
char *file;
|
||||||
char *export_name;
|
char *export_name;
|
||||||
const char *host_spec;
|
const char *host_spec;
|
||||||
const char *unixpath;
|
const char *unixpath;
|
||||||
int err = -EINVAL;
|
|
||||||
|
if (qdict_haskey(options, "host")
|
||||||
|
|| qdict_haskey(options, "port")
|
||||||
|
|| qdict_haskey(options, "path"))
|
||||||
|
{
|
||||||
|
error_setg(errp, "host/port/path and a file name may not be specified "
|
||||||
|
"at the same time");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (strstr(filename, "://")) {
|
if (strstr(filename, "://")) {
|
||||||
return nbd_parse_uri(s, filename);
|
int ret = nbd_parse_uri(filename, options);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg(errp, "No valid URL specified");
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = g_strdup(filename);
|
file = g_strdup(filename);
|
||||||
@ -154,34 +174,79 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
|
|||||||
}
|
}
|
||||||
export_name[0] = 0; /* truncate 'file' */
|
export_name[0] = 0; /* truncate 'file' */
|
||||||
export_name += strlen(EN_OPTSTR);
|
export_name += strlen(EN_OPTSTR);
|
||||||
s->export_name = g_strdup(export_name);
|
|
||||||
|
qdict_put(options, "export", qstring_from_str(export_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* extract the host_spec - fail if it's not nbd:... */
|
/* extract the host_spec - fail if it's not nbd:... */
|
||||||
if (!strstart(file, "nbd:", &host_spec)) {
|
if (!strstart(file, "nbd:", &host_spec)) {
|
||||||
|
error_setg(errp, "File name string for NBD must start with 'nbd:'");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*host_spec) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* are we a UNIX or TCP socket? */
|
/* are we a UNIX or TCP socket? */
|
||||||
if (strstart(host_spec, "unix:", &unixpath)) {
|
if (strstart(host_spec, "unix:", &unixpath)) {
|
||||||
s->is_unix = true;
|
qdict_put(options, "path", qstring_from_str(unixpath));
|
||||||
s->host_spec = g_strdup(unixpath);
|
|
||||||
} else {
|
} else {
|
||||||
s->is_unix = false;
|
InetSocketAddress *addr = NULL;
|
||||||
s->host_spec = g_strdup(host_spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = 0;
|
addr = inet_parse(host_spec, errp);
|
||||||
|
if (error_is_set(errp)) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdict_put(options, "host", qstring_from_str(addr->host));
|
||||||
|
qdict_put(options, "port", qstring_from_str(addr->port));
|
||||||
|
qapi_free_InetSocketAddress(addr);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
g_free(file);
|
g_free(file);
|
||||||
if (err != 0) {
|
|
||||||
g_free(s->export_name);
|
|
||||||
g_free(s->host_spec);
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nbd_config(BDRVNBDState *s, QDict *options)
|
||||||
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
if (qdict_haskey(options, "path")) {
|
||||||
|
if (qdict_haskey(options, "host")) {
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR, "path and host may not "
|
||||||
|
"be used at the same time.");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
s->is_unix = true;
|
||||||
|
} else if (qdict_haskey(options, "host")) {
|
||||||
|
s->is_unix = false;
|
||||||
|
} else {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->socket_opts = qemu_opts_create_nofail(&socket_optslist);
|
||||||
|
|
||||||
|
qemu_opts_absorb_qdict(s->socket_opts, options, &local_err);
|
||||||
|
if (error_is_set(&local_err)) {
|
||||||
|
qerror_report_err(local_err);
|
||||||
|
error_free(local_err);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qemu_opt_get(s->socket_opts, "port")) {
|
||||||
|
qemu_opt_set_number(s->socket_opts, "port", NBD_DEFAULT_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
s->export_name = g_strdup(qdict_get_try_str(options, "export"));
|
||||||
|
if (s->export_name) {
|
||||||
|
qdict_del(options, "export");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void nbd_coroutine_start(BDRVNBDState *s, struct nbd_request *request)
|
static void nbd_coroutine_start(BDRVNBDState *s, struct nbd_request *request)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -328,9 +393,9 @@ static int nbd_establish_connection(BlockDriverState *bs)
|
|||||||
size_t blocksize;
|
size_t blocksize;
|
||||||
|
|
||||||
if (s->is_unix) {
|
if (s->is_unix) {
|
||||||
sock = unix_socket_outgoing(s->host_spec);
|
sock = unix_socket_outgoing(qemu_opt_get(s->socket_opts, "path"));
|
||||||
} else {
|
} else {
|
||||||
sock = tcp_socket_outgoing_spec(s->host_spec);
|
sock = tcp_socket_outgoing_opts(s->socket_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Failed to establish connection */
|
/* Failed to establish connection */
|
||||||
@ -376,7 +441,8 @@ static void nbd_teardown_connection(BlockDriverState *bs)
|
|||||||
closesocket(s->sock);
|
closesocket(s->sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
|
static int nbd_open(BlockDriverState *bs, const char* filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BDRVNBDState *s = bs->opaque;
|
BDRVNBDState *s = bs->opaque;
|
||||||
int result;
|
int result;
|
||||||
@ -385,7 +451,7 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
|
|||||||
qemu_co_mutex_init(&s->free_sema);
|
qemu_co_mutex_init(&s->free_sema);
|
||||||
|
|
||||||
/* Pop the config into our state object. Exit if invalid. */
|
/* Pop the config into our state object. Exit if invalid. */
|
||||||
result = nbd_config(s, filename);
|
result = nbd_config(s, options);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -549,7 +615,7 @@ static void nbd_close(BlockDriverState *bs)
|
|||||||
{
|
{
|
||||||
BDRVNBDState *s = bs->opaque;
|
BDRVNBDState *s = bs->opaque;
|
||||||
g_free(s->export_name);
|
g_free(s->export_name);
|
||||||
g_free(s->host_spec);
|
qemu_opts_del(s->socket_opts);
|
||||||
|
|
||||||
nbd_teardown_connection(bs);
|
nbd_teardown_connection(bs);
|
||||||
}
|
}
|
||||||
@ -565,6 +631,7 @@ static BlockDriver bdrv_nbd = {
|
|||||||
.format_name = "nbd",
|
.format_name = "nbd",
|
||||||
.protocol_name = "nbd",
|
.protocol_name = "nbd",
|
||||||
.instance_size = sizeof(BDRVNBDState),
|
.instance_size = sizeof(BDRVNBDState),
|
||||||
|
.bdrv_parse_filename = nbd_parse_filename,
|
||||||
.bdrv_file_open = nbd_open,
|
.bdrv_file_open = nbd_open,
|
||||||
.bdrv_co_readv = nbd_co_readv,
|
.bdrv_co_readv = nbd_co_readv,
|
||||||
.bdrv_co_writev = nbd_co_writev,
|
.bdrv_co_writev = nbd_co_writev,
|
||||||
@ -578,6 +645,7 @@ static BlockDriver bdrv_nbd_tcp = {
|
|||||||
.format_name = "nbd",
|
.format_name = "nbd",
|
||||||
.protocol_name = "nbd+tcp",
|
.protocol_name = "nbd+tcp",
|
||||||
.instance_size = sizeof(BDRVNBDState),
|
.instance_size = sizeof(BDRVNBDState),
|
||||||
|
.bdrv_parse_filename = nbd_parse_filename,
|
||||||
.bdrv_file_open = nbd_open,
|
.bdrv_file_open = nbd_open,
|
||||||
.bdrv_co_readv = nbd_co_readv,
|
.bdrv_co_readv = nbd_co_readv,
|
||||||
.bdrv_co_writev = nbd_co_writev,
|
.bdrv_co_writev = nbd_co_writev,
|
||||||
@ -591,6 +659,7 @@ static BlockDriver bdrv_nbd_unix = {
|
|||||||
.format_name = "nbd",
|
.format_name = "nbd",
|
||||||
.protocol_name = "nbd+unix",
|
.protocol_name = "nbd+unix",
|
||||||
.instance_size = sizeof(BDRVNBDState),
|
.instance_size = sizeof(BDRVNBDState),
|
||||||
|
.bdrv_parse_filename = nbd_parse_filename,
|
||||||
.bdrv_file_open = nbd_open,
|
.bdrv_file_open = nbd_open,
|
||||||
.bdrv_co_readv = nbd_co_readv,
|
.bdrv_co_readv = nbd_co_readv,
|
||||||
.bdrv_co_writev = nbd_co_writev,
|
.bdrv_co_writev = nbd_co_writev,
|
||||||
|
@ -679,7 +679,7 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_file_open(&qcow_bs, filename, BDRV_O_RDWR);
|
ret = bdrv_file_open(&qcow_bs, filename, NULL, BDRV_O_RDWR);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1254,7 +1254,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR);
|
ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -558,7 +558,7 @@ static int qed_create(const char *filename, uint32_t cluster_size,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR | BDRV_O_CACHE_WB);
|
ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -303,7 +303,8 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
|
static int raw_open(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BDRVRawState *s = bs->opaque;
|
BDRVRawState *s = bs->opaque;
|
||||||
|
|
||||||
@ -1292,7 +1293,8 @@ static int check_hdev_writable(BDRVRawState *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
|
static int hdev_open(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BDRVRawState *s = bs->opaque;
|
BDRVRawState *s = bs->opaque;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1530,7 +1532,8 @@ static BlockDriver bdrv_host_device = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
|
static int floppy_open(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BDRVRawState *s = bs->opaque;
|
BDRVRawState *s = bs->opaque;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1652,7 +1655,8 @@ static BlockDriver bdrv_host_floppy = {
|
|||||||
.bdrv_eject = floppy_eject,
|
.bdrv_eject = floppy_eject,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
|
static int cdrom_open(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BDRVRawState *s = bs->opaque;
|
BDRVRawState *s = bs->opaque;
|
||||||
|
|
||||||
@ -1760,7 +1764,8 @@ static BlockDriver bdrv_host_cdrom = {
|
|||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
|
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
|
static int cdrom_open(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BDRVRawState *s = bs->opaque;
|
BDRVRawState *s = bs->opaque;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1126,7 +1126,8 @@ static int write_object(int fd, char *buf, uint64_t oid, int copies,
|
|||||||
create, cache_flags);
|
create, cache_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sd_open(BlockDriverState *bs, const char *filename, int flags)
|
static int sd_open(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
int ret, fd;
|
int ret, fd;
|
||||||
uint32_t vid = 0;
|
uint32_t vid = 0;
|
||||||
@ -1269,7 +1270,7 @@ static int sd_prealloc(const char *filename)
|
|||||||
void *buf = g_malloc0(SD_DATA_OBJ_SIZE);
|
void *buf = g_malloc0(SD_DATA_OBJ_SIZE);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR);
|
ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1367,7 +1368,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_file_open(&bs, backing_file, 0);
|
ret = bdrv_file_open(&bs, backing_file, NULL, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -661,7 +661,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
|||||||
|
|
||||||
path_combine(extent_path, sizeof(extent_path),
|
path_combine(extent_path, sizeof(extent_path),
|
||||||
desc_file_path, fname);
|
desc_file_path, fname);
|
||||||
ret = bdrv_file_open(&extent_file, extent_path, bs->open_flags);
|
ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -988,7 +988,8 @@ static void vvfat_rebind(BlockDriverState *bs)
|
|||||||
s->bs = bs;
|
s->bs = bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
|
static int vvfat_open(BlockDriverState *bs, const char* dirname,
|
||||||
|
QDict *options, int flags)
|
||||||
{
|
{
|
||||||
BDRVVVFATState *s = bs->opaque;
|
BDRVVVFATState *s = bs->opaque;
|
||||||
int i, cyls, heads, secs;
|
int i, cyls, heads, secs;
|
||||||
|
13
blockdev.c
13
blockdev.c
@ -658,7 +658,11 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if (!file || !*file) {
|
if (!file || !*file) {
|
||||||
return dinfo;
|
if (qdict_size(bs_opts)) {
|
||||||
|
file = NULL;
|
||||||
|
} else {
|
||||||
|
return dinfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (snapshot) {
|
if (snapshot) {
|
||||||
/* always use cache=unsafe with snapshot */
|
/* always use cache=unsafe with snapshot */
|
||||||
@ -697,10 +701,10 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ret == -EMEDIUMTYPE) {
|
if (ret == -EMEDIUMTYPE) {
|
||||||
error_report("could not open disk image %s: not in %s format",
|
error_report("could not open disk image %s: not in %s format",
|
||||||
file, drv->format_name);
|
file ?: dinfo->id, drv->format_name);
|
||||||
} else {
|
} else {
|
||||||
error_report("could not open disk image %s: %s",
|
error_report("could not open disk image %s: %s",
|
||||||
file, strerror(-ret));
|
file ?: dinfo->id, strerror(-ret));
|
||||||
}
|
}
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -1127,6 +1131,9 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* complete all in-flight operations before resizing the device */
|
||||||
|
bdrv_drain_all();
|
||||||
|
|
||||||
switch (bdrv_truncate(bs, size)) {
|
switch (bdrv_truncate(bs, size)) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
@ -135,7 +135,8 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
|
|||||||
void bdrv_delete(BlockDriverState *bs);
|
void bdrv_delete(BlockDriverState *bs);
|
||||||
int bdrv_parse_cache_flags(const char *mode, int *flags);
|
int bdrv_parse_cache_flags(const char *mode, int *flags);
|
||||||
int bdrv_parse_discard_flags(const char *mode, int *flags);
|
int bdrv_parse_discard_flags(const char *mode, int *flags);
|
||||||
int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
|
int bdrv_file_open(BlockDriverState **pbs, const char *filename,
|
||||||
|
QDict *options, int flags);
|
||||||
int bdrv_open_backing_file(BlockDriverState *bs);
|
int bdrv_open_backing_file(BlockDriverState *bs);
|
||||||
int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
|
int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
|
||||||
int flags, BlockDriver *drv);
|
int flags, BlockDriver *drv);
|
||||||
|
@ -76,6 +76,10 @@ struct BlockDriver {
|
|||||||
int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
|
int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
|
||||||
int (*bdrv_probe_device)(const char *filename);
|
int (*bdrv_probe_device)(const char *filename);
|
||||||
|
|
||||||
|
/* Any driver implementing this callback is expected to be able to handle
|
||||||
|
* NULL file names in its .bdrv_open() implementation */
|
||||||
|
void (*bdrv_parse_filename)(const char *filename, QDict *options, Error **errp);
|
||||||
|
|
||||||
/* For handling image reopen for split or non-split files */
|
/* For handling image reopen for split or non-split files */
|
||||||
int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
|
int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
|
||||||
BlockReopenQueue *queue, Error **errp);
|
BlockReopenQueue *queue, Error **errp);
|
||||||
@ -83,7 +87,8 @@ struct BlockDriver {
|
|||||||
void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
|
void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
|
||||||
|
|
||||||
int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags);
|
int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags);
|
||||||
int (*bdrv_file_open)(BlockDriverState *bs, const char *filename, int flags);
|
int (*bdrv_file_open)(BlockDriverState *bs, const char *filename,
|
||||||
|
QDict *options, int flags);
|
||||||
int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
|
int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
|
||||||
uint8_t *buf, int nb_sectors);
|
uint8_t *buf, int nb_sectors);
|
||||||
int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
|
int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
#include "qemu/option.h"
|
||||||
|
|
||||||
struct nbd_request {
|
struct nbd_request {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
@ -60,10 +61,9 @@ enum {
|
|||||||
#define NBD_BUFFER_SIZE (1024*1024)
|
#define NBD_BUFFER_SIZE (1024*1024)
|
||||||
|
|
||||||
ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read);
|
ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read);
|
||||||
int tcp_socket_outgoing(const char *address, uint16_t port);
|
|
||||||
int tcp_socket_incoming(const char *address, uint16_t port);
|
int tcp_socket_incoming(const char *address, uint16_t port);
|
||||||
int tcp_socket_outgoing_spec(const char *address_and_port);
|
|
||||||
int tcp_socket_incoming_spec(const char *address_and_port);
|
int tcp_socket_incoming_spec(const char *address_and_port);
|
||||||
|
int tcp_socket_outgoing_opts(QemuOpts *opts);
|
||||||
int unix_socket_outgoing(const char *path);
|
int unix_socket_outgoing(const char *path);
|
||||||
int unix_socket_incoming(const char *path);
|
int unix_socket_incoming(const char *path);
|
||||||
|
|
||||||
|
@ -30,6 +30,8 @@ int inet_aton(const char *cp, struct in_addr *ia);
|
|||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
#include "qapi/qmp/qerror.h"
|
||||||
|
|
||||||
|
extern QemuOptsList socket_optslist;
|
||||||
|
|
||||||
/* misc helpers */
|
/* misc helpers */
|
||||||
int qemu_socket(int domain, int type, int protocol);
|
int qemu_socket(int domain, int type, int protocol);
|
||||||
int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||||
@ -45,6 +47,7 @@ int recv_all(int fd, void *buf, int len1, bool single_read);
|
|||||||
*/
|
*/
|
||||||
typedef void NonBlockingConnectHandler(int fd, void *opaque);
|
typedef void NonBlockingConnectHandler(int fd, void *opaque);
|
||||||
|
|
||||||
|
InetSocketAddress *inet_parse(const char *str, Error **errp);
|
||||||
int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp);
|
int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp);
|
||||||
int inet_listen(const char *str, char *ostr, int olen,
|
int inet_listen(const char *str, char *ostr, int olen,
|
||||||
int socktype, int port_offset, Error **errp);
|
int socktype, int port_offset, Error **errp);
|
||||||
|
13
nbd.c
13
nbd.c
@ -199,22 +199,15 @@ static void combine_addr(char *buf, size_t len, const char* address,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int tcp_socket_outgoing(const char *address, uint16_t port)
|
int tcp_socket_outgoing_opts(QemuOpts *opts)
|
||||||
{
|
|
||||||
char address_and_port[128];
|
|
||||||
combine_addr(address_and_port, 128, address, port);
|
|
||||||
return tcp_socket_outgoing_spec(address_and_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
int tcp_socket_outgoing_spec(const char *address_and_port)
|
|
||||||
{
|
{
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
int fd = inet_connect(address_and_port, &local_err);
|
int fd = inet_connect_opts(opts, &local_err, NULL, NULL);
|
||||||
|
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
qerror_report_err(local_err);
|
qerror_report_err(local_err);
|
||||||
error_free(local_err);
|
error_free(local_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1766,7 +1766,7 @@ static int openfile(char *name, int flags, int growable)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (growable) {
|
if (growable) {
|
||||||
if (bdrv_file_open(&bs, name, flags)) {
|
if (bdrv_file_open(&bs, name, NULL, flags)) {
|
||||||
fprintf(stderr, "%s: can't open device %s\n", progname, name);
|
fprintf(stderr, "%s: can't open device %s\n", progname, name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,10 @@
|
|||||||
|
|
||||||
static const int on=1, off=0;
|
static const int on=1, off=0;
|
||||||
|
|
||||||
/* used temporarely until all users are converted to QemuOpts */
|
/* used temporarily until all users are converted to QemuOpts */
|
||||||
static QemuOptsList dummy_opts = {
|
QemuOptsList socket_optslist = {
|
||||||
.name = "dummy",
|
.name = "socket",
|
||||||
.head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
|
.head = QTAILQ_HEAD_INITIALIZER(socket_optslist.head),
|
||||||
.desc = {
|
.desc = {
|
||||||
{
|
{
|
||||||
.name = "path",
|
.name = "path",
|
||||||
@ -485,7 +485,7 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* compatibility wrapper */
|
/* compatibility wrapper */
|
||||||
static InetSocketAddress *inet_parse(const char *str, Error **errp)
|
InetSocketAddress *inet_parse(const char *str, Error **errp)
|
||||||
{
|
{
|
||||||
InetSocketAddress *addr;
|
InetSocketAddress *addr;
|
||||||
const char *optstr, *h;
|
const char *optstr, *h;
|
||||||
@ -555,7 +555,7 @@ fail:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inet_addr_to_opts(QemuOpts *opts, InetSocketAddress *addr)
|
static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr)
|
||||||
{
|
{
|
||||||
bool ipv4 = addr->ipv4 || !addr->has_ipv4;
|
bool ipv4 = addr->ipv4 || !addr->has_ipv4;
|
||||||
bool ipv6 = addr->ipv6 || !addr->has_ipv6;
|
bool ipv6 = addr->ipv6 || !addr->has_ipv6;
|
||||||
@ -583,7 +583,7 @@ int inet_listen(const char *str, char *ostr, int olen,
|
|||||||
|
|
||||||
addr = inet_parse(str, errp);
|
addr = inet_parse(str, errp);
|
||||||
if (addr != NULL) {
|
if (addr != NULL) {
|
||||||
opts = qemu_opts_create_nofail(&dummy_opts);
|
opts = qemu_opts_create_nofail(&socket_optslist);
|
||||||
inet_addr_to_opts(opts, addr);
|
inet_addr_to_opts(opts, addr);
|
||||||
qapi_free_InetSocketAddress(addr);
|
qapi_free_InetSocketAddress(addr);
|
||||||
sock = inet_listen_opts(opts, port_offset, errp);
|
sock = inet_listen_opts(opts, port_offset, errp);
|
||||||
@ -622,7 +622,7 @@ int inet_connect(const char *str, Error **errp)
|
|||||||
|
|
||||||
addr = inet_parse(str, errp);
|
addr = inet_parse(str, errp);
|
||||||
if (addr != NULL) {
|
if (addr != NULL) {
|
||||||
opts = qemu_opts_create_nofail(&dummy_opts);
|
opts = qemu_opts_create_nofail(&socket_optslist);
|
||||||
inet_addr_to_opts(opts, addr);
|
inet_addr_to_opts(opts, addr);
|
||||||
qapi_free_InetSocketAddress(addr);
|
qapi_free_InetSocketAddress(addr);
|
||||||
sock = inet_connect_opts(opts, errp, NULL, NULL);
|
sock = inet_connect_opts(opts, errp, NULL, NULL);
|
||||||
@ -656,7 +656,7 @@ int inet_nonblocking_connect(const char *str,
|
|||||||
|
|
||||||
addr = inet_parse(str, errp);
|
addr = inet_parse(str, errp);
|
||||||
if (addr != NULL) {
|
if (addr != NULL) {
|
||||||
opts = qemu_opts_create_nofail(&dummy_opts);
|
opts = qemu_opts_create_nofail(&socket_optslist);
|
||||||
inet_addr_to_opts(opts, addr);
|
inet_addr_to_opts(opts, addr);
|
||||||
qapi_free_InetSocketAddress(addr);
|
qapi_free_InetSocketAddress(addr);
|
||||||
sock = inet_connect_opts(opts, errp, callback, opaque);
|
sock = inet_connect_opts(opts, errp, callback, opaque);
|
||||||
@ -799,7 +799,7 @@ int unix_listen(const char *str, char *ostr, int olen, Error **errp)
|
|||||||
char *path, *optstr;
|
char *path, *optstr;
|
||||||
int sock, len;
|
int sock, len;
|
||||||
|
|
||||||
opts = qemu_opts_create_nofail(&dummy_opts);
|
opts = qemu_opts_create_nofail(&socket_optslist);
|
||||||
|
|
||||||
optstr = strchr(str, ',');
|
optstr = strchr(str, ',');
|
||||||
if (optstr) {
|
if (optstr) {
|
||||||
@ -827,7 +827,7 @@ int unix_connect(const char *path, Error **errp)
|
|||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
int sock;
|
int sock;
|
||||||
|
|
||||||
opts = qemu_opts_create_nofail(&dummy_opts);
|
opts = qemu_opts_create_nofail(&socket_optslist);
|
||||||
qemu_opt_set(opts, "path", path);
|
qemu_opt_set(opts, "path", path);
|
||||||
sock = unix_connect_opts(opts, errp, NULL, NULL);
|
sock = unix_connect_opts(opts, errp, NULL, NULL);
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
@ -844,7 +844,7 @@ int unix_nonblocking_connect(const char *path,
|
|||||||
|
|
||||||
g_assert(callback != NULL);
|
g_assert(callback != NULL);
|
||||||
|
|
||||||
opts = qemu_opts_create_nofail(&dummy_opts);
|
opts = qemu_opts_create_nofail(&socket_optslist);
|
||||||
qemu_opt_set(opts, "path", path);
|
qemu_opt_set(opts, "path", path);
|
||||||
sock = unix_connect_opts(opts, errp, callback, opaque);
|
sock = unix_connect_opts(opts, errp, callback, opaque);
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
@ -895,7 +895,7 @@ int socket_connect(SocketAddress *addr, Error **errp,
|
|||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
opts = qemu_opts_create_nofail(&dummy_opts);
|
opts = qemu_opts_create_nofail(&socket_optslist);
|
||||||
switch (addr->kind) {
|
switch (addr->kind) {
|
||||||
case SOCKET_ADDRESS_KIND_INET:
|
case SOCKET_ADDRESS_KIND_INET:
|
||||||
inet_addr_to_opts(opts, addr->inet);
|
inet_addr_to_opts(opts, addr->inet);
|
||||||
@ -926,7 +926,7 @@ int socket_listen(SocketAddress *addr, Error **errp)
|
|||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
opts = qemu_opts_create_nofail(&dummy_opts);
|
opts = qemu_opts_create_nofail(&socket_optslist);
|
||||||
switch (addr->kind) {
|
switch (addr->kind) {
|
||||||
case SOCKET_ADDRESS_KIND_INET:
|
case SOCKET_ADDRESS_KIND_INET:
|
||||||
inet_addr_to_opts(opts, addr->inet);
|
inet_addr_to_opts(opts, addr->inet);
|
||||||
@ -954,7 +954,7 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
|
|||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
opts = qemu_opts_create_nofail(&dummy_opts);
|
opts = qemu_opts_create_nofail(&socket_optslist);
|
||||||
switch (remote->kind) {
|
switch (remote->kind) {
|
||||||
case SOCKET_ADDRESS_KIND_INET:
|
case SOCKET_ADDRESS_KIND_INET:
|
||||||
qemu_opt_set(opts, "host", remote->inet->host);
|
qemu_opt_set(opts, "host", remote->inet->host);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user