Skip to content

Commit

Permalink
Merge tag 'pull-nbd-2023-09-07-v2' of https://repo.or.cz/qemu/ericb i…
Browse files Browse the repository at this point in the history
…nto staging

NBD patches for 2023-09-07

- Andrey Drobyshev - fix regression in iotest 197 under -nbd
- Stefan Hajnoczi - allow coroutine read and write context to split
across threads
- Philippe Mathieu-Daudé - remove a VLA allocation
- Denis V. Lunev - fix regression in iotest 233 with qemu-nbd -v --fork

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCAAdFiEEccLMIrHEYCkn0vOqp6FrSiUnQ2oFAmT7EsUACgkQp6FrSiUn
# Q2qiKgf9EqCWPmcsH2nvXrDvZmDc0/I4tineaNY+hSdPtSb6RFA1IH8AvzkrkPYU
# 9ojX6QFp1Z30fUs+pwweQhBMYta03QyjCFhsbPRmDq391dtIDCeww3o+RD1kw/pg
# 2ZC+P9N1U3pi2Hi8FhxH17GYYgOQnHMKM9gt1V7JOQvFsDFWbTo9sFj8p/BPoWxV
# I3TeLQDWqVnNjf57lG2pwhdKc8DbKoqRmA3XNiXiKI5inEBeRJsTdMMGn4YWpwJE
# Y5imM/PbyCqRKQ6MYyJenVk4QVTe1IKO6D4vf1ZHLDBEiaw9NaeYHlk6lnDC4O9v
# PeTycAwND6cMKYlKMyEzcJXv9IdRBw==
# =jAZi
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 08 Sep 2023 08:25:41 EDT
# gpg:                using RSA key 71C2CC22B1C4602927D2F3AAA7A16B4A2527436A
# gpg: Good signature from "Eric Blake <eblake@redhat.com>" [full]
# gpg:                 aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" [full]
# gpg:                 aka "[jpeg image of size 6874]" [full]
# Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2  F3AA A7A1 6B4A 2527 436A

* tag 'pull-nbd-2023-09-07-v2' of https://repo.or.cz/qemu/ericb:
  qemu-nbd: document -v behavior in respect to --fork in man
  qemu-nbd: Restore "qemu-nbd -v --fork" output
  qemu-nbd: invent nbd_client_release_pipe() helper
  qemu-nbd: put saddr into into struct NbdClientOpts
  qemu-nbd: move srcpath into struct NbdClientOpts
  qemu-nbd: define struct NbdClientOpts when HAVE_NBD_DEVICE is not defined
  qemu-nbd: improve error message for dup2 error
  util/iov: Avoid dynamic stack allocation
  io: follow coroutine AioContext in qio_channel_yield()
  io: check there are no qio_channel_yield() coroutines during ->finalize()
  nbd: drop unused nbd_start_negotiate() aio_context argument
  nbd: drop unused nbd_receive_negotiate() aio_context argument
  qemu-iotests/197: use more generic commands for formats other than qcow2

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
  • Loading branch information
stefanhaRH committed Sep 8, 2023
2 parents 2f352bc + 35e087d commit 0b63052
Show file tree
Hide file tree
Showing 24 changed files with 325 additions and 216 deletions.
11 changes: 1 addition & 10 deletions block/nbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ int coroutine_fn nbd_co_do_establish_connection(BlockDriverState *bs,
}

qio_channel_set_blocking(s->ioc, false, NULL);
qio_channel_attach_aio_context(s->ioc, bdrv_get_aio_context(bs));
qio_channel_set_follow_coroutine_ctx(s->ioc, true);

/* successfully connected */
WITH_QEMU_LOCK_GUARD(&s->requests_lock) {
Expand Down Expand Up @@ -397,7 +397,6 @@ static void coroutine_fn GRAPH_RDLOCK nbd_reconnect_attempt(BDRVNBDState *s)

/* Finalize previous connection if any */
if (s->ioc) {
qio_channel_detach_aio_context(s->ioc);
yank_unregister_function(BLOCKDEV_YANK_INSTANCE(s->bs->node_name),
nbd_yank, s->bs);
object_unref(OBJECT(s->ioc));
Expand Down Expand Up @@ -2089,10 +2088,6 @@ static void nbd_attach_aio_context(BlockDriverState *bs,
* the reconnect_delay_timer cannot be active here.
*/
assert(!s->reconnect_delay_timer);

if (s->ioc) {
qio_channel_attach_aio_context(s->ioc, new_context);
}
}

static void nbd_detach_aio_context(BlockDriverState *bs)
Expand All @@ -2101,10 +2096,6 @@ static void nbd_detach_aio_context(BlockDriverState *bs)

assert(!s->open_timer);
assert(!s->reconnect_delay_timer);

if (s->ioc) {
qio_channel_detach_aio_context(s->ioc);
}
}

static BlockDriver bdrv_nbd = {
Expand Down
4 changes: 3 additions & 1 deletion docs/tools/qemu-nbd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,9 @@ driver options if :option:`--image-opts` is specified.

.. option:: -v, --verbose

Display extra debugging information.
Display extra debugging information. This option also keeps the original
*STDERR* stream open if the ``qemu-nbd`` process is daemonized due to
other options like :option:`--fork` or :option:`-c`.

.. option:: -h, --help

Expand Down
3 changes: 1 addition & 2 deletions include/block/nbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,7 @@ typedef struct NBDExportInfo {
char **contexts;
} NBDExportInfo;

int nbd_receive_negotiate(AioContext *aio_context, QIOChannel *ioc,
QCryptoTLSCreds *tlscreds,
int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
const char *hostname, QIOChannel **outioc,
NBDExportInfo *info, Error **errp);
void nbd_free_export_list(NBDExportInfo *info, int count);
Expand Down
23 changes: 23 additions & 0 deletions include/io/channel-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,27 @@
QIOChannel *qio_channel_new_fd(int fd,
Error **errp);

/**
* qio_channel_util_set_aio_fd_handler:
* @read_fd: the file descriptor for the read handler
* @read_ctx: the AioContext for the read handler
* @io_read: the read handler
* @write_fd: the file descriptor for the write handler
* @write_ctx: the AioContext for the write handler
* @io_write: the write handler
* @opaque: the opaque argument to the read and write handler
*
* Set the read and write handlers when @read_ctx and @write_ctx are non-NULL,
* respectively. To leave a handler in its current state, pass a NULL
* AioContext. To clear a handler, pass a non-NULL AioContext and a NULL
* handler.
*/
void qio_channel_util_set_aio_fd_handler(int read_fd,
AioContext *read_ctx,
IOHandler *io_read,
int write_fd,
AioContext *write_ctx,
IOHandler *io_write,
void *opaque);

#endif /* QIO_CHANNEL_UTIL_H */
69 changes: 30 additions & 39 deletions include/io/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ struct QIOChannel {
Object parent;
unsigned int features; /* bitmask of QIOChannelFeatures */
char *name;
AioContext *ctx;
AioContext *read_ctx;
Coroutine *read_coroutine;
AioContext *write_ctx;
Coroutine *write_coroutine;
bool follow_coroutine_ctx;
#ifdef _WIN32
HANDLE event; /* For use with GSource on Win32 */
#endif
Expand Down Expand Up @@ -140,8 +142,9 @@ struct QIOChannelClass {
int whence,
Error **errp);
void (*io_set_aio_fd_handler)(QIOChannel *ioc,
AioContext *ctx,
AioContext *read_ctx,
IOHandler *io_read,
AioContext *write_ctx,
IOHandler *io_write,
void *opaque);
int (*io_flush)(QIOChannel *ioc,
Expand Down Expand Up @@ -498,6 +501,21 @@ int qio_channel_set_blocking(QIOChannel *ioc,
bool enabled,
Error **errp);

/**
* qio_channel_set_follow_coroutine_ctx:
* @ioc: the channel object
* @enabled: whether or not to follow the coroutine's AioContext
*
* If @enabled is true, calls to qio_channel_yield() use the current
* coroutine's AioContext. Usually this is desirable.
*
* If @enabled is false, calls to qio_channel_yield() use the global iohandler
* AioContext. This is may be used by coroutines that run in the main loop and
* do not wish to respond to I/O during nested event loops. This is the
* default for compatibility with code that is not aware of AioContexts.
*/
void qio_channel_set_follow_coroutine_ctx(QIOChannel *ioc, bool enabled);

/**
* qio_channel_close:
* @ioc: the channel object
Expand Down Expand Up @@ -703,41 +721,6 @@ GSource *qio_channel_add_watch_source(QIOChannel *ioc,
GDestroyNotify notify,
GMainContext *context);

/**
* qio_channel_attach_aio_context:
* @ioc: the channel object
* @ctx: the #AioContext to set the handlers on
*
* Request that qio_channel_yield() sets I/O handlers on
* the given #AioContext. If @ctx is %NULL, qio_channel_yield()
* uses QEMU's main thread event loop.
*
* You can move a #QIOChannel from one #AioContext to another even if
* I/O handlers are set for a coroutine. However, #QIOChannel provides
* no synchronization between the calls to qio_channel_yield() and
* qio_channel_attach_aio_context().
*
* Therefore you should first call qio_channel_detach_aio_context()
* to ensure that the coroutine is not entered concurrently. Then,
* while the coroutine has yielded, call qio_channel_attach_aio_context(),
* and then aio_co_schedule() to place the coroutine on the new
* #AioContext. The calls to qio_channel_detach_aio_context()
* and qio_channel_attach_aio_context() should be protected with
* aio_context_acquire() and aio_context_release().
*/
void qio_channel_attach_aio_context(QIOChannel *ioc,
AioContext *ctx);

/**
* qio_channel_detach_aio_context:
* @ioc: the channel object
*
* Disable any I/O handlers set by qio_channel_yield(). With the
* help of aio_co_schedule(), this allows moving a coroutine that was
* paused by qio_channel_yield() to another context.
*/
void qio_channel_detach_aio_context(QIOChannel *ioc);

/**
* qio_channel_yield:
* @ioc: the channel object
Expand Down Expand Up @@ -785,19 +768,27 @@ void qio_channel_wait(QIOChannel *ioc,
/**
* qio_channel_set_aio_fd_handler:
* @ioc: the channel object
* @ctx: the AioContext to set the handlers on
* @read_ctx: the AioContext to set the read handler on or NULL
* @io_read: the read handler
* @write_ctx: the AioContext to set the write handler on or NULL
* @io_write: the write handler
* @opaque: the opaque value passed to the handler
*
* This is used internally by qio_channel_yield(). It can
* be used by channel implementations to forward the handlers
* to another channel (e.g. from #QIOChannelTLS to the
* underlying socket).
*
* When @read_ctx is NULL, don't touch the read handler. When @write_ctx is
* NULL, don't touch the write handler. Note that setting the read handler
* clears the write handler, and vice versa, if they share the same AioContext.
* Therefore the caller must pass both handlers together when sharing the same
* AioContext.
*/
void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
AioContext *ctx,
AioContext *read_ctx,
IOHandler *io_read,
AioContext *write_ctx,
IOHandler *io_write,
void *opaque);

Expand Down
1 change: 1 addition & 0 deletions include/qemu/vhost-user-server.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ typedef struct {
unsigned int in_flight; /* atomic */

/* Protected by ctx lock */
bool in_qio_channel_yield;
bool wait_idle;
VuDev vu_dev;
QIOChannel *ioc; /* The I/O channel with the client */
Expand Down
10 changes: 7 additions & 3 deletions io/channel-command.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "qemu/osdep.h"
#include "io/channel-command.h"
#include "io/channel-util.h"
#include "io/channel-watch.h"
#include "qapi/error.h"
#include "qemu/module.h"
Expand Down Expand Up @@ -331,14 +332,17 @@ static int qio_channel_command_close(QIOChannel *ioc,


static void qio_channel_command_set_aio_fd_handler(QIOChannel *ioc,
AioContext *ctx,
AioContext *read_ctx,
IOHandler *io_read,
AioContext *write_ctx,
IOHandler *io_write,
void *opaque)
{
QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
aio_set_fd_handler(ctx, cioc->readfd, io_read, NULL, NULL, NULL, opaque);
aio_set_fd_handler(ctx, cioc->writefd, NULL, io_write, NULL, NULL, opaque);

qio_channel_util_set_aio_fd_handler(cioc->readfd, read_ctx, io_read,
cioc->writefd, write_ctx, io_write,
opaque);
}


Expand Down
9 changes: 7 additions & 2 deletions io/channel-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "qemu/osdep.h"
#include "io/channel-file.h"
#include "io/channel-util.h"
#include "io/channel-watch.h"
#include "qapi/error.h"
#include "qemu/module.h"
Expand Down Expand Up @@ -192,13 +193,17 @@ static int qio_channel_file_close(QIOChannel *ioc,


static void qio_channel_file_set_aio_fd_handler(QIOChannel *ioc,
AioContext *ctx,
AioContext *read_ctx,
IOHandler *io_read,
AioContext *write_ctx,
IOHandler *io_write,
void *opaque)
{
QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
aio_set_fd_handler(ctx, fioc->fd, io_read, io_write, NULL, NULL, opaque);

qio_channel_util_set_aio_fd_handler(fioc->fd, read_ctx, io_read,
fioc->fd, write_ctx, io_write,
opaque);
}

static GSource *qio_channel_file_create_watch(QIOChannel *ioc,
Expand Down
3 changes: 2 additions & 1 deletion io/channel-null.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,9 @@ qio_channel_null_close(QIOChannel *ioc,

static void
qio_channel_null_set_aio_fd_handler(QIOChannel *ioc G_GNUC_UNUSED,
AioContext *ctx G_GNUC_UNUSED,
AioContext *read_ctx G_GNUC_UNUSED,
IOHandler *io_read G_GNUC_UNUSED,
AioContext *write_ctx G_GNUC_UNUSED,
IOHandler *io_write G_GNUC_UNUSED,
void *opaque G_GNUC_UNUSED)
{
Expand Down
9 changes: 7 additions & 2 deletions io/channel-socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "qapi/qapi-visit-sockets.h"
#include "qemu/module.h"
#include "io/channel-socket.h"
#include "io/channel-util.h"
#include "io/channel-watch.h"
#include "trace.h"
#include "qapi/clone-visitor.h"
Expand Down Expand Up @@ -893,13 +894,17 @@ qio_channel_socket_shutdown(QIOChannel *ioc,
}

static void qio_channel_socket_set_aio_fd_handler(QIOChannel *ioc,
AioContext *ctx,
AioContext *read_ctx,
IOHandler *io_read,
AioContext *write_ctx,
IOHandler *io_write,
void *opaque)
{
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
aio_set_fd_handler(ctx, sioc->fd, io_read, io_write, NULL, NULL, opaque);

qio_channel_util_set_aio_fd_handler(sioc->fd, read_ctx, io_read,
sioc->fd, write_ctx, io_write,
opaque);
}

static GSource *qio_channel_socket_create_watch(QIOChannel *ioc,
Expand Down
6 changes: 4 additions & 2 deletions io/channel-tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,14 +388,16 @@ static int qio_channel_tls_close(QIOChannel *ioc,
}

static void qio_channel_tls_set_aio_fd_handler(QIOChannel *ioc,
AioContext *ctx,
AioContext *read_ctx,
IOHandler *io_read,
AioContext *write_ctx,
IOHandler *io_write,
void *opaque)
{
QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);

qio_channel_set_aio_fd_handler(tioc->master, ctx, io_read, io_write, opaque);
qio_channel_set_aio_fd_handler(tioc->master, read_ctx, io_read,
write_ctx, io_write, opaque);
}

typedef struct QIOChannelTLSSource QIOChannelTLSSource;
Expand Down
24 changes: 24 additions & 0 deletions io/channel-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,27 @@ QIOChannel *qio_channel_new_fd(int fd,
}
return ioc;
}


void qio_channel_util_set_aio_fd_handler(int read_fd,
AioContext *read_ctx,
IOHandler *io_read,
int write_fd,
AioContext *write_ctx,
IOHandler *io_write,
void *opaque)
{
if (read_fd == write_fd && read_ctx == write_ctx) {
aio_set_fd_handler(read_ctx, read_fd, io_read, io_write,
NULL, NULL, opaque);
} else {
if (read_ctx) {
aio_set_fd_handler(read_ctx, read_fd, io_read, NULL,
NULL, NULL, opaque);
}
if (write_ctx) {
aio_set_fd_handler(write_ctx, write_fd, NULL, io_write,
NULL, NULL, opaque);
}
}
}

0 comments on commit 0b63052

Please sign in to comment.