Block patches for 2.9-rc3
-----BEGIN PGP SIGNATURE----- iQFGBAABCAAwFiEEkb62CjDbPohX0Rgp9AfbAGHVz0AFAljiam0SHG1yZWl0ekBy ZWRoYXQuY29tAAoJEPQH2wBh1c9AXr4H/0ckwgS+VDSkVfo1/vE/DjAOcBQkV933 OXosPbSAOVQSbDLkfooMJ8FzdYCDlGANuFMLtZkEe0FJVOGqb9CGaWkclSlw/RaT W3XJLpITfWpsBlt5/6a3U1lhD4cpB1nQ8GJ2YK6P6eU/jLp4wn6lycjimo2jiGIT 3tfi8hIwxFgR+/BT4LwlfjvB1khzreHbTynFMBex9YPx77pu62pxJoCne01JrpVh I1hL9my/c4Fux1LOnXopIAo4p5I4aW5YLwAWtdku1x3CTPprdW82Q9KCxSxOCMZ/ yyLjSIgJQPWNDbOminXmOSQ0UC01RZeX7ruvx6k+vepFlLvuBFrHHeo= =u0Qt -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2017-04-03' into staging Block patches for 2.9-rc3 # gpg: Signature made Mon 03 Apr 2017 16:29:49 BST # gpg: using RSA key 0xF407DB0061D5CF40 # gpg: Good signature from "Max Reitz <mreitz@redhat.com>" # Primary key fingerprint: 91BE B60A 30DB 3E88 57D1 1829 F407 DB00 61D5 CF40 * remotes/maxreitz/tags/pull-block-2017-04-03: block/parallels: Avoid overflows iotests: Improve image-clear tests on non-aligned image qcow2: Discard unaligned tail when wiping image iotests: fix 097 when run with qcow qemu-io-cmds: Assert that global and nofile commands don't use ct->perms sheepdog: Fix blockdev-add nbd: Tidy up blockdev-add interface sockets: New helper socket_address_crumple() qapi-schema: SocketAddressFlat variants 'vsock' and 'fd' gluster: Prepare for SocketAddressFlat extension block: Document -drive problematic code and bugs io vnc sockets: Clean up SocketAddressKind switches char: Fix socket with "type": "vsock" address nbd sockets vnc: Mark problematic address family tests TODO block: add missed aio_context_acquire into release_drive Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
b1a419ec79
48
block.c
48
block.c
@ -1157,6 +1157,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
|
||||
if (file != NULL) {
|
||||
filename = blk_bs(file)->filename;
|
||||
} else {
|
||||
/*
|
||||
* Caution: while qdict_get_try_str() is fine, getting
|
||||
* non-string types would require more care. When @options
|
||||
* come from -blockdev or blockdev_add, its members are typed
|
||||
* according to the QAPI schema, but when they come from
|
||||
* -drive, they're all QString.
|
||||
*/
|
||||
filename = qdict_get_try_str(options, "filename");
|
||||
}
|
||||
|
||||
@ -1324,6 +1331,13 @@ static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
BlockDriver *drv = NULL;
|
||||
Error *local_err = NULL;
|
||||
|
||||
/*
|
||||
* Caution: while qdict_get_try_str() is fine, getting non-string
|
||||
* types would require more care. When @options come from
|
||||
* -blockdev or blockdev_add, its members are typed according to
|
||||
* the QAPI schema, but when they come from -drive, they're all
|
||||
* QString.
|
||||
*/
|
||||
drvname = qdict_get_try_str(*options, "driver");
|
||||
if (drvname) {
|
||||
drv = bdrv_find_format(drvname);
|
||||
@ -1358,6 +1372,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
}
|
||||
|
||||
/* Find the right block driver */
|
||||
/* See cautionary note on accessing @options above */
|
||||
filename = qdict_get_try_str(*options, "filename");
|
||||
|
||||
if (!drvname && protocol) {
|
||||
@ -1987,6 +2002,13 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
qdict_extract_subqdict(parent_options, &options, bdref_key_dot);
|
||||
g_free(bdref_key_dot);
|
||||
|
||||
/*
|
||||
* Caution: while qdict_get_try_str() is fine, getting non-string
|
||||
* types would require more care. When @parent_options come from
|
||||
* -blockdev or blockdev_add, its members are typed according to
|
||||
* the QAPI schema, but when they come from -drive, they're all
|
||||
* QString.
|
||||
*/
|
||||
reference = qdict_get_try_str(parent_options, bdref_key);
|
||||
if (reference || qdict_haskey(options, "file.filename")) {
|
||||
backing_filename[0] = '\0';
|
||||
@ -2059,6 +2081,13 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||
qdict_extract_subqdict(options, &image_options, bdref_key_dot);
|
||||
g_free(bdref_key_dot);
|
||||
|
||||
/*
|
||||
* Caution: while qdict_get_try_str() is fine, getting non-string
|
||||
* types would require more care. When @options come from
|
||||
* -blockdev or blockdev_add, its members are typed according to
|
||||
* the QAPI schema, but when they come from -drive, they're all
|
||||
* QString.
|
||||
*/
|
||||
reference = qdict_get_try_str(options, bdref_key);
|
||||
if (!filename && !reference && !qdict_size(image_options)) {
|
||||
if (!allow_none) {
|
||||
@ -2274,9 +2303,13 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set the BDRV_O_RDWR and BDRV_O_ALLOW_RDWR flags.
|
||||
* FIXME: we're parsing the QDict to avoid having to create a
|
||||
* QemuOpts just for this, but neither option is optimal. */
|
||||
/*
|
||||
* Set the BDRV_O_RDWR and BDRV_O_ALLOW_RDWR flags.
|
||||
* Caution: getting a boolean member of @options requires care.
|
||||
* When @options come from -blockdev or blockdev_add, members are
|
||||
* typed according to the QAPI schema, but when they come from
|
||||
* -drive, they're all QString.
|
||||
*/
|
||||
if (g_strcmp0(qdict_get_try_str(options, BDRV_OPT_READ_ONLY), "on") &&
|
||||
!qdict_get_try_bool(options, BDRV_OPT_READ_ONLY, false)) {
|
||||
flags |= (BDRV_O_RDWR | BDRV_O_ALLOW_RDWR);
|
||||
@ -2298,6 +2331,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
options = qdict_clone_shallow(options);
|
||||
|
||||
/* Find the right image format driver */
|
||||
/* See cautionary note on accessing @options above */
|
||||
drvname = qdict_get_try_str(options, "driver");
|
||||
if (drvname) {
|
||||
drv = bdrv_find_format(drvname);
|
||||
@ -2309,6 +2343,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
|
||||
assert(drvname || !(flags & BDRV_O_PROTOCOL));
|
||||
|
||||
/* See cautionary note on accessing @options above */
|
||||
backing = qdict_get_try_str(options, "backing");
|
||||
if (backing && *backing == '\0') {
|
||||
flags |= BDRV_O_NO_BACKING;
|
||||
@ -2787,6 +2822,13 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
||||
do {
|
||||
QString *new_obj = qobject_to_qstring(entry->value);
|
||||
const char *new = qstring_get_str(new_obj);
|
||||
/*
|
||||
* Caution: while qdict_get_try_str() is fine, getting
|
||||
* non-string types would require more care. When
|
||||
* bs->options come from -blockdev or blockdev_add, its
|
||||
* members are typed according to the QAPI schema, but
|
||||
* when they come from -drive, they're all QString.
|
||||
*/
|
||||
const char *old = qdict_get_try_str(reopen_state->bs->options,
|
||||
entry->key);
|
||||
|
||||
|
@ -2193,6 +2193,12 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
int ret;
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
/*
|
||||
* Caution: while qdict_get_str() is fine, getting non-string types
|
||||
* would require more care. When @options come from -blockdev or
|
||||
* blockdev_add, its members are typed according to the QAPI
|
||||
* schema, but when they come from -drive, they're all QString.
|
||||
*/
|
||||
const char *filename = qdict_get_str(options, "filename");
|
||||
char bsd_path[MAXPATHLEN] = "";
|
||||
bool error_occurred = false;
|
||||
|
@ -412,10 +412,12 @@ static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf,
|
||||
glfs_set_preopened(gconf->volume, glfs);
|
||||
|
||||
for (server = gconf->server; server; server = server->next) {
|
||||
if (server->value->type == SOCKET_ADDRESS_FLAT_TYPE_UNIX) {
|
||||
switch (server->value->type) {
|
||||
case SOCKET_ADDRESS_FLAT_TYPE_UNIX:
|
||||
ret = glfs_set_volfile_server(glfs, "unix",
|
||||
server->value->u.q_unix.path, 0);
|
||||
} else {
|
||||
break;
|
||||
case SOCKET_ADDRESS_FLAT_TYPE_INET:
|
||||
if (parse_uint_full(server->value->u.inet.port, &port, 10) < 0 ||
|
||||
port > 65535) {
|
||||
error_setg(errp, "'%s' is not a valid port number",
|
||||
@ -426,6 +428,11 @@ static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf,
|
||||
ret = glfs_set_volfile_server(glfs, "tcp",
|
||||
server->value->u.inet.host,
|
||||
(int)port);
|
||||
break;
|
||||
case SOCKET_ADDRESS_FLAT_TYPE_VSOCK:
|
||||
case SOCKET_ADDRESS_FLAT_TYPE_FD:
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
@ -487,7 +494,7 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf,
|
||||
char *str = NULL;
|
||||
const char *ptr;
|
||||
size_t num_servers;
|
||||
int i;
|
||||
int i, type;
|
||||
|
||||
/* create opts info from runtime_json_opts list */
|
||||
opts = qemu_opts_create(&runtime_json_opts, NULL, 0, &error_abort);
|
||||
@ -539,16 +546,17 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf,
|
||||
if (!strcmp(ptr, "tcp")) {
|
||||
ptr = "inet"; /* accept legacy "tcp" */
|
||||
}
|
||||
gsconf->type = qapi_enum_parse(SocketAddressFlatType_lookup, ptr,
|
||||
SOCKET_ADDRESS_FLAT_TYPE__MAX, -1,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_append_hint(&local_err,
|
||||
"Parameter '%s' may be 'inet' or 'unix'\n",
|
||||
GLUSTER_OPT_TYPE);
|
||||
type = qapi_enum_parse(SocketAddressFlatType_lookup, ptr,
|
||||
SOCKET_ADDRESS_FLAT_TYPE__MAX, -1, NULL);
|
||||
if (type != SOCKET_ADDRESS_FLAT_TYPE_INET
|
||||
&& type != SOCKET_ADDRESS_FLAT_TYPE_UNIX) {
|
||||
error_setg(&local_err,
|
||||
"Parameter '%s' may be 'inet' or 'unix'",
|
||||
GLUSTER_OPT_TYPE);
|
||||
error_append_hint(&local_err, GERR_INDEX_HINT, i);
|
||||
goto out;
|
||||
}
|
||||
gsconf->type = type;
|
||||
qemu_opts_del(opts);
|
||||
|
||||
if (gsconf->type == SOCKET_ADDRESS_FLAT_TYPE_INET) {
|
||||
|
62
block/nbd.c
62
block/nbd.c
@ -47,7 +47,7 @@ typedef struct BDRVNBDState {
|
||||
NBDClientSession client;
|
||||
|
||||
/* For nbd_refresh_filename() */
|
||||
SocketAddress *saddr;
|
||||
SocketAddressFlat *saddr;
|
||||
char *export, *tlscredsid;
|
||||
} BDRVNBDState;
|
||||
|
||||
@ -95,7 +95,7 @@ static int nbd_parse_uri(const char *filename, QDict *options)
|
||||
goto out;
|
||||
}
|
||||
qdict_put(options, "server.type", qstring_from_str("unix"));
|
||||
qdict_put(options, "server.data.path",
|
||||
qdict_put(options, "server.path",
|
||||
qstring_from_str(qp->p[0].value));
|
||||
} else {
|
||||
QString *host;
|
||||
@ -116,10 +116,10 @@ static int nbd_parse_uri(const char *filename, QDict *options)
|
||||
}
|
||||
|
||||
qdict_put(options, "server.type", qstring_from_str("inet"));
|
||||
qdict_put(options, "server.data.host", host);
|
||||
qdict_put(options, "server.host", host);
|
||||
|
||||
port_str = g_strdup_printf("%d", uri->port ?: NBD_DEFAULT_PORT);
|
||||
qdict_put(options, "server.data.port", qstring_from_str(port_str));
|
||||
qdict_put(options, "server.port", qstring_from_str(port_str));
|
||||
g_free(port_str);
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ static void nbd_parse_filename(const char *filename, QDict *options,
|
||||
/* are we a UNIX or TCP socket? */
|
||||
if (strstart(host_spec, "unix:", &unixpath)) {
|
||||
qdict_put(options, "server.type", qstring_from_str("unix"));
|
||||
qdict_put(options, "server.data.path", qstring_from_str(unixpath));
|
||||
qdict_put(options, "server.path", qstring_from_str(unixpath));
|
||||
} else {
|
||||
InetSocketAddress *addr = NULL;
|
||||
|
||||
@ -207,8 +207,8 @@ static void nbd_parse_filename(const char *filename, QDict *options,
|
||||
}
|
||||
|
||||
qdict_put(options, "server.type", qstring_from_str("inet"));
|
||||
qdict_put(options, "server.data.host", qstring_from_str(addr->host));
|
||||
qdict_put(options, "server.data.port", qstring_from_str(addr->port));
|
||||
qdict_put(options, "server.host", qstring_from_str(addr->host));
|
||||
qdict_put(options, "server.port", qstring_from_str(addr->port));
|
||||
qapi_free_InetSocketAddress(addr);
|
||||
}
|
||||
|
||||
@ -248,20 +248,21 @@ static bool nbd_process_legacy_socket_options(QDict *output_options,
|
||||
}
|
||||
|
||||
qdict_put(output_options, "server.type", qstring_from_str("unix"));
|
||||
qdict_put(output_options, "server.data.path", qstring_from_str(path));
|
||||
qdict_put(output_options, "server.path", qstring_from_str(path));
|
||||
} else if (host) {
|
||||
qdict_put(output_options, "server.type", qstring_from_str("inet"));
|
||||
qdict_put(output_options, "server.data.host", qstring_from_str(host));
|
||||
qdict_put(output_options, "server.data.port",
|
||||
qdict_put(output_options, "server.host", qstring_from_str(host));
|
||||
qdict_put(output_options, "server.port",
|
||||
qstring_from_str(port ?: stringify(NBD_DEFAULT_PORT)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, Error **errp)
|
||||
static SocketAddressFlat *nbd_config(BDRVNBDState *s, QDict *options,
|
||||
Error **errp)
|
||||
{
|
||||
SocketAddress *saddr = NULL;
|
||||
SocketAddressFlat *saddr = NULL;
|
||||
QDict *addr = NULL;
|
||||
QObject *crumpled_addr = NULL;
|
||||
Visitor *iv = NULL;
|
||||
@ -278,8 +279,16 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, Error **errp)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive
|
||||
* server.type=inet. .to doesn't matter, it's ignored anyway.
|
||||
* That's because when @options come from -blockdev or
|
||||
* blockdev_add, members are typed according to the QAPI schema,
|
||||
* but when they come from -drive, they're all QString. The
|
||||
* visitor expects the former.
|
||||
*/
|
||||
iv = qobject_input_visitor_new(crumpled_addr);
|
||||
visit_type_SocketAddress(iv, NULL, &saddr, &local_err);
|
||||
visit_type_SocketAddressFlat(iv, NULL, &saddr, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
goto done;
|
||||
@ -298,9 +307,10 @@ NBDClientSession *nbd_get_client_session(BlockDriverState *bs)
|
||||
return &s->client;
|
||||
}
|
||||
|
||||
static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr,
|
||||
static QIOChannelSocket *nbd_establish_connection(SocketAddressFlat *saddr_flat,
|
||||
Error **errp)
|
||||
{
|
||||
SocketAddress *saddr = socket_address_crumple(saddr_flat);
|
||||
QIOChannelSocket *sioc;
|
||||
Error *local_err = NULL;
|
||||
|
||||
@ -310,6 +320,7 @@ static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr,
|
||||
qio_channel_socket_connect_sync(sioc,
|
||||
saddr,
|
||||
&local_err);
|
||||
qapi_free_SocketAddress(saddr);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return NULL;
|
||||
@ -401,7 +412,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Translate @host, @port, and @path to a SocketAddress */
|
||||
/* Translate @host, @port, and @path to a SocketAddressFlat */
|
||||
if (!nbd_process_legacy_socket_options(options, opts, errp)) {
|
||||
goto error;
|
||||
}
|
||||
@ -421,11 +432,12 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (s->saddr->type != SOCKET_ADDRESS_KIND_INET) {
|
||||
/* TODO SOCKET_ADDRESS_KIND_FD where fd has AF_INET or AF_INET6 */
|
||||
if (s->saddr->type != SOCKET_ADDRESS_FLAT_TYPE_INET) {
|
||||
error_setg(errp, "TLS only supported over IP sockets");
|
||||
goto error;
|
||||
}
|
||||
hostname = s->saddr->u.inet.data->host;
|
||||
hostname = s->saddr->u.inet.host;
|
||||
}
|
||||
|
||||
/* establish TCP connection, return error if it fails
|
||||
@ -448,7 +460,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
object_unref(OBJECT(tlscreds));
|
||||
}
|
||||
if (ret < 0) {
|
||||
qapi_free_SocketAddress(s->saddr);
|
||||
qapi_free_SocketAddressFlat(s->saddr);
|
||||
g_free(s->export);
|
||||
g_free(s->tlscredsid);
|
||||
}
|
||||
@ -474,7 +486,7 @@ static void nbd_close(BlockDriverState *bs)
|
||||
|
||||
nbd_client_close(bs);
|
||||
|
||||
qapi_free_SocketAddress(s->saddr);
|
||||
qapi_free_SocketAddressFlat(s->saddr);
|
||||
g_free(s->export);
|
||||
g_free(s->tlscredsid);
|
||||
}
|
||||
@ -505,15 +517,15 @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
Visitor *ov;
|
||||
const char *host = NULL, *port = NULL, *path = NULL;
|
||||
|
||||
if (s->saddr->type == SOCKET_ADDRESS_KIND_INET) {
|
||||
const InetSocketAddress *inet = s->saddr->u.inet.data;
|
||||
if (s->saddr->type == SOCKET_ADDRESS_FLAT_TYPE_INET) {
|
||||
const InetSocketAddress *inet = &s->saddr->u.inet;
|
||||
if (!inet->has_ipv4 && !inet->has_ipv6 && !inet->has_to) {
|
||||
host = inet->host;
|
||||
port = inet->port;
|
||||
}
|
||||
} else if (s->saddr->type == SOCKET_ADDRESS_KIND_UNIX) {
|
||||
path = s->saddr->u.q_unix.data->path;
|
||||
}
|
||||
} else if (s->saddr->type == SOCKET_ADDRESS_FLAT_TYPE_UNIX) {
|
||||
path = s->saddr->u.q_unix.path;
|
||||
} /* else can't represent as pseudo-filename */
|
||||
|
||||
qdict_put(opts, "driver", qstring_from_str("nbd"));
|
||||
|
||||
@ -532,7 +544,7 @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
}
|
||||
|
||||
ov = qobject_output_visitor_new(&saddr_qdict);
|
||||
visit_type_SocketAddress(ov, NULL, &s->saddr, &error_abort);
|
||||
visit_type_SocketAddressFlat(ov, NULL, &s->saddr, &error_abort);
|
||||
visit_complete(ov, &saddr_qdict);
|
||||
visit_free(ov);
|
||||
qdict_put_obj(opts, "server", saddr_qdict);
|
||||
|
@ -474,6 +474,13 @@ static NFSServer *nfs_config(QDict *options, Error **errp)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Caution: this works only because all scalar members of
|
||||
* NFSServer are QString in @crumpled_addr. The visitor expects
|
||||
* @crumpled_addr to be typed according to the QAPI schema. It
|
||||
* is when @options come from -blockdev or blockdev_add. But when
|
||||
* they come from -drive, they're all QString.
|
||||
*/
|
||||
iv = qobject_input_visitor_new(crumpled_addr);
|
||||
visit_type_NFSServer(iv, NULL, &server, &local_error);
|
||||
if (local_error) {
|
||||
|
@ -192,8 +192,7 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
|
||||
int nb_sectors, int *pnum)
|
||||
{
|
||||
BDRVParallelsState *s = bs->opaque;
|
||||
uint32_t idx, to_allocate, i;
|
||||
int64_t pos, space;
|
||||
int64_t pos, space, idx, to_allocate, i;
|
||||
|
||||
pos = block_status(s, sector_num, nb_sectors, pnum);
|
||||
if (pos > 0) {
|
||||
@ -201,11 +200,19 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
|
||||
}
|
||||
|
||||
idx = sector_num / s->tracks;
|
||||
if (idx >= s->bat_size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
to_allocate = DIV_ROUND_UP(sector_num + *pnum, s->tracks) - idx;
|
||||
|
||||
/* This function is called only by parallels_co_writev(), which will never
|
||||
* pass a sector_num at or beyond the end of the image (because the block
|
||||
* layer never passes such a sector_num to that function). Therefore, idx
|
||||
* is always below s->bat_size.
|
||||
* block_status() will limit *pnum so that sector_num + *pnum will not
|
||||
* exceed the image end. Therefore, idx + to_allocate cannot exceed
|
||||
* s->bat_size.
|
||||
* Note that s->bat_size is an unsigned int, therefore idx + to_allocate
|
||||
* will always fit into a uint32_t. */
|
||||
assert(idx < s->bat_size && idx + to_allocate <= s->bat_size);
|
||||
|
||||
space = to_allocate * s->tracks;
|
||||
if (s->data_end + space > bdrv_getlength(bs->file->bs) >> BDRV_SECTOR_BITS) {
|
||||
int ret;
|
||||
|
@ -1519,12 +1519,10 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
|
||||
|
||||
end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS);
|
||||
|
||||
/* Round start up and end down */
|
||||
offset = align_offset(offset, s->cluster_size);
|
||||
end_offset = start_of_cluster(s, end_offset);
|
||||
|
||||
if (offset > end_offset) {
|
||||
return 0;
|
||||
/* The caller must cluster-align start; round end down except at EOF */
|
||||
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
|
||||
if (end_offset != bs->total_sectors * BDRV_SECTOR_SIZE) {
|
||||
end_offset = start_of_cluster(s, end_offset);
|
||||
}
|
||||
|
||||
nb_clusters = size_to_clusters(s, end_offset - offset);
|
||||
|
@ -385,6 +385,12 @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Caution: while qdict_get_try_str() is fine, getting non-string
|
||||
* types would require more care. When @options come from -blockdev
|
||||
* or blockdev_add, its members are typed according to the QAPI
|
||||
* schema, but when they come from -drive, they're all QString.
|
||||
*/
|
||||
pool = qdict_get_try_str(options, "pool");
|
||||
conf = qdict_get_try_str(options, "conf");
|
||||
clientname = qdict_get_try_str(options, "user");
|
||||
|
@ -13,9 +13,11 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qemu/uri.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/sockets.h"
|
||||
@ -547,6 +549,47 @@ static SocketAddress *sd_socket_address(const char *path,
|
||||
return addr;
|
||||
}
|
||||
|
||||
static SocketAddress *sd_server_config(QDict *options, Error **errp)
|
||||
{
|
||||
QDict *server = NULL;
|
||||
QObject *crumpled_server = NULL;
|
||||
Visitor *iv = NULL;
|
||||
SocketAddressFlat *saddr_flat = NULL;
|
||||
SocketAddress *saddr = NULL;
|
||||
Error *local_err = NULL;
|
||||
|
||||
qdict_extract_subqdict(options, &server, "server.");
|
||||
|
||||
crumpled_server = qdict_crumple(server, errp);
|
||||
if (!crumpled_server) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive
|
||||
* server.type=inet. .to doesn't matter, it's ignored anyway.
|
||||
* That's because when @options come from -blockdev or
|
||||
* blockdev_add, members are typed according to the QAPI schema,
|
||||
* but when they come from -drive, they're all QString. The
|
||||
* visitor expects the former.
|
||||
*/
|
||||
iv = qobject_input_visitor_new(crumpled_server);
|
||||
visit_type_SocketAddressFlat(iv, NULL, &saddr_flat, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
saddr = socket_address_crumple(saddr_flat);
|
||||
|
||||
done:
|
||||
qapi_free_SocketAddressFlat(saddr_flat);
|
||||
visit_free(iv);
|
||||
qobject_decref(crumpled_server);
|
||||
QDECREF(server);
|
||||
return saddr;
|
||||
}
|
||||
|
||||
/* Return -EIO in case of error, file descriptor on success */
|
||||
static int connect_to_sdog(BDRVSheepdogState *s, Error **errp)
|
||||
{
|
||||
@ -1174,15 +1217,15 @@ static void sd_parse_filename(const char *filename, QDict *options,
|
||||
return;
|
||||
}
|
||||
|
||||
if (cfg.host) {
|
||||
qdict_set_default_str(options, "host", cfg.host);
|
||||
}
|
||||
if (cfg.port) {
|
||||
snprintf(buf, sizeof(buf), "%d", cfg.port);
|
||||
qdict_set_default_str(options, "port", buf);
|
||||
}
|
||||
if (cfg.path) {
|
||||
qdict_set_default_str(options, "path", cfg.path);
|
||||
qdict_set_default_str(options, "server.path", cfg.path);
|
||||
qdict_set_default_str(options, "server.type", "unix");
|
||||
} else {
|
||||
qdict_set_default_str(options, "server.type", "inet");
|
||||
qdict_set_default_str(options, "server.host",
|
||||
cfg.host ?: SD_DEFAULT_ADDR);
|
||||
snprintf(buf, sizeof(buf), "%d", cfg.port ?: SD_DEFAULT_PORT);
|
||||
qdict_set_default_str(options, "server.port", buf);
|
||||
}
|
||||
qdict_set_default_str(options, "vdi", cfg.vdi);
|
||||
qdict_set_default_str(options, "tag", cfg.tag);
|
||||
@ -1509,18 +1552,6 @@ static QemuOptsList runtime_opts = {
|
||||
.name = "sheepdog",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = "host",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},
|
||||
{
|
||||
.name = "port",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},
|
||||
{
|
||||
.name = "path",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},
|
||||
{
|
||||
.name = "vdi",
|
||||
.type = QEMU_OPT_STRING,
|
||||
@ -1543,7 +1574,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
int ret, fd;
|
||||
uint32_t vid = 0;
|
||||
BDRVSheepdogState *s = bs->opaque;
|
||||
const char *host, *port, *path, *vdi, *snap_id_str, *tag;
|
||||
const char *vdi, *snap_id_str, *tag;
|
||||
uint64_t snap_id;
|
||||
char *buf = NULL;
|
||||
QemuOpts *opts;
|
||||
@ -1560,20 +1591,17 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto err_no_fd;
|
||||
}
|
||||
|
||||
host = qemu_opt_get(opts, "host");
|
||||
port = qemu_opt_get(opts, "port");
|
||||
path = qemu_opt_get(opts, "path");
|
||||
s->addr = sd_server_config(options, errp);
|
||||
if (!s->addr) {
|
||||
ret = -EINVAL;
|
||||
goto err_no_fd;
|
||||
}
|
||||
|
||||
vdi = qemu_opt_get(opts, "vdi");
|
||||
snap_id_str = qemu_opt_get(opts, "snap-id");
|
||||
snap_id = qemu_opt_get_number(opts, "snap-id", CURRENT_VDI_ID);
|
||||
tag = qemu_opt_get(opts, "tag");
|
||||
|
||||
if ((host || port) && path) {
|
||||
error_setg(errp, "can't use 'path' together with 'host' or 'port'");
|
||||
ret = -EINVAL;
|
||||
goto err_no_fd;
|
||||
}
|
||||
|
||||
if (!vdi) {
|
||||
error_setg(errp, "parameter 'vdi' is missing");
|
||||
ret = -EINVAL;
|
||||
@ -1604,8 +1632,6 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto err_no_fd;
|
||||
}
|
||||
|
||||
s->addr = sd_socket_address(path, host, port);
|
||||
|
||||
QLIST_INIT(&s->inflight_aio_head);
|
||||
QLIST_INIT(&s->failed_aio_head);
|
||||
QLIST_INIT(&s->inflight_aiocb_head);
|
||||
|
@ -601,6 +601,14 @@ static InetSocketAddress *ssh_config(QDict *options, Error **errp)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive.
|
||||
* .to doesn't matter, it's ignored anyway.
|
||||
* That's because when @options come from -blockdev or
|
||||
* blockdev_add, members are typed according to the QAPI schema,
|
||||
* but when they come from -drive, they're all QString. The
|
||||
* visitor expects the former.
|
||||
*/
|
||||
iv = qobject_input_visitor_new(crumpled_addr);
|
||||
visit_type_InetSocketAddress(iv, NULL, &inet, &local_error);
|
||||
if (local_error) {
|
||||
|
@ -124,6 +124,7 @@ void qmp_nbd_server_start(SocketAddress *addr,
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* TODO SOCKET_ADDRESS_KIND_FD where fd has AF_INET or AF_INET6 */
|
||||
if (addr->type != SOCKET_ADDRESS_KIND_INET) {
|
||||
error_setg(errp, "TLS is only supported with IPv4/IPv6");
|
||||
goto error;
|
||||
|
@ -47,7 +47,6 @@ typedef struct {
|
||||
int max_size;
|
||||
int do_telnetopt;
|
||||
int do_nodelay;
|
||||
int is_unix;
|
||||
int *read_msgfds;
|
||||
size_t read_msgfds_num;
|
||||
int *write_msgfds;
|
||||
@ -358,6 +357,10 @@ static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr,
|
||||
return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd.data->str,
|
||||
is_listen ? ",server" : "");
|
||||
break;
|
||||
case SOCKET_ADDRESS_KIND_VSOCK:
|
||||
return g_strdup_printf("%svsock:%s:%s", prefix,
|
||||
addr->u.vsock.data->cid,
|
||||
addr->u.vsock.data->port);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@ -825,7 +828,6 @@ static void qmp_chardev_open_socket(Chardev *chr,
|
||||
int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0;
|
||||
QIOChannelSocket *sioc = NULL;
|
||||
|
||||
s->is_unix = addr->type == SOCKET_ADDRESS_KIND_UNIX;
|
||||
s->is_listen = is_listen;
|
||||
s->is_telnet = is_telnet;
|
||||
s->do_nodelay = do_nodelay;
|
||||
@ -865,7 +867,8 @@ static void qmp_chardev_open_socket(Chardev *chr,
|
||||
s->addr = QAPI_CLONE(SocketAddress, sock->addr);
|
||||
|
||||
qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
|
||||
if (s->is_unix) {
|
||||
/* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */
|
||||
if (addr->type == SOCKET_ADDRESS_KIND_UNIX) {
|
||||
qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
|
||||
}
|
||||
|
||||
|
@ -124,8 +124,12 @@ static void release_drive(Object *obj, const char *name, void *opaque)
|
||||
BlockBackend **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
AioContext *ctx = blk_get_aio_context(*ptr);
|
||||
|
||||
aio_context_acquire(ctx);
|
||||
blockdev_auto_del(*ptr);
|
||||
blk_detach_dev(*ptr, dev);
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,4 +119,15 @@ SocketAddress *socket_remote_address(int fd, Error **errp);
|
||||
*/
|
||||
char *socket_address_to_string(struct SocketAddress *addr, Error **errp);
|
||||
|
||||
/**
|
||||
* socket_address_crumple:
|
||||
* @addr_flat: the socket address to crumple
|
||||
*
|
||||
* Convert SocketAddressFlat to SocketAddress. Caller is responsible
|
||||
* for freeing with qapi_free_SocketAddress().
|
||||
*
|
||||
* Returns: the argument converted to SocketAddress.
|
||||
*/
|
||||
SocketAddress *socket_address_crumple(SocketAddressFlat *addr_flat);
|
||||
|
||||
#endif /* QEMU_SOCKETS_H */
|
||||
|
@ -164,9 +164,12 @@ int qio_dns_resolver_lookup_sync(QIODNSResolver *resolver,
|
||||
addrs,
|
||||
errp);
|
||||
|
||||
default:
|
||||
error_setg(errp, "Unknown socket address kind");
|
||||
case SOCKET_ADDRESS_KIND_FD:
|
||||
error_setg(errp, "Unsupported socket address type 'fd'");
|
||||
return -1;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4144,7 +4144,7 @@
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'enum': 'SocketAddressFlatType',
|
||||
'data': [ 'unix', 'inet' ] }
|
||||
'data': [ 'inet', 'unix', 'vsock', 'fd' ] }
|
||||
|
||||
##
|
||||
# @SocketAddressFlat:
|
||||
@ -4153,22 +4153,19 @@
|
||||
#
|
||||
# @type: Transport type
|
||||
#
|
||||
# This is similar to SocketAddress, only distinction:
|
||||
#
|
||||
# 1. SocketAddressFlat is a flat union, SocketAddress is a simple union.
|
||||
# A flat union is nicer than simple because it avoids nesting
|
||||
# (i.e. more {}) on the wire.
|
||||
#
|
||||
# 2. SocketAddressFlat supports only types 'unix' and 'inet', because
|
||||
# that's what its current users need.
|
||||
# This is just like SocketAddress, except it's a flat union rather
|
||||
# than a simple union. Nicer because it avoids nesting on the wire,
|
||||
# i.e. this form has fewer {}.
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'union': 'SocketAddressFlat',
|
||||
'base': { 'type': 'SocketAddressFlatType' },
|
||||
'discriminator': 'type',
|
||||
'data': { 'unix': 'UnixSocketAddress',
|
||||
'inet': 'InetSocketAddress' } }
|
||||
'data': { 'inet': 'InetSocketAddress',
|
||||
'unix': 'UnixSocketAddress',
|
||||
'vsock': 'VsockSocketAddress',
|
||||
'fd': 'String' } }
|
||||
|
||||
##
|
||||
# @getfd:
|
||||
|
@ -2623,7 +2623,7 @@
|
||||
# Driver specific block device options for sheepdog
|
||||
#
|
||||
# @vdi: Virtual disk image name
|
||||
# @addr: The Sheepdog server to connect to
|
||||
# @server: The Sheepdog server to connect to
|
||||
# @snap-id: Snapshot ID
|
||||
# @tag: Snapshot tag name
|
||||
#
|
||||
@ -2632,7 +2632,7 @@
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'struct': 'BlockdevOptionsSheepdog',
|
||||
'data': { 'addr': 'SocketAddressFlat',
|
||||
'data': { 'server': 'SocketAddressFlat',
|
||||
'vdi': 'str',
|
||||
'*snap-id': 'uint32',
|
||||
'*tag': 'str' } }
|
||||
@ -2847,7 +2847,7 @@
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'struct': 'BlockdevOptionsNbd',
|
||||
'data': { 'server': 'SocketAddress',
|
||||
'data': { 'server': 'SocketAddressFlat',
|
||||
'*export': 'str',
|
||||
'*tls-creds': 'str' } }
|
||||
|
||||
|
@ -35,6 +35,13 @@ static int compare_cmdname(const void *a, const void *b)
|
||||
|
||||
void qemuio_add_command(const cmdinfo_t *ci)
|
||||
{
|
||||
/* ci->perm assumes a file is open, but the GLOBAL and NOFILE_OK
|
||||
* flags allow it not to be, so that combination is invalid.
|
||||
* Catch it now rather than letting it manifest as a crash if a
|
||||
* particular set of command line options are used.
|
||||
*/
|
||||
assert(ci->perm == 0 ||
|
||||
(ci->flags & (CMD_FLAG_GLOBAL | CMD_NOFILE_OK)) == 0);
|
||||
cmdtab = g_renew(cmdinfo_t, cmdtab, ++ncmds);
|
||||
cmdtab[ncmds - 1] = *ci;
|
||||
qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
|
||||
|
@ -56,30 +56,25 @@ _supported_os Linux
|
||||
# 3: Two-layer backing chain, commit to lower backing file
|
||||
# (in this case, the top image will implicitly stay unchanged)
|
||||
#
|
||||
# Each pass is run twice, since qcow2 has different code paths for cleaning
|
||||
# an image depending on whether it has a snapshot.
|
||||
#
|
||||
# 020 already tests committing, so this only tests whether image chains are
|
||||
# working properly and that all images above the base are emptied; therefore,
|
||||
# no complicated patterns are necessary. Check near the 2G mark, as qcow2
|
||||
# has been buggy at that boundary in the past.
|
||||
for i in 0 1 2 3; do
|
||||
for j in 0 1; do
|
||||
|
||||
echo
|
||||
echo "=== Test pass $i.$j ==="
|
||||
echo "=== Test pass $i ==="
|
||||
echo
|
||||
|
||||
TEST_IMG="$TEST_IMG.base" _make_test_img 2100M
|
||||
TEST_IMG="$TEST_IMG.itmd" _make_test_img -b "$TEST_IMG.base" 2100M
|
||||
_make_test_img -b "$TEST_IMG.itmd" 2100M
|
||||
if [ $j -eq 0 ]; then
|
||||
$QEMU_IMG snapshot -c snap "$TEST_IMG"
|
||||
fi
|
||||
len=$((2100 * 1024 * 1024 + 512)) # larger than 2G, and not cluster aligned
|
||||
TEST_IMG="$TEST_IMG.base" _make_test_img $len
|
||||
TEST_IMG="$TEST_IMG.itmd" _make_test_img -b "$TEST_IMG.base" $len
|
||||
_make_test_img -b "$TEST_IMG.itmd" $len
|
||||
|
||||
$QEMU_IO -c 'write -P 1 0x7ffd0000 192k' "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c 'write -P 2 0x7ffe0000 128k' "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
$QEMU_IO -c 'write -P 3 0x7fff0000 64k' "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 1 0x7ffd0000 192k" "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 2 0x7ffe0000 128k" "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 3 0x7fff0000 64k" "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 4 $(($len - 512)) 512" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
if [ $i -lt 3 ]; then
|
||||
if [ $i == 0 ]; then
|
||||
@ -97,11 +92,13 @@ if [ $i -lt 3 ]; then
|
||||
|
||||
# Bottom should be unchanged
|
||||
$QEMU_IO -c 'read -P 1 0x7ffd0000 192k' "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c "read -P 0 $((len - 512)) 512" "$TEST_IMG.base" | _filter_qemu_io
|
||||
|
||||
# Intermediate should contain changes from top
|
||||
$QEMU_IO -c 'read -P 1 0x7ffd0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
$QEMU_IO -c 'read -P 2 0x7ffe0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
$QEMU_IO -c 'read -P 3 0x7fff0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
$QEMU_IO -c "read -P 4 $((len - 512)) 512" "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
|
||||
# And in pass 0, the top image should be empty, whereas in both other passes
|
||||
# it should be unchanged (which is both checked by qemu-img map)
|
||||
@ -112,6 +109,7 @@ else
|
||||
$QEMU_IO -c 'read -P 1 0x7ffd0000 64k' "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c 'read -P 2 0x7ffe0000 64k' "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c 'read -P 3 0x7fff0000 64k' "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c "read -P 4 $((len - 512)) 512" "$TEST_IMG.base" | _filter_qemu_io
|
||||
|
||||
# Both top and intermediate should be unchanged
|
||||
fi
|
||||
@ -121,7 +119,6 @@ $QEMU_IMG map "$TEST_IMG.itmd" | _filter_qemu_img_map
|
||||
$QEMU_IMG map "$TEST_IMG" | _filter_qemu_img_map
|
||||
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
# success, all done
|
||||
|
@ -1,222 +1,131 @@
|
||||
QA output created by 097
|
||||
|
||||
=== Test pass 0.0 ===
|
||||
=== Test pass 0 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd
|
||||
|
||||
=== Test pass 0.1 ===
|
||||
=== Test pass 1 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
|
||||
=== Test pass 1.0 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x7fff0000 0x10000 TEST_DIR/t.IMGFMT
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT
|
||||
|
||||
=== Test pass 1.1 ===
|
||||
=== Test pass 2 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x7fff0000 0x10000 TEST_DIR/t.IMGFMT
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT
|
||||
|
||||
=== Test pass 2.0 ===
|
||||
=== Test pass 3 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x7fff0000 0x10000 TEST_DIR/t.IMGFMT
|
||||
|
||||
=== Test pass 2.1 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x7fff0000 0x10000 TEST_DIR/t.IMGFMT
|
||||
|
||||
=== Test pass 3.0 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x7fff0000 0x10000 TEST_DIR/t.IMGFMT
|
||||
|
||||
=== Test pass 3.1 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
@ -224,13 +133,18 @@ read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x7fff0000 0x10000 TEST_DIR/t.IMGFMT
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT
|
||||
*** done
|
||||
|
@ -30,6 +30,13 @@ NBD_PORT = 10811
|
||||
test_img = os.path.join(iotests.test_dir, 'test.img')
|
||||
unix_socket = os.path.join(iotests.test_dir, 'nbd.socket')
|
||||
|
||||
|
||||
def flatten_sock_addr(crumpled_address):
|
||||
result = { 'type': crumpled_address['type'] }
|
||||
result.update(crumpled_address['data'])
|
||||
return result
|
||||
|
||||
|
||||
class NBDBlockdevAddBase(iotests.QMPTestCase):
|
||||
def blockdev_add_options(self, address, export=None):
|
||||
options = { 'node-name': 'nbd-blockdev',
|
||||
@ -85,13 +92,15 @@ class QemuNBD(NBDBlockdevAddBase):
|
||||
'host': 'localhost',
|
||||
'port': str(NBD_PORT)
|
||||
} }
|
||||
self.client_test('nbd://localhost:%i' % NBD_PORT, address)
|
||||
self.client_test('nbd://localhost:%i' % NBD_PORT,
|
||||
flatten_sock_addr(address))
|
||||
|
||||
def test_unix(self):
|
||||
self._server_up('-k', unix_socket)
|
||||
address = { 'type': 'unix',
|
||||
'data': { 'path': unix_socket } }
|
||||
self.client_test('nbd+unix://?socket=' + unix_socket, address)
|
||||
self.client_test('nbd+unix://?socket=' + unix_socket,
|
||||
flatten_sock_addr(address))
|
||||
|
||||
|
||||
class BuiltinNBD(NBDBlockdevAddBase):
|
||||
@ -134,7 +143,7 @@ class BuiltinNBD(NBDBlockdevAddBase):
|
||||
} }
|
||||
self._server_up(address)
|
||||
self.client_test('nbd://localhost:%i/nbd-export' % NBD_PORT,
|
||||
address, 'nbd-export')
|
||||
flatten_sock_addr(address), 'nbd-export')
|
||||
self._server_down()
|
||||
|
||||
def test_inet6(self):
|
||||
@ -149,10 +158,10 @@ class BuiltinNBD(NBDBlockdevAddBase):
|
||||
'file': {
|
||||
'driver': 'nbd',
|
||||
'export': 'nbd-export',
|
||||
'server': address
|
||||
'server': flatten_sock_addr(address)
|
||||
} }
|
||||
self._server_up(address)
|
||||
self.client_test(filename, address, 'nbd-export')
|
||||
self.client_test(filename, flatten_sock_addr(address), 'nbd-export')
|
||||
self._server_down()
|
||||
|
||||
def test_unix(self):
|
||||
@ -160,7 +169,7 @@ class BuiltinNBD(NBDBlockdevAddBase):
|
||||
'data': { 'path': unix_socket } }
|
||||
self._server_up(address)
|
||||
self.client_test('nbd+unix:///nbd-export?socket=' + unix_socket,
|
||||
address, 'nbd-export')
|
||||
flatten_sock_addr(address), 'nbd-export')
|
||||
self._server_down()
|
||||
|
||||
def test_fd(self):
|
||||
@ -182,9 +191,9 @@ class BuiltinNBD(NBDBlockdevAddBase):
|
||||
'file': {
|
||||
'driver': 'nbd',
|
||||
'export': 'nbd-export',
|
||||
'server': address
|
||||
'server': flatten_sock_addr(address)
|
||||
} }
|
||||
self.client_test(filename, address, 'nbd-export')
|
||||
self.client_test(filename, flatten_sock_addr(address), 'nbd-export')
|
||||
|
||||
self._server_down()
|
||||
|
||||
|
131
tests/qemu-iotests/176
Executable file
131
tests/qemu-iotests/176
Executable file
@ -0,0 +1,131 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Commit changes into backing chains and empty the top image if the
|
||||
# backing image is not explicitly specified.
|
||||
#
|
||||
# Variant of 097, which includes snapshots to test different codepath
|
||||
# in qcow2
|
||||
#
|
||||
# Copyright (C) 2014 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# creator
|
||||
owner=mreitz@redhat.com
|
||||
|
||||
seq="$(basename $0)"
|
||||
echo "QA output created by $seq"
|
||||
|
||||
here="$PWD"
|
||||
status=1 # failure is the default!
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
_cleanup_test_img
|
||||
_rm_test_img "$TEST_IMG.itmd"
|
||||
}
|
||||
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common.rc
|
||||
. ./common.filter
|
||||
. ./common.pattern
|
||||
|
||||
# Any format supporting backing files and bdrv_make_empty
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
|
||||
# Four passes:
|
||||
# 0: Two-layer backing chain, commit to upper backing file (implicitly)
|
||||
# (in this case, the top image will be emptied)
|
||||
# 1: Two-layer backing chain, commit to upper backing file (explicitly)
|
||||
# (in this case, the top image will implicitly stay unchanged)
|
||||
# 2: Two-layer backing chain, commit to upper backing file (implicitly with -d)
|
||||
# (in this case, the top image will explicitly stay unchanged)
|
||||
# 3: Two-layer backing chain, commit to lower backing file
|
||||
# (in this case, the top image will implicitly stay unchanged)
|
||||
#
|
||||
# 020 already tests committing, so this only tests whether image chains are
|
||||
# working properly and that all images above the base are emptied; therefore,
|
||||
# no complicated patterns are necessary. Check near the 2G mark, as qcow2
|
||||
# has been buggy at that boundary in the past.
|
||||
for i in 0 1 2 3; do
|
||||
|
||||
echo
|
||||
echo "=== Test pass $i ==="
|
||||
echo
|
||||
|
||||
len=$((2100 * 1024 * 1024 + 512)) # larger than 2G, and not cluster aligned
|
||||
TEST_IMG="$TEST_IMG.base" _make_test_img $len
|
||||
TEST_IMG="$TEST_IMG.itmd" _make_test_img -b "$TEST_IMG.base" $len
|
||||
_make_test_img -b "$TEST_IMG.itmd" $len
|
||||
$QEMU_IMG snapshot -c snap "$TEST_IMG"
|
||||
|
||||
$QEMU_IO -c "write -P 1 0x7ffd0000 192k" "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 2 0x7ffe0000 128k" "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 3 0x7fff0000 64k" "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c "write -P 4 $(($len - 512)) 512" "$TEST_IMG" | _filter_qemu_io
|
||||
|
||||
if [ $i -lt 3 ]; then
|
||||
if [ $i == 0 ]; then
|
||||
# -b "$TEST_IMG.itmd" should be the default (that is, committing to the
|
||||
# first backing file in the chain)
|
||||
$QEMU_IMG commit "$TEST_IMG"
|
||||
elif [ $i == 1 ]; then
|
||||
# explicitly specify the commit target (this should imply -d)
|
||||
$QEMU_IMG commit -b "$TEST_IMG.itmd" "$TEST_IMG"
|
||||
else
|
||||
# do not explicitly specify the commit target, but use -d to leave the
|
||||
# top image unchanged
|
||||
$QEMU_IMG commit -d "$TEST_IMG"
|
||||
fi
|
||||
|
||||
# Bottom should be unchanged
|
||||
$QEMU_IO -c 'read -P 1 0x7ffd0000 192k' "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c "read -P 0 $((len - 512)) 512" "$TEST_IMG.base" | _filter_qemu_io
|
||||
|
||||
# Intermediate should contain changes from top
|
||||
$QEMU_IO -c 'read -P 1 0x7ffd0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
$QEMU_IO -c 'read -P 2 0x7ffe0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
$QEMU_IO -c 'read -P 3 0x7fff0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
$QEMU_IO -c "read -P 4 $((len - 512)) 512" "$TEST_IMG.itmd" | _filter_qemu_io
|
||||
|
||||
# And in pass 0, the top image should be empty, whereas in both other passes
|
||||
# it should be unchanged (which is both checked by qemu-img map)
|
||||
else
|
||||
$QEMU_IMG commit -b "$TEST_IMG.base" "$TEST_IMG"
|
||||
|
||||
# Bottom should contain all changes
|
||||
$QEMU_IO -c 'read -P 1 0x7ffd0000 64k' "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c 'read -P 2 0x7ffe0000 64k' "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c 'read -P 3 0x7fff0000 64k' "$TEST_IMG.base" | _filter_qemu_io
|
||||
$QEMU_IO -c "read -P 4 $((len - 512)) 512" "$TEST_IMG.base" | _filter_qemu_io
|
||||
|
||||
# Both top and intermediate should be unchanged
|
||||
fi
|
||||
|
||||
$QEMU_IMG map "$TEST_IMG.base" | _filter_qemu_img_map
|
||||
$QEMU_IMG map "$TEST_IMG.itmd" | _filter_qemu_img_map
|
||||
$QEMU_IMG map "$TEST_IMG" | _filter_qemu_img_map
|
||||
|
||||
done
|
||||
|
||||
|
||||
# success, all done
|
||||
echo "*** done"
|
||||
rm -f $seq.full
|
||||
status=0
|
150
tests/qemu-iotests/176.out
Normal file
150
tests/qemu-iotests/176.out
Normal file
@ -0,0 +1,150 @@
|
||||
QA output created by 176
|
||||
|
||||
=== Test pass 0 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd
|
||||
|
||||
=== Test pass 1 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x7fff0000 0x10000 TEST_DIR/t.IMGFMT
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT
|
||||
|
||||
=== Test pass 2 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x7fff0000 0x10000 TEST_DIR/t.IMGFMT
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT
|
||||
|
||||
=== Test pass 3 ===
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112
|
||||
Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd
|
||||
wrote 196608/196608 bytes at offset 2147287040
|
||||
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 131072/131072 bytes at offset 2147352576
|
||||
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
wrote 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Image committed.
|
||||
read 65536/65536 bytes at offset 2147287040
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147352576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 65536/65536 bytes at offset 2147418112
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
read 512/512 bytes at offset 2202009600
|
||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
Offset Length File
|
||||
0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT.base
|
||||
Offset Length File
|
||||
0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base
|
||||
0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd
|
||||
0x7fff0000 0x10000 TEST_DIR/t.IMGFMT
|
||||
0x83400000 0x200 TEST_DIR/t.IMGFMT
|
||||
*** done
|
@ -168,3 +168,4 @@
|
||||
173 rw auto
|
||||
174 auto
|
||||
175 auto quick
|
||||
176 rw auto backing
|
||||
|
19
ui/vnc.c
19
ui/vnc.c
@ -129,10 +129,13 @@ static void vnc_init_basic_info(SocketAddress *addr,
|
||||
info->family = NETWORK_ADDRESS_FAMILY_UNIX;
|
||||
break;
|
||||
|
||||
default:
|
||||
error_setg(errp, "Unsupported socket kind %d",
|
||||
addr->type);
|
||||
case SOCKET_ADDRESS_KIND_VSOCK:
|
||||
case SOCKET_ADDRESS_KIND_FD:
|
||||
error_setg(errp, "Unsupported socket address type %s",
|
||||
SocketAddressKind_lookup[addr->type]);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
return;
|
||||
@ -411,10 +414,13 @@ VncInfo *qmp_query_vnc(Error **errp)
|
||||
info->family = NETWORK_ADDRESS_FAMILY_UNIX;
|
||||
break;
|
||||
|
||||
default:
|
||||
error_setg(errp, "Unsupported socket kind %d",
|
||||
addr->type);
|
||||
case SOCKET_ADDRESS_KIND_VSOCK:
|
||||
case SOCKET_ADDRESS_KIND_FD:
|
||||
error_setg(errp, "Unsupported socket address type %s",
|
||||
SocketAddressKind_lookup[addr->type]);
|
||||
goto out_error;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
info->has_host = true;
|
||||
@ -3642,6 +3648,7 @@ static int vnc_display_connect(VncDisplay *vd,
|
||||
error_setg(errp, "Expected a single address in reverse mode");
|
||||
return -1;
|
||||
}
|
||||
/* TODO SOCKET_ADDRESS_KIND_FD when fd has AF_UNIX */
|
||||
vd->is_unix = saddr[0]->type == SOCKET_ADDRESS_KIND_UNIX;
|
||||
sioc = qio_channel_socket_new();
|
||||
qio_channel_set_name(QIO_CHANNEL(sioc), "vnc-reverse");
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qapi/clone-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi-visit.h"
|
||||
@ -1154,6 +1155,10 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
|
||||
{
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* TODO SOCKET_ADDRESS_KIND_FD when fd is AF_INET or AF_INET6
|
||||
* (although other address families can do SOCK_DGRAM, too)
|
||||
*/
|
||||
switch (remote->type) {
|
||||
case SOCKET_ADDRESS_KIND_INET:
|
||||
fd = inet_dgram_saddr(remote->u.inet.data,
|
||||
@ -1333,9 +1338,38 @@ char *socket_address_to_string(struct SocketAddress *addr, Error **errp)
|
||||
break;
|
||||
|
||||
default:
|
||||
error_setg(errp, "socket family %d unsupported",
|
||||
addr->type);
|
||||
return NULL;
|
||||
abort();
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
SocketAddress *socket_address_crumple(SocketAddressFlat *addr_flat)
|
||||
{
|
||||
SocketAddress *addr = g_new(SocketAddress, 1);
|
||||
|
||||
switch (addr_flat->type) {
|
||||
case SOCKET_ADDRESS_FLAT_TYPE_INET:
|
||||
addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
addr->u.inet.data = QAPI_CLONE(InetSocketAddress,
|
||||
&addr_flat->u.inet);
|
||||
break;
|
||||
case SOCKET_ADDRESS_FLAT_TYPE_UNIX:
|
||||
addr->type = SOCKET_ADDRESS_KIND_UNIX;
|
||||
addr->u.q_unix.data = QAPI_CLONE(UnixSocketAddress,
|
||||
&addr_flat->u.q_unix);
|
||||
break;
|
||||
case SOCKET_ADDRESS_FLAT_TYPE_VSOCK:
|
||||
addr->type = SOCKET_ADDRESS_KIND_VSOCK;
|
||||
addr->u.vsock.data = QAPI_CLONE(VsockSocketAddress,
|
||||
&addr_flat->u.vsock);
|
||||
break;
|
||||
case SOCKET_ADDRESS_FLAT_TYPE_FD:
|
||||
addr->type = SOCKET_ADDRESS_KIND_FD;
|
||||
addr->u.fd.data = QAPI_CLONE(String, &addr_flat->u.fd);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user