2008-07-03 14:23:51 +04:00
|
|
|
/*
|
2008-05-28 01:13:40 +04:00
|
|
|
* Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws>
|
|
|
|
*
|
|
|
|
* Network Block Device
|
|
|
|
*
|
|
|
|
* 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; under version 2 of the License.
|
|
|
|
*
|
|
|
|
* 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
|
2009-07-17 00:47:01 +04:00
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
2008-05-28 01:13:40 +04:00
|
|
|
*/
|
|
|
|
|
2016-01-29 20:50:05 +03:00
|
|
|
#include "qemu/osdep.h"
|
2017-07-21 16:50:47 +03:00
|
|
|
#include <getopt.h>
|
|
|
|
#include <libgen.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
|
2022-04-20 16:25:49 +03:00
|
|
|
#include "qemu/help-texts.h"
|
include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef. Since then, we've moved to include qemu/osdep.h
everywhere. Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h. That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h. Include qapi/error.h in .c files that need it and don't
get it now. Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly. Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third. Unfortunately, the number depending on
qapi-types.h shrinks only a little. More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-03-14 11:01:28 +03:00
|
|
|
#include "qapi/error.h"
|
2016-03-20 20:16:19 +03:00
|
|
|
#include "qemu/cutils.h"
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
#include "sysemu/block-backend.h"
|
2020-09-29 15:55:15 +03:00
|
|
|
#include "sysemu/runstate.h" /* for qemu_system_killed() prototype */
|
2014-08-13 21:20:18 +04:00
|
|
|
#include "block/block_int.h"
|
2012-12-17 21:19:44 +04:00
|
|
|
#include "block/nbd.h"
|
2013-08-21 19:02:47 +04:00
|
|
|
#include "qemu/main-loop.h"
|
2019-05-23 17:35:07 +03:00
|
|
|
#include "qemu/module.h"
|
2018-02-01 14:18:46 +03:00
|
|
|
#include "qemu/option.h"
|
2014-02-17 17:43:51 +04:00
|
|
|
#include "qemu/error-report.h"
|
2016-02-10 21:41:00 +03:00
|
|
|
#include "qemu/config-file.h"
|
2016-03-15 19:22:36 +03:00
|
|
|
#include "qemu/bswap.h"
|
2016-06-17 17:44:12 +03:00
|
|
|
#include "qemu/log.h"
|
2017-03-16 18:29:45 +03:00
|
|
|
#include "qemu/systemd.h"
|
2013-12-04 13:10:55 +04:00
|
|
|
#include "block/snapshot.h"
|
2018-02-01 14:18:39 +03:00
|
|
|
#include "qapi/qmp/qdict.h"
|
2015-03-17 20:29:20 +03:00
|
|
|
#include "qapi/qmp/qstring.h"
|
2016-02-10 21:41:00 +03:00
|
|
|
#include "qom/object_interfaces.h"
|
2016-02-10 21:41:02 +03:00
|
|
|
#include "io/channel-socket.h"
|
2017-12-18 13:16:43 +03:00
|
|
|
#include "io/net-listener.h"
|
2016-04-06 14:12:06 +03:00
|
|
|
#include "crypto/init.h"
|
2021-06-28 19:09:10 +03:00
|
|
|
#include "crypto/tlscreds.h"
|
2016-06-17 17:44:12 +03:00
|
|
|
#include "trace/control.h"
|
2017-07-21 16:50:46 +03:00
|
|
|
#include "qemu-version.h"
|
2008-05-28 01:13:40 +04:00
|
|
|
|
2021-11-15 23:29:43 +03:00
|
|
|
#ifdef CONFIG_SELINUX
|
|
|
|
#include <selinux/selinux.h>
|
|
|
|
#endif
|
|
|
|
|
2018-12-15 16:53:08 +03:00
|
|
|
#ifdef __linux__
|
|
|
|
#define HAVE_NBD_DEVICE 1
|
|
|
|
#else
|
|
|
|
#define HAVE_NBD_DEVICE 0
|
|
|
|
#endif
|
|
|
|
|
2014-08-13 21:20:19 +04:00
|
|
|
#define SOCKET_PATH "/var/lock/qemu-nbd-%s"
|
2016-02-17 13:10:21 +03:00
|
|
|
#define QEMU_NBD_OPT_CACHE 256
|
|
|
|
#define QEMU_NBD_OPT_AIO 257
|
|
|
|
#define QEMU_NBD_OPT_DISCARD 258
|
|
|
|
#define QEMU_NBD_OPT_DETECT_ZEROES 259
|
|
|
|
#define QEMU_NBD_OPT_OBJECT 260
|
|
|
|
#define QEMU_NBD_OPT_TLSCREDS 261
|
|
|
|
#define QEMU_NBD_OPT_IMAGE_OPTS 262
|
2016-09-28 23:46:42 +03:00
|
|
|
#define QEMU_NBD_OPT_FORK 263
|
qemu-nbd: add support for authorization of TLS clients
Currently any client which can complete the TLS handshake is able to use
the NBD server. The server admin can turn on the 'verify-peer' option
for the x509 creds to require the client to provide a x509 certificate.
This means the client will have to acquire a certificate from the CA
before they are permitted to use the NBD server. This is still a fairly
low bar to cross.
This adds a '--tls-authz OBJECT-ID' option to the qemu-nbd command which
takes the ID of a previously added 'QAuthZ' object instance. This will
be used to validate the client's x509 distinguished name. Clients
failing the authorization check will not be permitted to use the NBD
server.
For example to setup authorization that only allows connection from a client
whose x509 certificate distinguished name is
CN=laptop.example.com,O=Example Org,L=London,ST=London,C=GB
escape the commas in the name and use:
qemu-nbd --object tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\
endpoint=server,verify-peer=yes \
--object 'authz-simple,id=auth0,identity=CN=laptop.example.com,,\
O=Example Org,,L=London,,ST=London,,C=GB' \
--tls-creds tls0 \
--tls-authz authz0 \
....other qemu-nbd args...
NB: a real shell command line would not have leading whitespace after
the line continuation, it is just included here for clarity.
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <20190227162035.18543-2-berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[eblake: split long line in --help text, tweak 233 to show that whitespace
after ,, in identity= portion is actually okay]
Signed-off-by: Eric Blake <eblake@redhat.com>
2019-02-27 19:20:33 +03:00
|
|
|
#define QEMU_NBD_OPT_TLSAUTHZ 264
|
2019-05-09 00:18:16 +03:00
|
|
|
#define QEMU_NBD_OPT_PID_FILE 265
|
2021-11-15 23:29:43 +03:00
|
|
|
#define QEMU_NBD_OPT_SELINUX_LABEL 266
|
2022-03-04 22:36:02 +03:00
|
|
|
#define QEMU_NBD_OPT_TLSHOSTNAME 267
|
2008-05-28 01:13:40 +04:00
|
|
|
|
2016-05-06 19:26:42 +03:00
|
|
|
#define MBR_SIZE 512
|
|
|
|
|
2011-11-04 18:51:21 +04:00
|
|
|
static char *srcpath;
|
2017-04-26 10:36:41 +03:00
|
|
|
static SocketAddress *saddr;
|
2012-09-18 15:31:56 +04:00
|
|
|
static int persistent = 0;
|
2020-09-24 18:26:56 +03:00
|
|
|
static enum { RUNNING, TERMINATE, TERMINATED } state;
|
2011-09-12 19:28:11 +04:00
|
|
|
static int shared = 1;
|
|
|
|
static int nb_fds;
|
2017-12-18 13:16:43 +03:00
|
|
|
static QIONetListener *server;
|
2016-02-10 21:41:13 +03:00
|
|
|
static QCryptoTLSCreds *tlscreds;
|
qemu-nbd: add support for authorization of TLS clients
Currently any client which can complete the TLS handshake is able to use
the NBD server. The server admin can turn on the 'verify-peer' option
for the x509 creds to require the client to provide a x509 certificate.
This means the client will have to acquire a certificate from the CA
before they are permitted to use the NBD server. This is still a fairly
low bar to cross.
This adds a '--tls-authz OBJECT-ID' option to the qemu-nbd command which
takes the ID of a previously added 'QAuthZ' object instance. This will
be used to validate the client's x509 distinguished name. Clients
failing the authorization check will not be permitted to use the NBD
server.
For example to setup authorization that only allows connection from a client
whose x509 certificate distinguished name is
CN=laptop.example.com,O=Example Org,L=London,ST=London,C=GB
escape the commas in the name and use:
qemu-nbd --object tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\
endpoint=server,verify-peer=yes \
--object 'authz-simple,id=auth0,identity=CN=laptop.example.com,,\
O=Example Org,,L=London,,ST=London,,C=GB' \
--tls-creds tls0 \
--tls-authz authz0 \
....other qemu-nbd args...
NB: a real shell command line would not have leading whitespace after
the line continuation, it is just included here for clarity.
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <20190227162035.18543-2-berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[eblake: split long line in --help text, tweak 233 to show that whitespace
after ,, in identity= portion is actually okay]
Signed-off-by: Eric Blake <eblake@redhat.com>
2019-02-27 19:20:33 +03:00
|
|
|
static const char *tlsauthz;
|
2008-05-28 01:13:40 +04:00
|
|
|
|
|
|
|
static void usage(const char *name)
|
|
|
|
{
|
2012-07-18 16:50:52 +04:00
|
|
|
(printf) (
|
2008-05-28 01:13:40 +04:00
|
|
|
"Usage: %s [OPTIONS] FILE\n"
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
" or: %s -L [OPTIONS]\n"
|
|
|
|
"QEMU Disk Network Block Device Utility\n"
|
2008-05-28 01:13:40 +04:00
|
|
|
"\n"
|
2014-08-13 21:20:19 +04:00
|
|
|
" -h, --help display this help and exit\n"
|
|
|
|
" -V, --version output version information and exit\n"
|
2012-07-18 16:50:52 +04:00
|
|
|
"\n"
|
|
|
|
"Connection properties:\n"
|
2014-08-13 21:20:19 +04:00
|
|
|
" -p, --port=PORT port to listen on (default `%d')\n"
|
|
|
|
" -b, --bind=IFACE interface to bind to (default `0.0.0.0')\n"
|
|
|
|
" -k, --socket=PATH path to the unix socket\n"
|
|
|
|
" (default '"SOCKET_PATH"')\n"
|
|
|
|
" -e, --shared=NUM device can be shared by NUM clients (default '1')\n"
|
|
|
|
" -t, --persistent don't exit on the last connection\n"
|
|
|
|
" -v, --verbose display extra debugging information\n"
|
2018-10-03 20:02:27 +03:00
|
|
|
" -x, --export-name=NAME expose export by name (default is empty string)\n"
|
|
|
|
" -D, --description=TEXT export a human-readable description\n"
|
2008-05-28 01:13:40 +04:00
|
|
|
"\n"
|
2012-07-18 16:50:52 +04:00
|
|
|
"Exposing part of the image:\n"
|
2014-08-13 21:20:19 +04:00
|
|
|
" -o, --offset=OFFSET offset into the image\n"
|
2020-10-27 08:05:55 +03:00
|
|
|
" -A, --allocation-depth expose the allocation depth\n"
|
2019-01-11 22:47:20 +03:00
|
|
|
" -B, --bitmap=NAME expose a persistent dirty bitmap\n"
|
2012-07-18 16:50:52 +04:00
|
|
|
"\n"
|
2016-02-10 21:41:00 +03:00
|
|
|
"General purpose options:\n"
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
" -L, --list list exports available from another NBD server\n"
|
2016-02-10 21:41:00 +03:00
|
|
|
" --object type,id=ID,... define an object such as 'secret' for providing\n"
|
|
|
|
" passwords and/or encryption keys\n"
|
2018-10-03 21:04:26 +03:00
|
|
|
" --tls-creds=ID use id of an earlier --object to provide TLS\n"
|
qemu-nbd: add support for authorization of TLS clients
Currently any client which can complete the TLS handshake is able to use
the NBD server. The server admin can turn on the 'verify-peer' option
for the x509 creds to require the client to provide a x509 certificate.
This means the client will have to acquire a certificate from the CA
before they are permitted to use the NBD server. This is still a fairly
low bar to cross.
This adds a '--tls-authz OBJECT-ID' option to the qemu-nbd command which
takes the ID of a previously added 'QAuthZ' object instance. This will
be used to validate the client's x509 distinguished name. Clients
failing the authorization check will not be permitted to use the NBD
server.
For example to setup authorization that only allows connection from a client
whose x509 certificate distinguished name is
CN=laptop.example.com,O=Example Org,L=London,ST=London,C=GB
escape the commas in the name and use:
qemu-nbd --object tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\
endpoint=server,verify-peer=yes \
--object 'authz-simple,id=auth0,identity=CN=laptop.example.com,,\
O=Example Org,,L=London,,ST=London,,C=GB' \
--tls-creds tls0 \
--tls-authz authz0 \
....other qemu-nbd args...
NB: a real shell command line would not have leading whitespace after
the line continuation, it is just included here for clarity.
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <20190227162035.18543-2-berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[eblake: split long line in --help text, tweak 233 to show that whitespace
after ,, in identity= portion is actually okay]
Signed-off-by: Eric Blake <eblake@redhat.com>
2019-02-27 19:20:33 +03:00
|
|
|
" --tls-authz=ID use id of an earlier --object to provide\n"
|
|
|
|
" authorization\n"
|
2016-06-17 17:44:12 +03:00
|
|
|
" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
|
|
|
|
" specify tracing options\n"
|
2016-09-28 23:46:42 +03:00
|
|
|
" --fork fork off the server process and exit the parent\n"
|
|
|
|
" once the server is running\n"
|
2019-05-09 00:18:16 +03:00
|
|
|
" --pid-file=PATH store the server's process ID in the given file\n"
|
2021-11-15 23:29:43 +03:00
|
|
|
#ifdef CONFIG_SELINUX
|
|
|
|
" --selinux-label=LABEL set SELinux process label on listening socket\n"
|
|
|
|
#endif
|
2018-12-15 16:53:08 +03:00
|
|
|
#if HAVE_NBD_DEVICE
|
|
|
|
"\n"
|
2012-07-18 16:50:52 +04:00
|
|
|
"Kernel NBD client support:\n"
|
2014-08-13 21:20:19 +04:00
|
|
|
" -c, --connect=DEV connect FILE to the local NBD device DEV\n"
|
|
|
|
" -d, --disconnect disconnect the specified device\n"
|
2012-07-18 16:50:52 +04:00
|
|
|
#endif
|
|
|
|
"\n"
|
|
|
|
"Block device options:\n"
|
2014-08-13 21:20:19 +04:00
|
|
|
" -f, --format=FORMAT set image format (raw, qcow2, ...)\n"
|
|
|
|
" -r, --read-only export read-only\n"
|
|
|
|
" -s, --snapshot use FILE as an external snapshot, create a temporary\n"
|
|
|
|
" file with backing_file=FILE, redirect the write to\n"
|
|
|
|
" the temporary one\n"
|
2013-12-04 13:10:55 +04:00
|
|
|
" -l, --load-snapshot=SNAPSHOT_PARAM\n"
|
2014-08-13 21:20:19 +04:00
|
|
|
" load an internal snapshot inside FILE and export it\n"
|
|
|
|
" as an read-only device, SNAPSHOT_PARAM format is\n"
|
|
|
|
" 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
|
|
|
|
" '[ID_OR_NAME]'\n"
|
|
|
|
" -n, --nocache disable host cache\n"
|
2021-08-13 23:55:19 +03:00
|
|
|
" --cache=MODE set cache mode used to access the disk image, the\n"
|
|
|
|
" valid options are: 'none', 'writeback' (default),\n"
|
|
|
|
" 'writethrough', 'directsync' and 'unsafe'\n"
|
2020-01-20 17:18:56 +03:00
|
|
|
" --aio=MODE set AIO mode (native, io_uring or threads)\n"
|
2014-08-13 21:20:18 +04:00
|
|
|
" --discard=MODE set discard mode (ignore, unmap)\n"
|
2015-07-31 22:12:54 +03:00
|
|
|
" --detect-zeroes=MODE set detect-zeroes mode (off, on, unmap)\n"
|
2016-02-17 13:10:19 +03:00
|
|
|
" --image-opts treat FILE as a full set of image options\n"
|
2012-07-18 16:50:52 +04:00
|
|
|
"\n"
|
2017-08-03 19:33:53 +03:00
|
|
|
QEMU_HELP_BOTTOM "\n"
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
, name, name, NBD_DEFAULT_PORT, "DEVICE");
|
2008-05-28 01:13:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void version(const char *name)
|
|
|
|
{
|
|
|
|
printf(
|
2018-02-15 14:06:47 +03:00
|
|
|
"%s " QEMU_FULL_VERSION "\n"
|
2008-05-28 01:13:40 +04:00
|
|
|
"Written by Anthony Liguori.\n"
|
|
|
|
"\n"
|
2017-07-21 16:50:46 +03:00
|
|
|
QEMU_COPYRIGHT "\n"
|
2008-05-28 01:13:40 +04:00
|
|
|
"This is free software; see the source for copying conditions. There is NO\n"
|
|
|
|
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
|
2008-07-18 22:06:23 +04:00
|
|
|
, name);
|
2008-05-28 01:13:40 +04:00
|
|
|
}
|
|
|
|
|
2020-09-30 15:11:01 +03:00
|
|
|
#ifdef CONFIG_POSIX
|
2020-09-29 15:55:15 +03:00
|
|
|
/*
|
|
|
|
* The client thread uses SIGTERM to interrupt the server. A signal
|
|
|
|
* handler ensures that "qemu-nbd -v -c" exits with a nice status code.
|
|
|
|
*/
|
|
|
|
void qemu_system_killed(int signum, pid_t pid)
|
2011-11-04 18:51:19 +04:00
|
|
|
{
|
2020-09-23 13:56:46 +03:00
|
|
|
qatomic_cmpxchg(&state, RUNNING, TERMINATE);
|
2011-09-12 19:28:11 +04:00
|
|
|
qemu_notify_event();
|
2011-11-04 18:51:19 +04:00
|
|
|
}
|
2020-09-30 15:11:01 +03:00
|
|
|
#endif /* CONFIG_POSIX */
|
2014-02-17 17:43:51 +04:00
|
|
|
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
static int qemu_nbd_client_list(SocketAddress *saddr, QCryptoTLSCreds *tls,
|
|
|
|
const char *hostname)
|
|
|
|
{
|
|
|
|
int ret = EXIT_FAILURE;
|
|
|
|
int rc;
|
|
|
|
Error *err = NULL;
|
|
|
|
QIOChannelSocket *sioc;
|
|
|
|
NBDExportInfo *list;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
sioc = qio_channel_socket_new();
|
|
|
|
if (qio_channel_socket_connect_sync(sioc, saddr, &err) < 0) {
|
|
|
|
error_report_err(err);
|
2020-11-30 15:36:51 +03:00
|
|
|
goto out;
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
}
|
|
|
|
rc = nbd_receive_export_list(QIO_CHANNEL(sioc), tls, hostname, &list,
|
|
|
|
&err);
|
|
|
|
if (rc < 0) {
|
|
|
|
if (err) {
|
|
|
|
error_report_err(err);
|
|
|
|
}
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
printf("exports available: %d\n", rc);
|
|
|
|
for (i = 0; i < rc; i++) {
|
|
|
|
printf(" export: '%s'\n", list[i].name);
|
|
|
|
if (list[i].description && *list[i].description) {
|
|
|
|
printf(" description: %s\n", list[i].description);
|
|
|
|
}
|
|
|
|
if (list[i].flags & NBD_FLAG_HAS_FLAGS) {
|
2019-04-05 22:16:35 +03:00
|
|
|
static const char *const flag_names[] = {
|
|
|
|
[NBD_FLAG_READ_ONLY_BIT] = "readonly",
|
|
|
|
[NBD_FLAG_SEND_FLUSH_BIT] = "flush",
|
|
|
|
[NBD_FLAG_SEND_FUA_BIT] = "fua",
|
|
|
|
[NBD_FLAG_ROTATIONAL_BIT] = "rotational",
|
|
|
|
[NBD_FLAG_SEND_TRIM_BIT] = "trim",
|
|
|
|
[NBD_FLAG_SEND_WRITE_ZEROES_BIT] = "zeroes",
|
|
|
|
[NBD_FLAG_SEND_DF_BIT] = "df",
|
|
|
|
[NBD_FLAG_CAN_MULTI_CONN_BIT] = "multi",
|
|
|
|
[NBD_FLAG_SEND_RESIZE_BIT] = "resize",
|
|
|
|
[NBD_FLAG_SEND_CACHE_BIT] = "cache",
|
2019-08-23 17:37:23 +03:00
|
|
|
[NBD_FLAG_SEND_FAST_ZERO_BIT] = "fast-zero",
|
2019-04-05 22:16:35 +03:00
|
|
|
};
|
|
|
|
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
printf(" size: %" PRIu64 "\n", list[i].size);
|
|
|
|
printf(" flags: 0x%x (", list[i].flags);
|
2019-04-05 22:16:35 +03:00
|
|
|
for (size_t bit = 0; bit < ARRAY_SIZE(flag_names); bit++) {
|
|
|
|
if (flag_names[bit] && (list[i].flags & (1 << bit))) {
|
|
|
|
printf(" %s", flag_names[bit]);
|
|
|
|
}
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
}
|
|
|
|
printf(" )\n");
|
|
|
|
}
|
|
|
|
if (list[i].min_block) {
|
|
|
|
printf(" min block: %u\n", list[i].min_block);
|
|
|
|
printf(" opt block: %u\n", list[i].opt_block);
|
|
|
|
printf(" max block: %u\n", list[i].max_block);
|
|
|
|
}
|
|
|
|
if (list[i].n_contexts) {
|
|
|
|
printf(" available meta contexts: %d\n", list[i].n_contexts);
|
|
|
|
for (j = 0; j < list[i].n_contexts; j++) {
|
|
|
|
printf(" %s\n", list[i].contexts[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nbd_free_export_list(list, rc);
|
|
|
|
|
|
|
|
ret = EXIT_SUCCESS;
|
|
|
|
out:
|
|
|
|
object_unref(OBJECT(sioc));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-12-15 16:53:08 +03:00
|
|
|
#if HAVE_NBD_DEVICE
|
2011-11-04 18:51:21 +04:00
|
|
|
static void *show_parts(void *arg)
|
2008-07-03 14:23:51 +04:00
|
|
|
{
|
2011-12-06 12:07:00 +04:00
|
|
|
char *device = arg;
|
2011-11-04 18:51:21 +04:00
|
|
|
int nbd;
|
|
|
|
|
|
|
|
/* linux just needs an open() to trigger
|
|
|
|
* the partition table update
|
|
|
|
* but remember to load the module with max_part != 0 :
|
|
|
|
* modprobe nbd max_part=63
|
|
|
|
*/
|
|
|
|
nbd = open(device, O_RDWR);
|
2012-03-07 14:05:34 +04:00
|
|
|
if (nbd >= 0) {
|
2011-11-04 18:51:21 +04:00
|
|
|
close(nbd);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-07-03 14:23:51 +04:00
|
|
|
|
2023-07-17 17:55:40 +03:00
|
|
|
struct NbdClientOpts {
|
|
|
|
char *device;
|
2023-07-17 17:55:41 +03:00
|
|
|
bool fork_process;
|
2023-07-17 23:25:20 +03:00
|
|
|
bool verbose;
|
2023-07-17 17:55:40 +03:00
|
|
|
};
|
|
|
|
|
2011-11-04 18:51:21 +04:00
|
|
|
static void *nbd_client_thread(void *arg)
|
|
|
|
{
|
2023-07-17 17:55:40 +03:00
|
|
|
struct NbdClientOpts *opts = arg;
|
2019-01-17 22:36:46 +03:00
|
|
|
NBDExportInfo info = { .request_sizes = false, .name = g_strdup("") };
|
2016-02-10 21:41:02 +03:00
|
|
|
QIOChannelSocket *sioc;
|
2020-12-08 16:49:44 +03:00
|
|
|
int fd = -1;
|
|
|
|
int ret = EXIT_FAILURE;
|
2011-11-04 18:51:21 +04:00
|
|
|
pthread_t show_parts_thread;
|
2015-01-27 05:02:59 +03:00
|
|
|
Error *local_error = NULL;
|
2011-11-04 18:51:21 +04:00
|
|
|
|
2016-02-10 21:41:02 +03:00
|
|
|
sioc = qio_channel_socket_new();
|
|
|
|
if (qio_channel_socket_connect_sync(sioc,
|
|
|
|
saddr,
|
|
|
|
&local_error) < 0) {
|
2015-09-16 16:52:23 +03:00
|
|
|
error_report_err(local_error);
|
2012-01-05 17:16:07 +04:00
|
|
|
goto out;
|
|
|
|
}
|
2011-11-04 18:51:21 +04:00
|
|
|
|
2020-12-08 16:49:44 +03:00
|
|
|
if (nbd_receive_negotiate(NULL, QIO_CHANNEL(sioc),
|
|
|
|
NULL, NULL, NULL, &info, &local_error) < 0) {
|
2015-01-27 05:02:59 +03:00
|
|
|
if (local_error) {
|
2015-12-18 18:35:07 +03:00
|
|
|
error_report_err(local_error);
|
2015-01-27 05:02:59 +03:00
|
|
|
}
|
2020-12-08 16:49:44 +03:00
|
|
|
goto out;
|
2011-11-04 18:51:21 +04:00
|
|
|
}
|
|
|
|
|
2023-07-17 17:55:40 +03:00
|
|
|
fd = open(opts->device, O_RDWR);
|
2012-03-07 14:05:34 +04:00
|
|
|
if (fd < 0) {
|
2011-12-06 12:07:00 +04:00
|
|
|
/* Linux-only, we can use %m in printf. */
|
2023-07-17 17:55:40 +03:00
|
|
|
error_report("Failed to open %s: %m", opts->device);
|
2020-12-08 16:49:44 +03:00
|
|
|
goto out;
|
2011-12-06 12:07:00 +04:00
|
|
|
}
|
|
|
|
|
2020-12-08 16:49:44 +03:00
|
|
|
if (nbd_init(fd, sioc, &info, &local_error) < 0) {
|
2017-05-26 14:09:13 +03:00
|
|
|
error_report_err(local_error);
|
2020-12-08 16:49:44 +03:00
|
|
|
goto out;
|
2011-11-04 18:51:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* update partition table */
|
2023-07-17 17:55:40 +03:00
|
|
|
pthread_create(&show_parts_thread, NULL, show_parts, opts->device);
|
2011-11-04 18:51:21 +04:00
|
|
|
|
2023-07-17 23:25:20 +03:00
|
|
|
if (opts->verbose && !opts->fork_process) {
|
2011-11-04 18:51:22 +04:00
|
|
|
fprintf(stderr, "NBD device %s is now connected to %s\n",
|
2023-07-17 17:55:40 +03:00
|
|
|
opts->device, srcpath);
|
2011-11-04 18:51:22 +04:00
|
|
|
} else {
|
|
|
|
/* Close stderr so that the qemu-nbd process exits. */
|
2023-07-17 17:55:44 +03:00
|
|
|
if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) {
|
|
|
|
error_report("Could not set stderr to /dev/null: %s",
|
|
|
|
strerror(errno));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2011-11-04 18:51:22 +04:00
|
|
|
}
|
2011-11-04 18:51:21 +04:00
|
|
|
|
2020-12-08 16:49:44 +03:00
|
|
|
if (nbd_client(fd) < 0) {
|
|
|
|
goto out;
|
2008-07-03 14:23:51 +04:00
|
|
|
}
|
2011-11-04 18:51:21 +04:00
|
|
|
|
2020-12-08 16:49:44 +03:00
|
|
|
ret = EXIT_SUCCESS;
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (fd >= 0) {
|
|
|
|
close(fd);
|
|
|
|
}
|
2016-02-10 21:41:02 +03:00
|
|
|
object_unref(OBJECT(sioc));
|
2019-01-17 22:36:46 +03:00
|
|
|
g_free(info.name);
|
2011-11-04 18:51:21 +04:00
|
|
|
kill(getpid(), SIGTERM);
|
2020-12-08 16:49:44 +03:00
|
|
|
return (void *) (intptr_t) ret;
|
2008-07-03 14:23:51 +04:00
|
|
|
}
|
2018-12-15 16:53:08 +03:00
|
|
|
#endif /* HAVE_NBD_DEVICE */
|
2008-07-03 14:23:51 +04:00
|
|
|
|
2015-05-19 13:50:59 +03:00
|
|
|
static int nbd_can_accept(void)
|
2011-09-12 19:28:11 +04:00
|
|
|
{
|
2021-02-09 18:27:59 +03:00
|
|
|
return state == RUNNING && (shared == 0 || nb_fds < shared);
|
2011-09-12 19:28:11 +04:00
|
|
|
}
|
|
|
|
|
2016-02-10 21:41:02 +03:00
|
|
|
static void nbd_update_server_watch(void);
|
2015-05-19 13:50:59 +03:00
|
|
|
|
nbd: Fix regression on resiliency to port scan
Back in qemu 2.5, qemu-nbd was immune to port probes (a transient
server would not quit, regardless of how many probe connections
came and went, until a connection actually negotiated). But we
broke that in commit ee7d7aa when removing the return value to
nbd_client_new(), although that patch also introduced a bug causing
an assertion failure on a client that fails negotiation. We then
made it worse during refactoring in commit 1a6245a (a segfault
before we could even assert); the (masked) assertion was cleaned
up in d3780c2 (still in 2.6), and just recently we finally fixed
the segfault ("nbd: Fully intialize client in case of failed
negotiation"). But that still means that ever since we added
TLS support to qemu-nbd, we have been vulnerable to an ill-timed
port-scan being able to cause a denial of service by taking down
qemu-nbd before a real client has a chance to connect.
Since negotiation is now handled asynchronously via coroutines,
we no longer have a synchronous point of return by re-adding a
return value to nbd_client_new(). So this patch instead wires
things up to pass the negotiation status through the close_fn
callback function.
Simple test across two terminals:
$ qemu-nbd -f raw -p 30001 file
$ nmap 127.0.0.1 -p 30001 && \
qemu-io -c 'r 0 512' -f raw nbd://localhost:30001
Note that this patch does not change what constitutes successful
negotiation (thus, a client must enter transmission phase before
that client can be considered as a reason to terminate the server
when the connection ends). Perhaps we may want to tweak things
in a later patch to also treat a client that uses NBD_OPT_ABORT
as being a 'successful' negotiation (the client correctly talked
the NBD protocol, and informed us it was not going to use our
export after all), but that's a discussion for another day.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1451614
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170608222617.20376-1-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-06-09 01:26:17 +03:00
|
|
|
static void nbd_client_closed(NBDClient *client, bool negotiated)
|
2011-09-12 19:28:11 +04:00
|
|
|
{
|
2011-09-19 16:33:23 +04:00
|
|
|
nb_fds--;
|
nbd: Fix regression on resiliency to port scan
Back in qemu 2.5, qemu-nbd was immune to port probes (a transient
server would not quit, regardless of how many probe connections
came and went, until a connection actually negotiated). But we
broke that in commit ee7d7aa when removing the return value to
nbd_client_new(), although that patch also introduced a bug causing
an assertion failure on a client that fails negotiation. We then
made it worse during refactoring in commit 1a6245a (a segfault
before we could even assert); the (masked) assertion was cleaned
up in d3780c2 (still in 2.6), and just recently we finally fixed
the segfault ("nbd: Fully intialize client in case of failed
negotiation"). But that still means that ever since we added
TLS support to qemu-nbd, we have been vulnerable to an ill-timed
port-scan being able to cause a denial of service by taking down
qemu-nbd before a real client has a chance to connect.
Since negotiation is now handled asynchronously via coroutines,
we no longer have a synchronous point of return by re-adding a
return value to nbd_client_new(). So this patch instead wires
things up to pass the negotiation status through the close_fn
callback function.
Simple test across two terminals:
$ qemu-nbd -f raw -p 30001 file
$ nmap 127.0.0.1 -p 30001 && \
qemu-io -c 'r 0 512' -f raw nbd://localhost:30001
Note that this patch does not change what constitutes successful
negotiation (thus, a client must enter transmission phase before
that client can be considered as a reason to terminate the server
when the connection ends). Perhaps we may want to tweak things
in a later patch to also treat a client that uses NBD_OPT_ABORT
as being a 'successful' negotiation (the client correctly talked
the NBD protocol, and informed us it was not going to use our
export after all), but that's a discussion for another day.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1451614
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170608222617.20376-1-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-06-09 01:26:17 +03:00
|
|
|
if (negotiated && nb_fds == 0 && !persistent && state == RUNNING) {
|
2012-09-18 15:31:56 +04:00
|
|
|
state = TERMINATE;
|
|
|
|
}
|
2016-02-10 21:41:02 +03:00
|
|
|
nbd_update_server_watch();
|
2012-09-18 15:31:56 +04:00
|
|
|
nbd_client_put(client);
|
2011-09-12 19:28:11 +04:00
|
|
|
}
|
|
|
|
|
2017-12-18 13:16:43 +03:00
|
|
|
static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
|
|
|
|
gpointer opaque)
|
2011-09-12 19:28:11 +04:00
|
|
|
{
|
2012-09-18 15:31:56 +04:00
|
|
|
if (state >= TERMINATE) {
|
2017-12-18 13:16:43 +03:00
|
|
|
return;
|
2012-09-18 15:31:56 +04:00
|
|
|
}
|
|
|
|
|
2016-01-14 11:41:01 +03:00
|
|
|
nb_fds++;
|
2016-02-10 21:41:02 +03:00
|
|
|
nbd_update_server_watch();
|
qemu-nbd: add support for authorization of TLS clients
Currently any client which can complete the TLS handshake is able to use
the NBD server. The server admin can turn on the 'verify-peer' option
for the x509 creds to require the client to provide a x509 certificate.
This means the client will have to acquire a certificate from the CA
before they are permitted to use the NBD server. This is still a fairly
low bar to cross.
This adds a '--tls-authz OBJECT-ID' option to the qemu-nbd command which
takes the ID of a previously added 'QAuthZ' object instance. This will
be used to validate the client's x509 distinguished name. Clients
failing the authorization check will not be permitted to use the NBD
server.
For example to setup authorization that only allows connection from a client
whose x509 certificate distinguished name is
CN=laptop.example.com,O=Example Org,L=London,ST=London,C=GB
escape the commas in the name and use:
qemu-nbd --object tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\
endpoint=server,verify-peer=yes \
--object 'authz-simple,id=auth0,identity=CN=laptop.example.com,,\
O=Example Org,,L=London,,ST=London,,C=GB' \
--tls-creds tls0 \
--tls-authz authz0 \
....other qemu-nbd args...
NB: a real shell command line would not have leading whitespace after
the line continuation, it is just included here for clarity.
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <20190227162035.18543-2-berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[eblake: split long line in --help text, tweak 233 to show that whitespace
after ,, in identity= portion is actually okay]
Signed-off-by: Eric Blake <eblake@redhat.com>
2019-02-27 19:20:33 +03:00
|
|
|
nbd_client_new(cioc, tlscreds, tlsauthz, nbd_client_closed);
|
2011-09-12 19:28:11 +04:00
|
|
|
}
|
|
|
|
|
2016-02-10 21:41:02 +03:00
|
|
|
static void nbd_update_server_watch(void)
|
2015-05-19 13:50:59 +03:00
|
|
|
{
|
|
|
|
if (nbd_can_accept()) {
|
2017-12-18 13:16:43 +03:00
|
|
|
qio_net_listener_set_client_func(server, nbd_accept, NULL, NULL);
|
2015-05-19 13:50:59 +03:00
|
|
|
} else {
|
2017-12-18 13:16:43 +03:00
|
|
|
qio_net_listener_set_client_func(server, NULL, NULL, NULL);
|
2015-05-19 13:50:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-16 16:52:23 +03:00
|
|
|
|
2017-04-26 10:36:41 +03:00
|
|
|
static SocketAddress *nbd_build_socket_address(const char *sockpath,
|
2015-09-16 16:52:23 +03:00
|
|
|
const char *bindto,
|
|
|
|
const char *port)
|
|
|
|
{
|
2017-04-26 10:36:41 +03:00
|
|
|
SocketAddress *saddr;
|
2015-09-16 16:52:23 +03:00
|
|
|
|
2017-04-26 10:36:41 +03:00
|
|
|
saddr = g_new0(SocketAddress, 1);
|
2015-09-16 16:52:23 +03:00
|
|
|
if (sockpath) {
|
2017-04-26 10:36:41 +03:00
|
|
|
saddr->type = SOCKET_ADDRESS_TYPE_UNIX;
|
|
|
|
saddr->u.q_unix.path = g_strdup(sockpath);
|
2015-09-16 16:52:23 +03:00
|
|
|
} else {
|
2016-03-03 19:16:48 +03:00
|
|
|
InetSocketAddress *inet;
|
2017-04-26 10:36:41 +03:00
|
|
|
saddr->type = SOCKET_ADDRESS_TYPE_INET;
|
|
|
|
inet = &saddr->u.inet;
|
2016-03-03 19:16:48 +03:00
|
|
|
inet->host = g_strdup(bindto);
|
2015-09-16 16:52:23 +03:00
|
|
|
if (port) {
|
2016-03-03 19:16:48 +03:00
|
|
|
inet->port = g_strdup(port);
|
2015-09-16 16:52:23 +03:00
|
|
|
} else {
|
2016-03-03 19:16:48 +03:00
|
|
|
inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
|
2015-09-16 16:52:23 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return saddr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-17 13:10:19 +03:00
|
|
|
static QemuOptsList file_opts = {
|
|
|
|
.name = "file",
|
|
|
|
.implied_opt_name = "file",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(file_opts.head),
|
|
|
|
.desc = {
|
|
|
|
/* no elements => accept any params */
|
|
|
|
{ /* end of list */ }
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, bool list,
|
|
|
|
Error **errp)
|
2016-02-10 21:41:13 +03:00
|
|
|
{
|
|
|
|
Object *obj;
|
|
|
|
QCryptoTLSCreds *creds;
|
|
|
|
|
|
|
|
obj = object_resolve_path_component(
|
|
|
|
object_get_objects_root(), id);
|
|
|
|
if (!obj) {
|
|
|
|
error_setg(errp, "No TLS credentials with id '%s'",
|
|
|
|
id);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
creds = (QCryptoTLSCreds *)
|
|
|
|
object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS);
|
|
|
|
if (!creds) {
|
|
|
|
error_setg(errp, "Object with id '%s' is not TLS credentials",
|
|
|
|
id);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-06-28 19:09:10 +03:00
|
|
|
if (!qcrypto_tls_creds_check_endpoint(creds,
|
|
|
|
list
|
|
|
|
? QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT
|
|
|
|
: QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
|
|
|
|
errp)) {
|
|
|
|
return NULL;
|
2016-02-10 21:41:13 +03:00
|
|
|
}
|
|
|
|
object_ref(obj);
|
|
|
|
return creds;
|
|
|
|
}
|
|
|
|
|
2017-02-04 13:03:17 +03:00
|
|
|
static void setup_address_and_port(const char **address, const char **port)
|
|
|
|
{
|
|
|
|
if (*address == NULL) {
|
|
|
|
*address = "0.0.0.0";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*port == NULL) {
|
|
|
|
*port = stringify(NBD_DEFAULT_PORT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check socket parameters compatibility when socket activation is used.
|
|
|
|
*/
|
|
|
|
static const char *socket_activation_validate_opts(const char *device,
|
|
|
|
const char *sockpath,
|
|
|
|
const char *address,
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
const char *port,
|
2021-11-15 23:29:43 +03:00
|
|
|
const char *selinux,
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
bool list)
|
2017-02-04 13:03:17 +03:00
|
|
|
{
|
|
|
|
if (device != NULL) {
|
|
|
|
return "NBD device can't be set when using socket activation";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sockpath != NULL) {
|
|
|
|
return "Unix socket can't be set when using socket activation";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (address != NULL) {
|
|
|
|
return "The interface can't be set when using socket activation";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (port != NULL) {
|
|
|
|
return "TCP port number can't be set when using socket activation";
|
|
|
|
}
|
|
|
|
|
2021-11-15 23:29:43 +03:00
|
|
|
if (selinux != NULL) {
|
|
|
|
return "SELinux label can't be set when using socket activation";
|
|
|
|
}
|
|
|
|
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
if (list) {
|
|
|
|
return "List mode is incompatible with socket activation";
|
|
|
|
}
|
|
|
|
|
2017-02-04 13:03:17 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
2016-02-10 21:41:13 +03:00
|
|
|
|
2018-05-16 14:46:37 +03:00
|
|
|
static void qemu_nbd_shutdown(void)
|
|
|
|
{
|
|
|
|
job_cancel_sync_all();
|
2021-02-01 15:50:32 +03:00
|
|
|
blk_exp_close_all();
|
2018-05-16 14:46:37 +03:00
|
|
|
bdrv_close_all();
|
|
|
|
}
|
|
|
|
|
2008-05-28 01:13:40 +04:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
BlockBackend *blk;
|
2008-05-28 01:13:40 +04:00
|
|
|
BlockDriverState *bs;
|
2019-01-17 22:36:43 +03:00
|
|
|
uint64_t dev_offset = 0;
|
nbd: Improve per-export flag handling in server
When creating a read-only image, we are still advertising support for
TRIM and WRITE_ZEROES to the client, even though the client should not
be issuing those commands. But seeing this requires looking across
multiple functions:
All callers to nbd_export_new() passed a single flag based solely on
whether the export allows writes. Later, we then pass a constant set
of flags to nbd_negotiate_options() (namely, the set of flags which we
always support, at least for writable images), which is then further
dynamically modified with NBD_FLAG_SEND_DF based on client requests
for structured options. Finally, when processing NBD_OPT_EXPORT_NAME
or NBD_OPT_EXPORT_GO we bitwise-or the original caller's flag with the
runtime set of flags we've built up over several functions.
Let's refactor things to instead compute a baseline of flags as soon
as possible which gets shared between multiple clients, in
nbd_export_new(), and changing the signature for the callers to pass
in a simpler bool rather than having to figure out flags. We can then
get rid of the 'myflags' parameter to various functions, and instead
refer to client for everything we need (we still have to perform a
bitwise-OR for NBD_FLAG_SEND_DF during NBD_OPT_EXPORT_NAME and
NBD_OPT_EXPORT_GO, but it's easier to see what is being computed).
This lets us quit advertising senseless flags for read-only images, as
well as making the next patch for exposing FAST_ZERO support easier to
write.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20190823143726.27062-2-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
[eblake: improve commit message, update iotest 223]
2019-08-23 17:37:22 +03:00
|
|
|
bool readonly = false;
|
2008-07-03 14:23:51 +04:00
|
|
|
bool disconnect = false;
|
2017-02-04 13:03:17 +03:00
|
|
|
const char *bindto = NULL;
|
2015-09-16 16:52:23 +03:00
|
|
|
const char *port = NULL;
|
|
|
|
char *sockpath = NULL;
|
2011-12-06 12:07:00 +04:00
|
|
|
char *device = NULL;
|
2013-12-04 13:10:55 +04:00
|
|
|
QemuOpts *sn_opts = NULL;
|
|
|
|
const char *sn_id_or_name = NULL;
|
2020-10-27 08:05:55 +03:00
|
|
|
const char *sopt = "hVb:o:p:rsnc:dvk:e:f:tl:x:T:D:AB:L";
|
2008-05-28 01:13:40 +04:00
|
|
|
struct option lopt[] = {
|
2016-02-17 13:10:22 +03:00
|
|
|
{ "help", no_argument, NULL, 'h' },
|
|
|
|
{ "version", no_argument, NULL, 'V' },
|
|
|
|
{ "bind", required_argument, NULL, 'b' },
|
|
|
|
{ "port", required_argument, NULL, 'p' },
|
|
|
|
{ "socket", required_argument, NULL, 'k' },
|
|
|
|
{ "offset", required_argument, NULL, 'o' },
|
|
|
|
{ "read-only", no_argument, NULL, 'r' },
|
2020-10-27 08:05:55 +03:00
|
|
|
{ "allocation-depth", no_argument, NULL, 'A' },
|
2019-01-11 22:47:20 +03:00
|
|
|
{ "bitmap", required_argument, NULL, 'B' },
|
2016-02-17 13:10:22 +03:00
|
|
|
{ "connect", required_argument, NULL, 'c' },
|
|
|
|
{ "disconnect", no_argument, NULL, 'd' },
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
{ "list", no_argument, NULL, 'L' },
|
2016-02-17 13:10:22 +03:00
|
|
|
{ "snapshot", no_argument, NULL, 's' },
|
|
|
|
{ "load-snapshot", required_argument, NULL, 'l' },
|
|
|
|
{ "nocache", no_argument, NULL, 'n' },
|
|
|
|
{ "cache", required_argument, NULL, QEMU_NBD_OPT_CACHE },
|
|
|
|
{ "aio", required_argument, NULL, QEMU_NBD_OPT_AIO },
|
|
|
|
{ "discard", required_argument, NULL, QEMU_NBD_OPT_DISCARD },
|
|
|
|
{ "detect-zeroes", required_argument, NULL,
|
|
|
|
QEMU_NBD_OPT_DETECT_ZEROES },
|
|
|
|
{ "shared", required_argument, NULL, 'e' },
|
|
|
|
{ "format", required_argument, NULL, 'f' },
|
|
|
|
{ "persistent", no_argument, NULL, 't' },
|
|
|
|
{ "verbose", no_argument, NULL, 'v' },
|
|
|
|
{ "object", required_argument, NULL, QEMU_NBD_OPT_OBJECT },
|
|
|
|
{ "export-name", required_argument, NULL, 'x' },
|
2016-10-14 21:33:03 +03:00
|
|
|
{ "description", required_argument, NULL, 'D' },
|
2016-02-17 13:10:22 +03:00
|
|
|
{ "tls-creds", required_argument, NULL, QEMU_NBD_OPT_TLSCREDS },
|
2022-03-04 22:36:02 +03:00
|
|
|
{ "tls-hostname", required_argument, NULL, QEMU_NBD_OPT_TLSHOSTNAME },
|
qemu-nbd: add support for authorization of TLS clients
Currently any client which can complete the TLS handshake is able to use
the NBD server. The server admin can turn on the 'verify-peer' option
for the x509 creds to require the client to provide a x509 certificate.
This means the client will have to acquire a certificate from the CA
before they are permitted to use the NBD server. This is still a fairly
low bar to cross.
This adds a '--tls-authz OBJECT-ID' option to the qemu-nbd command which
takes the ID of a previously added 'QAuthZ' object instance. This will
be used to validate the client's x509 distinguished name. Clients
failing the authorization check will not be permitted to use the NBD
server.
For example to setup authorization that only allows connection from a client
whose x509 certificate distinguished name is
CN=laptop.example.com,O=Example Org,L=London,ST=London,C=GB
escape the commas in the name and use:
qemu-nbd --object tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\
endpoint=server,verify-peer=yes \
--object 'authz-simple,id=auth0,identity=CN=laptop.example.com,,\
O=Example Org,,L=London,,ST=London,,C=GB' \
--tls-creds tls0 \
--tls-authz authz0 \
....other qemu-nbd args...
NB: a real shell command line would not have leading whitespace after
the line continuation, it is just included here for clarity.
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <20190227162035.18543-2-berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[eblake: split long line in --help text, tweak 233 to show that whitespace
after ,, in identity= portion is actually okay]
Signed-off-by: Eric Blake <eblake@redhat.com>
2019-02-27 19:20:33 +03:00
|
|
|
{ "tls-authz", required_argument, NULL, QEMU_NBD_OPT_TLSAUTHZ },
|
2016-02-17 13:10:22 +03:00
|
|
|
{ "image-opts", no_argument, NULL, QEMU_NBD_OPT_IMAGE_OPTS },
|
2016-06-17 17:44:12 +03:00
|
|
|
{ "trace", required_argument, NULL, 'T' },
|
2016-09-28 23:46:42 +03:00
|
|
|
{ "fork", no_argument, NULL, QEMU_NBD_OPT_FORK },
|
2019-05-09 00:18:16 +03:00
|
|
|
{ "pid-file", required_argument, NULL, QEMU_NBD_OPT_PID_FILE },
|
2021-11-15 23:29:43 +03:00
|
|
|
{ "selinux-label", required_argument, NULL,
|
|
|
|
QEMU_NBD_OPT_SELINUX_LABEL },
|
2009-08-01 01:16:51 +04:00
|
|
|
{ NULL, 0, NULL, 0 }
|
2008-05-28 01:13:40 +04:00
|
|
|
};
|
|
|
|
int ch;
|
|
|
|
int opt_ind = 0;
|
2010-01-17 17:48:13 +03:00
|
|
|
int flags = BDRV_O_RDWR;
|
2015-02-05 21:58:19 +03:00
|
|
|
int ret = 0;
|
2012-07-18 16:57:15 +04:00
|
|
|
bool seen_cache = false;
|
2013-02-08 17:06:13 +04:00
|
|
|
bool seen_discard = false;
|
2012-07-18 16:57:15 +04:00
|
|
|
bool seen_aio = false;
|
2011-11-04 18:51:21 +04:00
|
|
|
pthread_t client_thread;
|
2013-03-19 15:20:20 +04:00
|
|
|
const char *fmt = NULL;
|
2013-09-05 16:45:29 +04:00
|
|
|
Error *local_err = NULL;
|
2014-08-13 21:20:18 +04:00
|
|
|
BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF;
|
2015-02-05 21:58:19 +03:00
|
|
|
QDict *options = NULL;
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
const char *export_name = NULL; /* defaults to "" later for server mode */
|
2016-10-14 21:33:03 +03:00
|
|
|
const char *export_description = NULL;
|
qapi: nbd-export: allow select bitmaps by node/name pair
Hi all! Current logic of relying on search through backing chain is not
safe neither convenient.
Sometimes it leads to necessity of extra bitmap copying. Also, we are
going to add "snapshot-access" driver, to access some snapshot state
through NBD. And this driver is not formally a filter, and of course
it's not a COW format driver. So, searching through backing chain will
not work. Instead of widening the workaround of bitmap searching, let's
extend the interface so that user can select bitmap precisely.
Note, that checking for bitmap active status is not copied to the new
API, I don't see a reason for it, user should understand the risks. And
anyway, bitmap from other node is unrelated to this export being
read-only or read-write.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@openvz.org>
Message-Id: <20220314213226.362217-3-v.sementsov-og@mail.ru>
[eblake: Adjust S-o-b to Vladimir's new email, with permission]
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
2022-03-15 00:32:25 +03:00
|
|
|
BlockDirtyBitmapOrStrList *bitmaps = NULL;
|
2020-10-27 08:05:55 +03:00
|
|
|
bool alloc_depth = false;
|
2016-02-10 21:41:13 +03:00
|
|
|
const char *tlscredsid = NULL;
|
2022-03-04 22:36:02 +03:00
|
|
|
const char *tlshostname = NULL;
|
2016-02-17 13:10:19 +03:00
|
|
|
bool imageOpts = false;
|
2021-08-13 23:55:19 +03:00
|
|
|
bool writethrough = false; /* Client will flush as needed. */
|
2023-07-17 23:25:20 +03:00
|
|
|
bool verbose = false;
|
2016-09-28 23:46:42 +03:00
|
|
|
bool fork_process = false;
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
bool list = false;
|
2017-02-04 13:03:17 +03:00
|
|
|
unsigned socket_activation;
|
2019-05-09 00:18:16 +03:00
|
|
|
const char *pid_file_name = NULL;
|
2021-11-15 23:29:43 +03:00
|
|
|
const char *selinux_label = NULL;
|
2020-09-24 18:26:57 +03:00
|
|
|
BlockExportOptions *export_opts;
|
2008-05-28 01:13:40 +04:00
|
|
|
|
2020-09-30 15:11:01 +03:00
|
|
|
#ifdef CONFIG_POSIX
|
2020-09-29 15:55:15 +03:00
|
|
|
os_setup_early_signal_handling();
|
|
|
|
os_setup_signal_handling();
|
2017-06-11 15:37:14 +03:00
|
|
|
#endif
|
|
|
|
|
2020-08-25 13:38:48 +03:00
|
|
|
socket_init();
|
log: Make glib logging go through QEMU
This commit adds a error_init() helper which calls
g_log_set_default_handler() so that glib logs (g_log, g_warning, ...)
are handled similarly to other QEMU logs. This means they will get a
timestamp if timestamps are enabled, and they will go through the
HMP monitor if one is configured.
This commit also adds a call to error_init() to the binaries
installed by QEMU. Since error_init() also calls error_set_progname(),
this means that *-linux-user, *-bsd-user and qemu-pr-helper messages
output with error_report, info_report, ... will slightly change: they
will be prefixed by the binary name.
glib debug messages are enabled through G_MESSAGES_DEBUG similarly to
the glib default log handler.
At the moment, this change will mostly impact SPICE logging if your
spice version is >= 0.14.1. With older spice versions, this is not going
to work as expected, but will not have any ill effect, so this call is
not conditional on the SPICE version.
Signed-off-by: Christophe Fergeau <cfergeau@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20190131164614.19209-3-cfergeau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2019-01-31 19:46:14 +03:00
|
|
|
error_init(argv[0]);
|
2016-10-04 16:35:52 +03:00
|
|
|
module_call_init(MODULE_INIT_TRACE);
|
2016-05-12 17:10:04 +03:00
|
|
|
qcrypto_init(&error_fatal);
|
2016-04-06 14:12:06 +03:00
|
|
|
|
2016-02-10 21:41:00 +03:00
|
|
|
module_call_init(MODULE_INIT_QOM);
|
2016-06-17 17:44:12 +03:00
|
|
|
qemu_add_opts(&qemu_trace_opts);
|
2014-02-10 10:48:51 +04:00
|
|
|
qemu_init_exec_dir(argv[0]);
|
2011-11-04 18:51:19 +04:00
|
|
|
|
2008-05-28 01:13:40 +04:00
|
|
|
while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
|
|
|
|
switch (ch) {
|
|
|
|
case 's':
|
2008-07-03 15:47:46 +04:00
|
|
|
flags |= BDRV_O_SNAPSHOT;
|
|
|
|
break;
|
|
|
|
case 'n':
|
2012-07-18 16:57:15 +04:00
|
|
|
optarg = (char *) "none";
|
|
|
|
/* fallthrough */
|
|
|
|
case QEMU_NBD_OPT_CACHE:
|
|
|
|
if (seen_cache) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("-n and --cache can only be specified once");
|
|
|
|
exit(EXIT_FAILURE);
|
2012-07-18 16:57:15 +04:00
|
|
|
}
|
|
|
|
seen_cache = true;
|
2016-03-14 13:43:28 +03:00
|
|
|
if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) == -1) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Invalid cache mode `%s'", optarg);
|
|
|
|
exit(EXIT_FAILURE);
|
2012-07-18 16:57:15 +04:00
|
|
|
}
|
2008-05-28 01:13:40 +04:00
|
|
|
break;
|
2012-07-18 16:57:15 +04:00
|
|
|
case QEMU_NBD_OPT_AIO:
|
|
|
|
if (seen_aio) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("--aio can only be specified once");
|
|
|
|
exit(EXIT_FAILURE);
|
2012-07-18 16:57:15 +04:00
|
|
|
}
|
|
|
|
seen_aio = true;
|
2020-01-20 17:18:56 +03:00
|
|
|
if (bdrv_parse_aio(optarg, &flags) < 0) {
|
|
|
|
error_report("Invalid aio mode '%s'", optarg);
|
|
|
|
exit(EXIT_FAILURE);
|
2012-07-18 16:57:15 +04:00
|
|
|
}
|
|
|
|
break;
|
2013-02-08 17:06:13 +04:00
|
|
|
case QEMU_NBD_OPT_DISCARD:
|
|
|
|
if (seen_discard) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("--discard can only be specified once");
|
|
|
|
exit(EXIT_FAILURE);
|
2013-02-08 17:06:13 +04:00
|
|
|
}
|
|
|
|
seen_discard = true;
|
|
|
|
if (bdrv_parse_discard_flags(optarg, &flags) == -1) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Invalid discard mode `%s'", optarg);
|
|
|
|
exit(EXIT_FAILURE);
|
2013-02-08 17:06:13 +04:00
|
|
|
}
|
|
|
|
break;
|
2014-08-13 21:20:18 +04:00
|
|
|
case QEMU_NBD_OPT_DETECT_ZEROES:
|
|
|
|
detect_zeroes =
|
2017-08-24 11:46:10 +03:00
|
|
|
qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup,
|
2014-08-13 21:20:18 +04:00
|
|
|
optarg,
|
|
|
|
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
|
|
|
|
&local_err);
|
|
|
|
if (local_err) {
|
2015-12-18 18:35:14 +03:00
|
|
|
error_reportf_err(local_err,
|
|
|
|
"Failed to parse detect_zeroes mode: ");
|
2015-12-18 18:35:04 +03:00
|
|
|
exit(EXIT_FAILURE);
|
2014-08-13 21:20:18 +04:00
|
|
|
}
|
|
|
|
if (detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
|
|
|
|
!(flags & BDRV_O_UNMAP)) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("setting detect-zeroes to unmap is not allowed "
|
|
|
|
"without setting discard operation to unmap");
|
|
|
|
exit(EXIT_FAILURE);
|
2014-08-13 21:20:18 +04:00
|
|
|
}
|
|
|
|
break;
|
2008-05-28 01:13:40 +04:00
|
|
|
case 'b':
|
|
|
|
bindto = optarg;
|
|
|
|
break;
|
|
|
|
case 'p':
|
2015-09-16 16:52:23 +03:00
|
|
|
port = optarg;
|
2008-05-28 01:13:40 +04:00
|
|
|
break;
|
|
|
|
case 'o':
|
2019-01-17 22:36:44 +03:00
|
|
|
if (qemu_strtou64(optarg, NULL, 0, &dev_offset) < 0) {
|
|
|
|
error_report("Invalid offset '%s'", optarg);
|
2015-12-18 18:35:04 +03:00
|
|
|
exit(EXIT_FAILURE);
|
2008-05-28 01:13:40 +04:00
|
|
|
}
|
|
|
|
break;
|
2013-12-04 13:10:55 +04:00
|
|
|
case 'l':
|
|
|
|
if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
|
QemuOpts: Wean off qerror_report_err()
qerror_report_err() is a transitional interface to help with
converting existing monitor commands to QMP. It should not be used
elsewhere.
The only remaining user in qemu-option.c is qemu_opts_parse(). Is it
used in QMP context? If not, we can simply replace
qerror_report_err() by error_report_err().
The uses in qemu-img.c, qemu-io.c, qemu-nbd.c and under tests/ are
clearly not in QMP context.
The uses in vl.c aren't either, because the only QMP command handlers
there are qmp_query_status() and qmp_query_machines(), and they don't
call it.
Remaining uses:
* drive_def(): Command line -drive and such, HMP drive_add and pci_add
* hmp_chardev_add(): HMP chardev-add
* monitor_parse_command(): HMP core
* tmp_config_parse(): Command line -tpmdev
* net_host_device_add(): HMP host_net_add
* net_client_parse(): Command line -net and -netdev
* qemu_global_option(): Command line -global
* vnc_parse_func(): Command line -display, -vnc, default display, HMP
change, QMP change. Bummer.
* qemu_pci_hot_add_nic(): HMP pci_add
* usb_net_init(): Command line -usbdevice, HMP usb_add
Propagate errors through qemu_opts_parse(). Create a convenience
function qemu_opts_parse_noisily() that passes errors to
error_report_err(). Switch all non-QMP users outside tests to it.
That leaves vnc_parse_func(). Propagate errors through it. Since I'm
touching it anyway, rename it to vnc_parse().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-02-13 14:50:26 +03:00
|
|
|
sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts,
|
|
|
|
optarg, false);
|
2013-12-04 13:10:55 +04:00
|
|
|
if (!sn_opts) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Failed in parsing snapshot param `%s'",
|
|
|
|
optarg);
|
|
|
|
exit(EXIT_FAILURE);
|
2013-12-04 13:10:55 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
sn_id_or_name = optarg;
|
|
|
|
}
|
|
|
|
/* fall through */
|
2008-05-28 01:13:40 +04:00
|
|
|
case 'r':
|
nbd: Improve per-export flag handling in server
When creating a read-only image, we are still advertising support for
TRIM and WRITE_ZEROES to the client, even though the client should not
be issuing those commands. But seeing this requires looking across
multiple functions:
All callers to nbd_export_new() passed a single flag based solely on
whether the export allows writes. Later, we then pass a constant set
of flags to nbd_negotiate_options() (namely, the set of flags which we
always support, at least for writable images), which is then further
dynamically modified with NBD_FLAG_SEND_DF based on client requests
for structured options. Finally, when processing NBD_OPT_EXPORT_NAME
or NBD_OPT_EXPORT_GO we bitwise-or the original caller's flag with the
runtime set of flags we've built up over several functions.
Let's refactor things to instead compute a baseline of flags as soon
as possible which gets shared between multiple clients, in
nbd_export_new(), and changing the signature for the callers to pass
in a simpler bool rather than having to figure out flags. We can then
get rid of the 'myflags' parameter to various functions, and instead
refer to client for everything we need (we still have to perform a
bitwise-OR for NBD_FLAG_SEND_DF during NBD_OPT_EXPORT_NAME and
NBD_OPT_EXPORT_GO, but it's easier to see what is being computed).
This lets us quit advertising senseless flags for read-only images, as
well as making the next patch for exposing FAST_ZERO support easier to
write.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20190823143726.27062-2-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
[eblake: improve commit message, update iotest 223]
2019-08-23 17:37:22 +03:00
|
|
|
readonly = true;
|
2010-03-14 16:19:57 +03:00
|
|
|
flags &= ~BDRV_O_RDWR;
|
2008-05-28 01:13:40 +04:00
|
|
|
break;
|
2020-10-27 08:05:55 +03:00
|
|
|
case 'A':
|
|
|
|
alloc_depth = true;
|
|
|
|
break;
|
2019-01-11 22:47:20 +03:00
|
|
|
case 'B':
|
qapi: nbd-export: allow select bitmaps by node/name pair
Hi all! Current logic of relying on search through backing chain is not
safe neither convenient.
Sometimes it leads to necessity of extra bitmap copying. Also, we are
going to add "snapshot-access" driver, to access some snapshot state
through NBD. And this driver is not formally a filter, and of course
it's not a COW format driver. So, searching through backing chain will
not work. Instead of widening the workaround of bitmap searching, let's
extend the interface so that user can select bitmap precisely.
Note, that checking for bitmap active status is not copied to the new
API, I don't see a reason for it, user should understand the risks. And
anyway, bitmap from other node is unrelated to this export being
read-only or read-write.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@openvz.org>
Message-Id: <20220314213226.362217-3-v.sementsov-og@mail.ru>
[eblake: Adjust S-o-b to Vladimir's new email, with permission]
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
2022-03-15 00:32:25 +03:00
|
|
|
{
|
|
|
|
BlockDirtyBitmapOrStr *el = g_new(BlockDirtyBitmapOrStr, 1);
|
|
|
|
*el = (BlockDirtyBitmapOrStr) {
|
|
|
|
.type = QTYPE_QSTRING,
|
|
|
|
.u.local = g_strdup(optarg),
|
|
|
|
};
|
|
|
|
QAPI_LIST_PREPEND(bitmaps, el);
|
|
|
|
}
|
2019-01-11 22:47:20 +03:00
|
|
|
break;
|
2008-07-03 14:23:51 +04:00
|
|
|
case 'k':
|
2011-11-04 18:51:20 +04:00
|
|
|
sockpath = optarg;
|
2014-08-13 21:20:19 +04:00
|
|
|
if (sockpath[0] != '/') {
|
2015-12-18 18:35:19 +03:00
|
|
|
error_report("socket path must be absolute");
|
2015-12-18 18:35:04 +03:00
|
|
|
exit(EXIT_FAILURE);
|
2014-08-13 21:20:19 +04:00
|
|
|
}
|
2008-07-03 14:23:51 +04:00
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
disconnect = true;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
device = optarg;
|
|
|
|
break;
|
2008-07-03 16:45:02 +04:00
|
|
|
case 'e':
|
2019-01-17 22:36:44 +03:00
|
|
|
if (qemu_strtoi(optarg, NULL, 0, &shared) < 0 ||
|
2021-02-09 18:27:59 +03:00
|
|
|
shared < 0) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Invalid shared device number '%s'", optarg);
|
|
|
|
exit(EXIT_FAILURE);
|
2008-07-03 16:45:02 +04:00
|
|
|
}
|
|
|
|
break;
|
2013-03-19 15:20:20 +04:00
|
|
|
case 'f':
|
|
|
|
fmt = optarg;
|
|
|
|
break;
|
2014-08-13 21:20:19 +04:00
|
|
|
case 't':
|
|
|
|
persistent = 1;
|
|
|
|
break;
|
2016-02-10 21:41:08 +03:00
|
|
|
case 'x':
|
|
|
|
export_name = optarg;
|
2019-11-14 05:46:34 +03:00
|
|
|
if (strlen(export_name) > NBD_MAX_STRING_SIZE) {
|
|
|
|
error_report("export name '%s' too long", export_name);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2016-02-10 21:41:08 +03:00
|
|
|
break;
|
2016-10-14 21:33:03 +03:00
|
|
|
case 'D':
|
|
|
|
export_description = optarg;
|
2019-11-14 05:46:34 +03:00
|
|
|
if (strlen(export_description) > NBD_MAX_STRING_SIZE) {
|
|
|
|
error_report("export description '%s' too long",
|
|
|
|
export_description);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2016-10-14 21:33:03 +03:00
|
|
|
break;
|
2008-05-28 01:13:40 +04:00
|
|
|
case 'v':
|
2023-07-17 23:25:20 +03:00
|
|
|
verbose = true;
|
2008-05-28 01:13:40 +04:00
|
|
|
break;
|
|
|
|
case 'V':
|
|
|
|
version(argv[0]);
|
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
usage(argv[0]);
|
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
case '?':
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Try `%s --help' for more information.", argv[0]);
|
|
|
|
exit(EXIT_FAILURE);
|
2021-02-17 14:56:45 +03:00
|
|
|
case QEMU_NBD_OPT_OBJECT:
|
|
|
|
user_creatable_process_cmdline(optarg);
|
|
|
|
break;
|
2016-02-10 21:41:13 +03:00
|
|
|
case QEMU_NBD_OPT_TLSCREDS:
|
|
|
|
tlscredsid = optarg;
|
|
|
|
break;
|
2022-03-04 22:36:02 +03:00
|
|
|
case QEMU_NBD_OPT_TLSHOSTNAME:
|
|
|
|
tlshostname = optarg;
|
|
|
|
break;
|
2016-02-17 13:10:19 +03:00
|
|
|
case QEMU_NBD_OPT_IMAGE_OPTS:
|
|
|
|
imageOpts = true;
|
|
|
|
break;
|
2016-06-17 17:44:12 +03:00
|
|
|
case 'T':
|
2020-11-02 14:58:41 +03:00
|
|
|
trace_opt_parse(optarg);
|
2016-06-17 17:44:12 +03:00
|
|
|
break;
|
qemu-nbd: add support for authorization of TLS clients
Currently any client which can complete the TLS handshake is able to use
the NBD server. The server admin can turn on the 'verify-peer' option
for the x509 creds to require the client to provide a x509 certificate.
This means the client will have to acquire a certificate from the CA
before they are permitted to use the NBD server. This is still a fairly
low bar to cross.
This adds a '--tls-authz OBJECT-ID' option to the qemu-nbd command which
takes the ID of a previously added 'QAuthZ' object instance. This will
be used to validate the client's x509 distinguished name. Clients
failing the authorization check will not be permitted to use the NBD
server.
For example to setup authorization that only allows connection from a client
whose x509 certificate distinguished name is
CN=laptop.example.com,O=Example Org,L=London,ST=London,C=GB
escape the commas in the name and use:
qemu-nbd --object tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\
endpoint=server,verify-peer=yes \
--object 'authz-simple,id=auth0,identity=CN=laptop.example.com,,\
O=Example Org,,L=London,,ST=London,,C=GB' \
--tls-creds tls0 \
--tls-authz authz0 \
....other qemu-nbd args...
NB: a real shell command line would not have leading whitespace after
the line continuation, it is just included here for clarity.
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <20190227162035.18543-2-berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[eblake: split long line in --help text, tweak 233 to show that whitespace
after ,, in identity= portion is actually okay]
Signed-off-by: Eric Blake <eblake@redhat.com>
2019-02-27 19:20:33 +03:00
|
|
|
case QEMU_NBD_OPT_TLSAUTHZ:
|
|
|
|
tlsauthz = optarg;
|
|
|
|
break;
|
2016-09-28 23:46:42 +03:00
|
|
|
case QEMU_NBD_OPT_FORK:
|
|
|
|
fork_process = true;
|
|
|
|
break;
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
case 'L':
|
|
|
|
list = true;
|
|
|
|
break;
|
2019-05-09 00:18:16 +03:00
|
|
|
case QEMU_NBD_OPT_PID_FILE:
|
|
|
|
pid_file_name = optarg;
|
|
|
|
break;
|
2021-11-15 23:29:43 +03:00
|
|
|
case QEMU_NBD_OPT_SELINUX_LABEL:
|
|
|
|
selinux_label = optarg;
|
|
|
|
break;
|
2008-05-28 01:13:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
if (list) {
|
|
|
|
if (argc != optind) {
|
|
|
|
error_report("List mode is incompatible with a file name");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2020-01-23 19:46:50 +03:00
|
|
|
if (export_name || export_description || dev_offset ||
|
2020-10-27 08:05:49 +03:00
|
|
|
device || disconnect || fmt || sn_id_or_name || bitmaps ||
|
2020-10-27 08:05:55 +03:00
|
|
|
alloc_depth || seen_aio || seen_discard || seen_cache) {
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
error_report("List mode is incompatible with per-device settings");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
if (fork_process) {
|
|
|
|
error_report("List mode is incompatible with forking");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
} else if ((argc - optind) != 1) {
|
2015-12-18 18:35:24 +03:00
|
|
|
error_report("Invalid number of arguments");
|
|
|
|
error_printf("Try `%s --help' for more information.\n", argv[0]);
|
2015-12-18 18:35:04 +03:00
|
|
|
exit(EXIT_FAILURE);
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
} else if (!export_name) {
|
|
|
|
export_name = "";
|
2008-05-28 01:13:40 +04:00
|
|
|
}
|
|
|
|
|
2016-06-17 17:44:12 +03:00
|
|
|
if (!trace_init_backends()) {
|
|
|
|
exit(1);
|
|
|
|
}
|
2020-11-02 14:58:41 +03:00
|
|
|
trace_init_file();
|
2022-04-17 21:29:44 +03:00
|
|
|
qemu_set_log(LOG_TRACE, &error_fatal);
|
2016-06-17 17:44:12 +03:00
|
|
|
|
2017-02-04 13:03:17 +03:00
|
|
|
socket_activation = check_socket_activation();
|
|
|
|
if (socket_activation == 0) {
|
2022-03-04 22:36:03 +03:00
|
|
|
if (!sockpath) {
|
|
|
|
setup_address_and_port(&bindto, &port);
|
|
|
|
}
|
2017-02-04 13:03:17 +03:00
|
|
|
} else {
|
|
|
|
/* Using socket activation - check user didn't use -p etc. */
|
|
|
|
const char *err_msg = socket_activation_validate_opts(device, sockpath,
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
bindto, port,
|
2021-11-15 23:29:43 +03:00
|
|
|
selinux_label,
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
list);
|
2017-02-04 13:03:17 +03:00
|
|
|
if (err_msg != NULL) {
|
|
|
|
error_report("%s", err_msg);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2017-03-16 18:29:45 +03:00
|
|
|
|
|
|
|
/* qemu-nbd can only listen on a single socket. */
|
|
|
|
if (socket_activation > 1) {
|
|
|
|
error_report("qemu-nbd does not support socket activation with %s > 1",
|
|
|
|
"LISTEN_FDS");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2017-02-04 13:03:17 +03:00
|
|
|
}
|
|
|
|
|
2016-02-10 21:41:13 +03:00
|
|
|
if (tlscredsid) {
|
|
|
|
if (device) {
|
|
|
|
error_report("TLS is not supported with a host device");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
qemu-nbd: add support for authorization of TLS clients
Currently any client which can complete the TLS handshake is able to use
the NBD server. The server admin can turn on the 'verify-peer' option
for the x509 creds to require the client to provide a x509 certificate.
This means the client will have to acquire a certificate from the CA
before they are permitted to use the NBD server. This is still a fairly
low bar to cross.
This adds a '--tls-authz OBJECT-ID' option to the qemu-nbd command which
takes the ID of a previously added 'QAuthZ' object instance. This will
be used to validate the client's x509 distinguished name. Clients
failing the authorization check will not be permitted to use the NBD
server.
For example to setup authorization that only allows connection from a client
whose x509 certificate distinguished name is
CN=laptop.example.com,O=Example Org,L=London,ST=London,C=GB
escape the commas in the name and use:
qemu-nbd --object tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\
endpoint=server,verify-peer=yes \
--object 'authz-simple,id=auth0,identity=CN=laptop.example.com,,\
O=Example Org,,L=London,,ST=London,,C=GB' \
--tls-creds tls0 \
--tls-authz authz0 \
....other qemu-nbd args...
NB: a real shell command line would not have leading whitespace after
the line continuation, it is just included here for clarity.
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <20190227162035.18543-2-berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[eblake: split long line in --help text, tweak 233 to show that whitespace
after ,, in identity= portion is actually okay]
Signed-off-by: Eric Blake <eblake@redhat.com>
2019-02-27 19:20:33 +03:00
|
|
|
if (tlsauthz && list) {
|
|
|
|
error_report("TLS authorization is incompatible with export list");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2022-03-04 22:36:02 +03:00
|
|
|
if (tlshostname && !list) {
|
|
|
|
error_report("TLS hostname is only supported with export list");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
tlscreds = nbd_get_tls_creds(tlscredsid, list, &local_err);
|
2016-02-10 21:41:13 +03:00
|
|
|
if (local_err) {
|
2020-05-05 13:19:03 +03:00
|
|
|
error_reportf_err(local_err, "Failed to get TLS creds: ");
|
2016-02-10 21:41:13 +03:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
qemu-nbd: add support for authorization of TLS clients
Currently any client which can complete the TLS handshake is able to use
the NBD server. The server admin can turn on the 'verify-peer' option
for the x509 creds to require the client to provide a x509 certificate.
This means the client will have to acquire a certificate from the CA
before they are permitted to use the NBD server. This is still a fairly
low bar to cross.
This adds a '--tls-authz OBJECT-ID' option to the qemu-nbd command which
takes the ID of a previously added 'QAuthZ' object instance. This will
be used to validate the client's x509 distinguished name. Clients
failing the authorization check will not be permitted to use the NBD
server.
For example to setup authorization that only allows connection from a client
whose x509 certificate distinguished name is
CN=laptop.example.com,O=Example Org,L=London,ST=London,C=GB
escape the commas in the name and use:
qemu-nbd --object tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\
endpoint=server,verify-peer=yes \
--object 'authz-simple,id=auth0,identity=CN=laptop.example.com,,\
O=Example Org,,L=London,,ST=London,,C=GB' \
--tls-creds tls0 \
--tls-authz authz0 \
....other qemu-nbd args...
NB: a real shell command line would not have leading whitespace after
the line continuation, it is just included here for clarity.
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <20190227162035.18543-2-berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[eblake: split long line in --help text, tweak 233 to show that whitespace
after ,, in identity= portion is actually okay]
Signed-off-by: Eric Blake <eblake@redhat.com>
2019-02-27 19:20:33 +03:00
|
|
|
} else {
|
|
|
|
if (tlsauthz) {
|
|
|
|
error_report("--tls-authz is not permitted without --tls-creds");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2022-03-04 22:36:02 +03:00
|
|
|
if (tlshostname) {
|
|
|
|
error_report("--tls-hostname is not permitted without --tls-creds");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2016-02-10 21:41:13 +03:00
|
|
|
}
|
|
|
|
|
2021-11-15 23:29:43 +03:00
|
|
|
if (selinux_label) {
|
|
|
|
#ifdef CONFIG_SELINUX
|
|
|
|
if (sockpath == NULL && device == NULL) {
|
|
|
|
error_report("--selinux-label is not permitted without --socket");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
error_report("SELinux support not enabled in this binary");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
if (list) {
|
|
|
|
saddr = nbd_build_socket_address(sockpath, bindto, port);
|
2022-03-04 22:36:02 +03:00
|
|
|
return qemu_nbd_client_list(saddr, tlscreds,
|
|
|
|
tlshostname ? tlshostname : bindto);
|
qemu-nbd: Add --list option
We want to be able to detect whether a given qemu NBD server is
exposing the right export(s) and dirty bitmaps, at least for
regression testing. We could use 'nbd-client -l' from the upstream
NBD project to list exports, but it's annoying to rely on
out-of-tree binaries; furthermore, nbd-client doesn't necessarily
know about all of the qemu NBD extensions. Thus, it is time to add
a new mode to qemu-nbd that merely sniffs all possible information
from the server during handshake phase, then disconnects and dumps
the information.
This patch actually implements --list/-L, while reusing other
options such as --tls-creds for now designating how to connect
as the client (rather than their non-list usage of how to operate
as the server).
I debated about adding this functionality to something akin to
'qemu-img info' - but that tool does not readily lend itself
to connecting to an arbitrary NBD server without also tying to
a specific export (I may, however, still add ImageInfoSpecificNBD
for reporting the bitmaps available when connecting to a single
export). And, while it may feel a bit odd that normally
qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not
really making the qemu-nbd binary that much larger, because
'qemu-nbd -c' has to operate as both server and client
simultaneously across two threads when feeding the kernel module
for /dev/nbdN access.
Sample output:
$ qemu-nbd -L
exports available: 1
export: ''
size: 65536
flags: 0x4ed ( flush fua trim zeroes df cache )
min block: 512
opt block: 4096
max block: 33554432
available meta contexts: 1
base:allocation
Note that the output only lists sizes if the server sent
NBD_FLAG_HAS_FLAGS, because a newstyle server does not give
the size otherwise. It has the side effect that for really
old servers that did not send any flags, the size is not
output even though it was available. However, I'm not too
concerned about that - oldstyle servers are (rightfully)
getting less common to encounter (qemu 3.0 was the last
version where we even serve it), and most existing servers
that still even offer oldstyle negotiation (such as nbdkit)
still send flags (since that was added to the NBD protocol
in 2007 to permit read-only connections).
Not done here, but maybe worth future experiments: capture
the meat of NBDExportInfo into a QAPI struct, and use the
generated QAPI pretty-printers instead of hand-rolling our
output loop. It would also permit us to add a JSON output
mode for machine parsing.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20190117193658.16413-20-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2019-01-17 22:36:56 +03:00
|
|
|
}
|
|
|
|
|
2018-12-15 16:53:08 +03:00
|
|
|
#if !HAVE_NBD_DEVICE
|
|
|
|
if (disconnect || device) {
|
|
|
|
error_report("Kernel /dev/nbdN support not available");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
#else /* HAVE_NBD_DEVICE */
|
2008-07-03 14:23:51 +04:00
|
|
|
if (disconnect) {
|
2016-02-10 21:41:02 +03:00
|
|
|
int nbdfd = open(argv[optind], O_RDWR);
|
|
|
|
if (nbdfd < 0) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Cannot open %s: %s", argv[optind],
|
|
|
|
strerror(errno));
|
|
|
|
exit(EXIT_FAILURE);
|
2012-03-07 14:05:34 +04:00
|
|
|
}
|
2016-02-10 21:41:02 +03:00
|
|
|
nbd_disconnect(nbdfd);
|
2008-07-03 14:23:51 +04:00
|
|
|
|
2016-02-10 21:41:02 +03:00
|
|
|
close(nbdfd);
|
2008-07-03 14:23:51 +04:00
|
|
|
|
|
|
|
printf("%s disconnected\n", argv[optind]);
|
|
|
|
|
2014-08-13 21:20:19 +04:00
|
|
|
return 0;
|
2008-07-03 14:23:51 +04:00
|
|
|
}
|
2018-12-15 16:53:08 +03:00
|
|
|
#endif
|
2008-07-03 14:23:51 +04:00
|
|
|
|
2016-09-28 23:46:42 +03:00
|
|
|
if ((device && !verbose) || fork_process) {
|
2020-08-25 13:38:50 +03:00
|
|
|
#ifndef WIN32
|
2022-03-29 14:21:00 +03:00
|
|
|
g_autoptr(GError) err = NULL;
|
2011-11-04 18:51:22 +04:00
|
|
|
int stderr_fd[2];
|
|
|
|
pid_t pid;
|
|
|
|
int ret;
|
|
|
|
|
2022-03-29 14:21:00 +03:00
|
|
|
if (!g_unix_open_pipe(stderr_fd, FD_CLOEXEC, &err)) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Error setting up communication pipe: %s",
|
2022-03-29 14:21:00 +03:00
|
|
|
err->message);
|
2015-12-18 18:35:04 +03:00
|
|
|
exit(EXIT_FAILURE);
|
2011-11-04 18:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now daemonize, but keep a communication channel open to
|
|
|
|
* print errors and exit with the proper status code.
|
|
|
|
*/
|
|
|
|
pid = fork();
|
2015-02-25 21:08:22 +03:00
|
|
|
if (pid < 0) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Failed to fork: %s", strerror(errno));
|
|
|
|
exit(EXIT_FAILURE);
|
2015-02-25 21:08:22 +03:00
|
|
|
} else if (pid == 0) {
|
2023-07-17 17:55:43 +03:00
|
|
|
int saved_errno;
|
|
|
|
|
2011-11-04 18:51:22 +04:00
|
|
|
close(stderr_fd[0]);
|
2019-05-09 00:18:18 +03:00
|
|
|
|
2012-01-16 18:37:44 +04:00
|
|
|
ret = qemu_daemon(1, 0);
|
2023-07-17 17:55:43 +03:00
|
|
|
saved_errno = errno; /* dup2 will overwrite error below */
|
2011-11-04 18:51:22 +04:00
|
|
|
|
|
|
|
/* Temporarily redirect stderr to the parent's pipe... */
|
2023-07-17 17:55:42 +03:00
|
|
|
if (dup2(stderr_fd[1], STDERR_FILENO) < 0) {
|
|
|
|
char str[256];
|
|
|
|
snprintf(str, sizeof(str),
|
|
|
|
"%s: Failed to link stderr to the pipe: %s\n",
|
|
|
|
g_get_prgname(), strerror(errno));
|
|
|
|
/*
|
|
|
|
* We are unable to use error_report() here as we need to get
|
|
|
|
* stderr pointed to the parent's pipe. Write to that pipe
|
|
|
|
* manually.
|
|
|
|
*/
|
|
|
|
ret = write(stderr_fd[1], str, strlen(str));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2012-03-07 14:05:34 +04:00
|
|
|
if (ret < 0) {
|
2023-07-17 17:55:43 +03:00
|
|
|
error_report("Failed to daemonize: %s", strerror(saved_errno));
|
2015-12-18 18:35:04 +03:00
|
|
|
exit(EXIT_FAILURE);
|
2011-11-04 18:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ... close the descriptor we inherited and go on. */
|
|
|
|
close(stderr_fd[1]);
|
|
|
|
} else {
|
|
|
|
bool errors = false;
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
/* In the parent. Print error messages from the child until
|
|
|
|
* it closes the pipe.
|
|
|
|
*/
|
|
|
|
close(stderr_fd[1]);
|
|
|
|
buf = g_malloc(1024);
|
|
|
|
while ((ret = read(stderr_fd[0], buf, 1024)) > 0) {
|
|
|
|
errors = true;
|
|
|
|
ret = qemu_write_full(STDERR_FILENO, buf, ret);
|
2012-03-07 14:05:34 +04:00
|
|
|
if (ret < 0) {
|
2011-11-04 18:51:22 +04:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
2012-03-07 14:05:34 +04:00
|
|
|
if (ret < 0) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Cannot read from daemon: %s",
|
|
|
|
strerror(errno));
|
|
|
|
exit(EXIT_FAILURE);
|
2011-11-04 18:51:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Usually the daemon should not print any message.
|
|
|
|
* Exit with zero status in that case.
|
|
|
|
*/
|
|
|
|
exit(errors);
|
|
|
|
}
|
2020-08-25 13:38:50 +03:00
|
|
|
#else /* WIN32 */
|
|
|
|
error_report("Unable to fork into background on Windows hosts");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
#endif /* WIN32 */
|
2011-11-04 18:51:22 +04:00
|
|
|
}
|
|
|
|
|
2011-12-06 12:07:00 +04:00
|
|
|
if (device != NULL && sockpath == NULL) {
|
|
|
|
sockpath = g_malloc(128);
|
|
|
|
snprintf(sockpath, 128, SOCKET_PATH, basename(device));
|
2008-07-03 14:23:51 +04:00
|
|
|
}
|
|
|
|
|
2017-12-18 13:16:43 +03:00
|
|
|
server = qio_net_listener_new();
|
2017-02-04 13:03:17 +03:00
|
|
|
if (socket_activation == 0) {
|
2021-02-09 18:27:58 +03:00
|
|
|
int backlog;
|
|
|
|
|
2021-02-09 18:27:59 +03:00
|
|
|
if (persistent || shared == 0) {
|
2021-02-09 18:27:58 +03:00
|
|
|
backlog = SOMAXCONN;
|
|
|
|
} else {
|
|
|
|
backlog = MIN(shared, SOMAXCONN);
|
|
|
|
}
|
2021-11-15 23:29:43 +03:00
|
|
|
#ifdef CONFIG_SELINUX
|
|
|
|
if (selinux_label && setsockcreatecon_raw(selinux_label) == -1) {
|
|
|
|
error_report("Cannot set SELinux socket create context to %s: %s",
|
|
|
|
selinux_label, strerror(errno));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
#endif
|
2017-02-04 13:03:17 +03:00
|
|
|
saddr = nbd_build_socket_address(sockpath, bindto, port);
|
2021-02-09 18:27:58 +03:00
|
|
|
if (qio_net_listener_open_sync(server, saddr, backlog,
|
|
|
|
&local_err) < 0) {
|
2017-12-18 13:16:43 +03:00
|
|
|
object_unref(OBJECT(server));
|
2017-02-04 13:03:17 +03:00
|
|
|
error_report_err(local_err);
|
2017-12-18 13:16:43 +03:00
|
|
|
exit(EXIT_FAILURE);
|
2017-02-04 13:03:17 +03:00
|
|
|
}
|
2021-11-15 23:29:43 +03:00
|
|
|
#ifdef CONFIG_SELINUX
|
|
|
|
if (selinux_label && setsockcreatecon_raw(NULL) == -1) {
|
|
|
|
error_report("Cannot clear SELinux socket create context: %s",
|
|
|
|
strerror(errno));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
#endif
|
2017-02-04 13:03:17 +03:00
|
|
|
} else {
|
2017-12-18 13:16:43 +03:00
|
|
|
size_t i;
|
2017-02-04 13:03:17 +03:00
|
|
|
/* See comment in check_socket_activation above. */
|
2017-12-18 13:16:43 +03:00
|
|
|
for (i = 0; i < socket_activation; i++) {
|
|
|
|
QIOChannelSocket *sioc;
|
|
|
|
sioc = qio_channel_socket_new_fd(FIRST_SOCKET_ACTIVATION_FD + i,
|
|
|
|
&local_err);
|
|
|
|
if (sioc == NULL) {
|
|
|
|
object_unref(OBJECT(server));
|
2020-05-05 13:19:03 +03:00
|
|
|
error_reportf_err(local_err,
|
|
|
|
"Failed to use socket activation: ");
|
2017-12-18 13:16:43 +03:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
qio_net_listener_add(server, sioc);
|
|
|
|
object_unref(OBJECT(sioc));
|
2017-02-04 13:03:17 +03:00
|
|
|
}
|
|
|
|
}
|
2015-09-16 16:52:23 +03:00
|
|
|
|
2021-07-20 15:53:53 +03:00
|
|
|
qemu_init_main_loop(&error_fatal);
|
2011-11-04 18:51:24 +04:00
|
|
|
bdrv_init();
|
2018-05-16 14:46:37 +03:00
|
|
|
atexit(qemu_nbd_shutdown);
|
2011-11-04 18:51:24 +04:00
|
|
|
|
2016-02-17 13:10:19 +03:00
|
|
|
srcpath = argv[optind];
|
|
|
|
if (imageOpts) {
|
|
|
|
QemuOpts *opts;
|
|
|
|
if (fmt) {
|
|
|
|
error_report("--image-opts and -f are mutually exclusive");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
opts = qemu_opts_parse_noisily(&file_opts, srcpath, true);
|
|
|
|
if (!opts) {
|
|
|
|
qemu_opts_reset(&file_opts);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
options = qemu_opts_to_qdict(opts, NULL);
|
|
|
|
qemu_opts_reset(&file_opts);
|
2016-03-16 21:54:38 +03:00
|
|
|
blk = blk_new_open(NULL, NULL, options, flags, &local_err);
|
2016-02-17 13:10:19 +03:00
|
|
|
} else {
|
|
|
|
if (fmt) {
|
|
|
|
options = qdict_new();
|
2017-04-28 00:58:17 +03:00
|
|
|
qdict_put_str(options, "driver", fmt);
|
2016-02-17 13:10:19 +03:00
|
|
|
}
|
2016-03-16 21:54:38 +03:00
|
|
|
blk = blk_new_open(srcpath, NULL, options, flags, &local_err);
|
2013-03-19 15:20:20 +04:00
|
|
|
}
|
|
|
|
|
2015-02-05 21:58:19 +03:00
|
|
|
if (!blk) {
|
2015-12-18 18:35:14 +03:00
|
|
|
error_reportf_err(local_err, "Failed to blk_new_open '%s': ",
|
|
|
|
argv[optind]);
|
2015-12-18 18:35:04 +03:00
|
|
|
exit(EXIT_FAILURE);
|
2011-11-04 18:51:24 +04:00
|
|
|
}
|
2015-02-05 21:58:19 +03:00
|
|
|
bs = blk_bs(blk);
|
2011-11-04 18:51:24 +04:00
|
|
|
|
2020-09-24 18:26:52 +03:00
|
|
|
if (dev_offset) {
|
|
|
|
QDict *raw_opts = qdict_new();
|
|
|
|
qdict_put_str(raw_opts, "driver", "raw");
|
|
|
|
qdict_put_str(raw_opts, "file", bs->node_name);
|
|
|
|
qdict_put_int(raw_opts, "offset", dev_offset);
|
2023-05-25 15:47:04 +03:00
|
|
|
|
|
|
|
aio_context_acquire(qemu_get_aio_context());
|
2020-09-24 18:26:52 +03:00
|
|
|
bs = bdrv_open(NULL, NULL, raw_opts, flags, &error_fatal);
|
2023-05-25 15:47:04 +03:00
|
|
|
aio_context_release(qemu_get_aio_context());
|
|
|
|
|
2020-09-24 18:26:52 +03:00
|
|
|
blk_remove_bs(blk);
|
|
|
|
blk_insert_bs(blk, bs, &error_fatal);
|
|
|
|
bdrv_unref(bs);
|
|
|
|
}
|
|
|
|
|
2016-03-14 13:43:28 +03:00
|
|
|
blk_set_enable_write_cache(blk, !writethrough);
|
|
|
|
|
2013-12-04 13:10:55 +04:00
|
|
|
if (sn_opts) {
|
|
|
|
ret = bdrv_snapshot_load_tmp(bs,
|
|
|
|
qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID),
|
|
|
|
qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME),
|
|
|
|
&local_err);
|
|
|
|
} else if (sn_id_or_name) {
|
|
|
|
ret = bdrv_snapshot_load_tmp_by_id_or_name(bs, sn_id_or_name,
|
|
|
|
&local_err);
|
|
|
|
}
|
|
|
|
if (ret < 0) {
|
2015-12-18 18:35:14 +03:00
|
|
|
error_reportf_err(local_err, "Failed to load snapshot: ");
|
2015-12-18 18:35:04 +03:00
|
|
|
exit(EXIT_FAILURE);
|
2013-12-04 13:10:55 +04:00
|
|
|
}
|
|
|
|
|
2014-08-13 21:20:18 +04:00
|
|
|
bs->detect_zeroes = detect_zeroes;
|
2016-10-06 00:40:20 +03:00
|
|
|
|
2022-05-12 03:49:23 +03:00
|
|
|
nbd_server_is_qemu_nbd(shared);
|
2020-09-24 18:26:57 +03:00
|
|
|
|
|
|
|
export_opts = g_new(BlockExportOptions, 1);
|
|
|
|
*export_opts = (BlockExportOptions) {
|
|
|
|
.type = BLOCK_EXPORT_TYPE_NBD,
|
2020-09-24 18:27:04 +03:00
|
|
|
.id = g_strdup("qemu-nbd-export"),
|
2020-09-24 18:27:01 +03:00
|
|
|
.node_name = g_strdup(bdrv_get_node_name(bs)),
|
2020-09-24 18:26:57 +03:00
|
|
|
.has_writethrough = true,
|
|
|
|
.writethrough = writethrough,
|
2020-09-24 18:27:11 +03:00
|
|
|
.has_writable = true,
|
|
|
|
.writable = !readonly,
|
2020-09-24 18:26:57 +03:00
|
|
|
.u.nbd = {
|
2020-10-27 08:05:49 +03:00
|
|
|
.name = g_strdup(export_name),
|
|
|
|
.description = g_strdup(export_description),
|
|
|
|
.has_bitmaps = !!bitmaps,
|
|
|
|
.bitmaps = bitmaps,
|
2020-10-27 08:05:55 +03:00
|
|
|
.has_allocation_depth = alloc_depth,
|
|
|
|
.allocation_depth = alloc_depth,
|
2020-09-24 18:26:57 +03:00
|
|
|
},
|
|
|
|
};
|
|
|
|
blk_exp_add(export_opts, &error_fatal);
|
|
|
|
qapi_free_BlockExportOptions(export_opts);
|
2008-07-03 16:45:02 +04:00
|
|
|
|
2011-11-04 18:51:23 +04:00
|
|
|
if (device) {
|
2018-12-15 16:53:08 +03:00
|
|
|
#if HAVE_NBD_DEVICE
|
2011-11-04 18:51:23 +04:00
|
|
|
int ret;
|
2023-07-17 17:55:40 +03:00
|
|
|
struct NbdClientOpts opts = {
|
|
|
|
.device = device,
|
2023-07-17 17:55:41 +03:00
|
|
|
.fork_process = fork_process,
|
2023-07-17 23:25:20 +03:00
|
|
|
.verbose = verbose,
|
2023-07-17 17:55:40 +03:00
|
|
|
};
|
2011-11-04 18:51:23 +04:00
|
|
|
|
2023-07-17 17:55:40 +03:00
|
|
|
ret = pthread_create(&client_thread, NULL, nbd_client_thread, &opts);
|
2011-11-04 18:51:23 +04:00
|
|
|
if (ret != 0) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Failed to create client thread: %s", strerror(ret));
|
|
|
|
exit(EXIT_FAILURE);
|
2011-11-04 18:51:23 +04:00
|
|
|
}
|
2018-12-15 16:53:08 +03:00
|
|
|
#endif
|
2011-11-04 18:51:23 +04:00
|
|
|
} else {
|
|
|
|
/* Shut up GCC warnings. */
|
|
|
|
memset(&client_thread, 0, sizeof(client_thread));
|
|
|
|
}
|
|
|
|
|
2016-02-10 21:41:02 +03:00
|
|
|
nbd_update_server_watch();
|
2008-05-28 01:13:40 +04:00
|
|
|
|
2019-05-09 00:18:16 +03:00
|
|
|
if (pid_file_name) {
|
|
|
|
qemu_write_pidfile(pid_file_name, &error_fatal);
|
|
|
|
}
|
|
|
|
|
2012-01-16 18:37:44 +04:00
|
|
|
/* now when the initialization is (almost) complete, chdir("/")
|
|
|
|
* to free any busy filesystems */
|
|
|
|
if (chdir("/") < 0) {
|
2015-12-18 18:35:04 +03:00
|
|
|
error_report("Could not chdir to root directory: %s",
|
|
|
|
strerror(errno));
|
|
|
|
exit(EXIT_FAILURE);
|
2012-01-16 18:37:44 +04:00
|
|
|
}
|
|
|
|
|
2016-09-28 23:46:42 +03:00
|
|
|
if (fork_process) {
|
2023-07-17 17:55:44 +03:00
|
|
|
if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) {
|
|
|
|
error_report("Could not set stderr to /dev/null: %s",
|
|
|
|
strerror(errno));
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2016-09-28 23:46:42 +03:00
|
|
|
}
|
|
|
|
|
2012-09-18 15:31:56 +04:00
|
|
|
state = RUNNING;
|
2008-07-03 16:45:02 +04:00
|
|
|
do {
|
2011-09-12 19:28:11 +04:00
|
|
|
main_loop_wait(false);
|
2012-09-18 15:31:56 +04:00
|
|
|
if (state == TERMINATE) {
|
2020-09-24 18:27:03 +03:00
|
|
|
blk_exp_close_all();
|
2020-09-24 18:26:56 +03:00
|
|
|
state = TERMINATED;
|
2012-09-18 15:31:56 +04:00
|
|
|
}
|
|
|
|
} while (state != TERMINATED);
|
2008-05-28 01:13:40 +04:00
|
|
|
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
blk_unref(blk);
|
2011-11-04 18:51:20 +04:00
|
|
|
if (sockpath) {
|
|
|
|
unlink(sockpath);
|
|
|
|
}
|
2008-05-28 01:13:40 +04:00
|
|
|
|
2014-09-29 18:07:55 +04:00
|
|
|
qemu_opts_del(sn_opts);
|
2013-12-04 13:10:55 +04:00
|
|
|
|
2011-11-04 18:51:21 +04:00
|
|
|
if (device) {
|
|
|
|
void *ret;
|
|
|
|
pthread_join(client_thread, &ret);
|
|
|
|
exit(ret != NULL);
|
|
|
|
} else {
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
2008-05-28 01:13:40 +04:00
|
|
|
}
|