qemu-e2k/tests/qemu-iotests/307.out
Eric Blake 2dcbb11b39 nbd/server: Add FLAG_PAYLOAD support to CMD_BLOCK_STATUS
Allow a client to request a subset of negotiated meta contexts.  For
example, a client may ask to use a single connection to learn about
both block status and dirty bitmaps, but where the dirty bitmap
queries only need to be performed on a subset of the disk; forcing the
server to compute that information on block status queries in the rest
of the disk is wasted effort (both at the server, and on the amount of
traffic sent over the wire to be parsed and ignored by the client).

Qemu as an NBD client never requests to use more than one meta
context, so it has no need to use block status payloads.  Testing this
instead requires support from libnbd, which CAN access multiple meta
contexts in parallel from a single NBD connection; an interop test
submitted to the libnbd project at the same time as this patch
demonstrates the feature working, as well as testing some corner cases
(for example, when the payload length is longer than the export
length), although other corner cases (like passing the same id
duplicated) requires a protocol fuzzer because libnbd is not wired up
to break the protocol that badly.

This also includes tweaks to 'qemu-nbd --list' to show when a server
is advertising the capability, and to the testsuite to reflect the
addition to that output.

Of note: qemu will always advertise the new feature bit during
NBD_OPT_INFO if extended headers have alreay been negotiated
(regardless of whether any NBD_OPT_SET_META_CONTEXT negotiation has
occurred); but for NBD_OPT_GO, qemu only advertises the feature if
block status is also enabled (that is, if the client does not
negotiate any contexts, then NBD_CMD_BLOCK_STATUS cannot be used, so
the feature is not advertised).

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-ID: <20230925192229.3186470-26-eblake@redhat.com>
[eblake: fix logic to reject unnegotiated contexts]
Signed-off-by: Eric Blake <eblake@redhat.com>
2023-10-05 11:02:08 -05:00

138 lines
6.3 KiB
Plaintext

wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Launch VM ===
{"execute": "nbd-server-start", "arguments": {"addr": {"data": {"path": "SOCK_DIR/PID-socket"}, "type": "unix"}}}
{"return": {}}
{"execute": "query-block-exports", "arguments": {}}
{"return": []}
=== Create a read-only NBD export ===
{"execute": "block-export-add", "arguments": {"id": "export0", "node-name": "fmt", "type": "nbd"}}
{"return": {}}
{"execute": "query-block-exports", "arguments": {}}
{"return": [{"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]}
exports available: 1
export: 'fmt'
size: 67108864
flags: 0x158f ( readonly flush fua df multi cache block-status-payload )
min block: XXX
opt block: XXX
max block: XXX
transaction size: 64-bit
available meta contexts: 1
base:allocation
=== Try a few invalid things ===
{"execute": "block-export-add", "arguments": {"id": "#invalid", "node-name": "fmt", "type": "nbd"}}
{"error": {"class": "GenericError", "desc": "Invalid block export id"}}
{"execute": "block-export-add", "arguments": {"id": "export0", "node-name": "fmt", "type": "nbd"}}
{"error": {"class": "GenericError", "desc": "Block export id 'export0' is already in use"}}
{"execute": "block-export-add", "arguments": {"id": "export1", "node-name": "ro", "type": "nbd", "writable": true}}
{"error": {"class": "GenericError", "desc": "Cannot export read-only node as writable"}}
{"execute": "block-export-del", "arguments": {"id": "export1"}}
{"error": {"class": "GenericError", "desc": "Export 'export1' is not found"}}
{"execute": "query-block-exports", "arguments": {}}
{"return": [{"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]}
=== Move export to an iothread ===
{"execute": "device_add", "arguments": {"drive": "fmt", "driver": "scsi-hd", "id": "sda"}}
{"return": {}}
{"execute": "query-block-exports", "arguments": {}}
{"return": [{"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]}
exports available: 1
export: 'fmt'
size: 67108864
flags: 0x158f ( readonly flush fua df multi cache block-status-payload )
min block: XXX
opt block: XXX
max block: XXX
transaction size: 64-bit
available meta contexts: 1
base:allocation
=== Add export with conflicting iothread ===
{"execute": "device_add", "arguments": {"drive": "null", "driver": "scsi-hd", "id": "sdb"}}
{"return": {}}
{"execute": "block-export-add", "arguments": {"fixed-iothread": true, "id": "export1", "iothread": "iothread1", "node-name": "null", "type": "nbd", "writable": true}}
{"error": {"class": "GenericError", "desc": "Cannot change iothread of active block backend"}}
{"execute": "block-export-add", "arguments": {"fixed-iothread": false, "id": "export1", "iothread": "iothread1", "node-name": "null", "type": "nbd", "writable": true}}
{"error": {"class": "GenericError", "desc": "Permission conflict on node 'null': permissions 'write' are both required by an unnamed block device (uses node 'null' as 'root' child) and unshared by block device 'sdb' (uses node 'null' as 'root' child)."}}
=== Add a writable export ===
{"execute": "block-export-add", "arguments": {"description": "This is the writable second export", "id": "export1", "name": "export1", "node-name": "fmt", "type": "nbd", "writable": true, "writethrough": true}}
{"error": {"class": "GenericError", "desc": "Permission conflict on node 'fmt': permissions 'write' are both required by an unnamed block device (uses node 'fmt' as 'root' child) and unshared by block device 'sda' (uses node 'fmt' as 'root' child)."}}
{"execute": "device_del", "arguments": {"id": "sda"}}
{"return": {}}
{"data": {"device": "sda", "path": "/machine/peripheral/sda"}, "event": "DEVICE_DELETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
{"execute": "device_add", "arguments": {"drive": "fmt", "driver": "scsi-hd", "id": "sda", "share-rw": true}}
{"return": {}}
{"execute": "block-export-add", "arguments": {"description": "This is the writable second export", "id": "export1", "name": "export1", "node-name": "fmt", "type": "nbd", "writable": true, "writethrough": true}}
{"return": {}}
{"execute": "query-block-exports", "arguments": {}}
{"return": [{"id": "export1", "node-name": "fmt", "shutting-down": false, "type": "nbd"}, {"id": "export0", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]}
exports available: 2
export: 'fmt'
size: 67108864
flags: 0x158f ( readonly flush fua df multi cache block-status-payload )
min block: XXX
opt block: XXX
max block: XXX
transaction size: 64-bit
available meta contexts: 1
base:allocation
export: 'export1'
description: This is the writable second export
size: 67108864
flags: 0x1ded ( flush fua trim zeroes df multi cache fast-zero block-status-payload )
min block: XXX
opt block: XXX
max block: XXX
transaction size: 64-bit
available meta contexts: 1
base:allocation
=== Connect qemu-io to export1, try removing exports ===
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 4096/4096 bytes at offset 4096
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"execute": "block-export-del", "arguments": {"id": "export1"}}
{"error": {"class": "GenericError", "desc": "export 'export1' still in use"}}
{"execute": "block-export-del", "arguments": {"id": "export0"}}
{"return": {}}
[{"data": {"id": "export0"}, "event": "BLOCK_EXPORT_DELETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}]
{"execute": "query-block-exports", "arguments": {}}
{"return": [{"id": "export1", "node-name": "fmt", "shutting-down": false, "type": "nbd"}]}
exports available: 1
export: 'export1'
description: This is the writable second export
size: 67108864
flags: 0x1ded ( flush fua trim zeroes df multi cache fast-zero block-status-payload )
min block: XXX
opt block: XXX
max block: XXX
transaction size: 64-bit
available meta contexts: 1
base:allocation
=== Connect qemu-io again, try force removing ===
{"execute": "block-export-del", "arguments": {"id": "export1"}}
{"error": {"class": "GenericError", "desc": "export 'export1' still in use"}}
{"execute": "block-export-del", "arguments": {"id": "export1", "mode": "hard"}}
{"return": {}}
read failed: Input/output error
{"execute": "query-block-exports", "arguments": {}}
{"return": []}
exports available: 0
=== Shut down QEMU ===