The NBD specification defines NBD_FLAG_CAN_MULTI_CONN, which can be advertised when the server promises cache consistency between simultaneous clients (basically, rules that determine what FUA and flush from one client are able to guarantee for reads from another client). When we don't permit simultaneous clients (such as qemu-nbd without -e), the bit makes no sense; and for writable images, we probably have a lot more work before we can declare that actions from one client are cache-consistent with actions from another. But for read-only images, where flush isn't changing any data, we might as well advertise multi-conn support. What's more, advertisement of the bit makes it easier for clients to determine if 'qemu-nbd -e' was in use, where a second connection will succeed rather than hang until the first client goes away. This patch affects qemu as server in advertising the bit. We may want to consider patches to qemu as client to attempt parallel connections for higher throughput by spreading the load over those connections when a server advertises multi-conn, but for now sticking to one connection per nbd:// BDS is okay. See also: https://bugzilla.redhat.com/1708300 Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <20190815185024.7010-1-eblake@redhat.com> [eblake: tweak blockdev-nbd.c to not request shared when writable, fix iotest 233] Reviewed-by: John Snow <jsnow@redhat.com>
104 lines
4.2 KiB
Plaintext
104 lines
4.2 KiB
Plaintext
QA output created by 223
|
|
|
|
=== Create partially sparse image, then add dirty bitmaps ===
|
|
|
|
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304
|
|
wrote 2097152/2097152 bytes at offset 1048576
|
|
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
Testing:
|
|
QMP_VERSION
|
|
{"return": {}}
|
|
{"return": {}}
|
|
{"return": {}}
|
|
{"return": {}}
|
|
{"return": {}}
|
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
|
|
|
|
|
=== Write part of the file under active bitmap ===
|
|
|
|
wrote 512/512 bytes at offset 512
|
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
wrote 2097152/2097152 bytes at offset 2097152
|
|
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
|
|
=== End dirty bitmaps, and start serving image over NBD ===
|
|
|
|
{"return": {}}
|
|
{"return": {}}
|
|
{"return": {}}
|
|
{"error": {"class": "GenericError", "desc": "NBD server not running"}}
|
|
{"return": {}}
|
|
{"error": {"class": "GenericError", "desc": "NBD server already running"}}
|
|
exports available: 0
|
|
{"return": {}}
|
|
{"error": {"class": "GenericError", "desc": "Cannot find device=nosuch nor node_name=nosuch"}}
|
|
{"error": {"class": "GenericError", "desc": "NBD server already has export named 'n'"}}
|
|
{"error": {"class": "GenericError", "desc": "Enabled bitmap 'b2' incompatible with readonly export"}}
|
|
{"error": {"class": "GenericError", "desc": "Bitmap 'b3' is not found"}}
|
|
{"return": {}}
|
|
exports available: 2
|
|
export: 'n'
|
|
size: 4194304
|
|
flags: 0x5ef ( readonly flush fua trim zeroes df multi cache )
|
|
min block: 1
|
|
opt block: 4096
|
|
max block: 33554432
|
|
available meta contexts: 2
|
|
base:allocation
|
|
qemu:dirty-bitmap:b
|
|
export: 'n2'
|
|
size: 4194304
|
|
flags: 0x4ed ( flush fua trim zeroes df cache )
|
|
min block: 1
|
|
opt block: 4096
|
|
max block: 33554432
|
|
available meta contexts: 2
|
|
base:allocation
|
|
qemu:dirty-bitmap:b2
|
|
|
|
=== Contrast normal status to large granularity dirty-bitmap ===
|
|
|
|
read 512/512 bytes at offset 512
|
|
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
read 524288/524288 bytes at offset 524288
|
|
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
read 1048576/1048576 bytes at offset 1048576
|
|
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
read 2097152/2097152 bytes at offset 2097152
|
|
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
|
{ "start": 1048576, "length": 3145728, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
|
|
[{ "start": 0, "length": 65536, "depth": 0, "zero": false, "data": false},
|
|
{ "start": 65536, "length": 2031616, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
|
|
|
|
=== Contrast to small granularity dirty-bitmap ===
|
|
|
|
[{ "start": 0, "length": 512, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
{ "start": 512, "length": 512, "depth": 0, "zero": false, "data": false},
|
|
{ "start": 1024, "length": 2096128, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
|
|
|
|
=== End qemu NBD server ===
|
|
|
|
{"return": {}}
|
|
{"return": {}}
|
|
{"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}}
|
|
{"return": {}}
|
|
{"error": {"class": "GenericError", "desc": "NBD server not running"}}
|
|
{"return": {}}
|
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
|
|
|
=== Use qemu-nbd as server ===
|
|
|
|
[{ "start": 0, "length": 65536, "depth": 0, "zero": false, "data": false},
|
|
{ "start": 65536, "length": 2031616, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
|
|
[{ "start": 0, "length": 512, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
{ "start": 512, "length": 512, "depth": 0, "zero": false, "data": false},
|
|
{ "start": 1024, "length": 2096128, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
|
|
*** done
|