Richard W.M. Jones
2020-Mar-04 15:17 UTC
[Libguestfs] [PATCH nbdkit 0/4] server: Add nbdkit_shutdown() call and two new filters.
This adds a new nbdkit_shutdown() API whereby plugins and filters can request that the server shuts down (asynchronously) during the serving phase. Two new filters are added, one of which depends on this feature and the other not needing it but being somewhat related. Rich.
Richard W.M. Jones
2020-Mar-04 15:17 UTC
[Libguestfs] [PATCH nbdkit 1/4] tests: Rename test-shutdown.sh to test-delay-shutdown.sh.
This is testing the delay filter, and we want to use the name ‘test-shutdown’ in a later commit to test the new nbdkit_shutdown() API, so let’s rename it. --- tests/Makefile.am | 4 ++-- tests/{test-shutdown.sh => test-delay-shutdown.sh} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index effe1857..2dc35309 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -101,6 +101,7 @@ EXTRA_DIST = \ test-data-file.sh \ test-data-raw.sh \ test-debug-flags.sh \ + test-delay-shutdown.sh \ test-dump-config.sh \ test-dump-plugin.sh \ test-dump-plugin-example4.sh \ @@ -181,7 +182,6 @@ EXTRA_DIST = \ test-retry-readonly.sh \ test-retry-reopen-fail.sh \ test-retry-zero-flags.sh \ - test-shutdown.sh \ test-ssh.sh \ test-swap.sh \ test.tcl \ @@ -1017,7 +1017,7 @@ endif TESTS += test-cow-null.sh # delay filter tests. -TESTS += test-shutdown.sh +TESTS += test-delay-shutdown.sh LIBNBD_TESTS += test-delay test_delay_SOURCES = test-delay.c diff --git a/tests/test-shutdown.sh b/tests/test-delay-shutdown.sh similarity index 96% rename from tests/test-shutdown.sh rename to tests/test-delay-shutdown.sh index 7d17045a..342c2346 100755 --- a/tests/test-shutdown.sh +++ b/tests/test-delay-shutdown.sh @@ -37,7 +37,7 @@ requires qemu-io --version requires timeout --version sock=`mktemp -u` -files="shutdown.pid $sock" +files="delay-shutdown.pid $sock" cleanup_fn rm -f $files fail=0 @@ -45,7 +45,7 @@ fail=0 # This tests that the delay filter's use of nbdkit_nanosleep is able to # react to both connection death and server shutdown without finishing # the entire delay duration. -start_nbdkit -P shutdown.pid -U $sock --filter=noparallel --filter=delay \ +start_nbdkit -P delay-shutdown.pid -U $sock --filter=noparallel --filter=delay \ null 1M serialize=connections rdelay=60 # Early client death should not stall connection of second client. -- 2.25.0
Richard W.M. Jones
2020-Mar-04 15:17 UTC
[Libguestfs] [PATCH nbdkit 2/4] server: Add nbdkit_shutdown() call.
Plugins and filters may call this to initiate an asynchronous shutdown of the server. This would only be used in the connected phase — plugins should still call exit(3) directly for configuration failure. It is equivalent to sending a kill signal to self, but it's cleaner to have an API for this and better for potential future non-POSIX platforms. --- docs/nbdkit-plugin.pod | 19 +++++++- include/nbdkit-common.h | 1 + include/nbdkit-plugin.h | 2 +- tests/Makefile.am | 20 ++++++++ server/nbdkit.syms | 3 +- server/quit.c | 8 +++- tests/test-shutdown.sh | 71 ++++++++++++++++++++++++++++ tests/test-shutdown-plugin.c | 89 ++++++++++++++++++++++++++++++++++++ 8 files changed, 209 insertions(+), 4 deletions(-) diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod index 77f1a098..494d77f8 100644 --- a/docs/nbdkit-plugin.pod +++ b/docs/nbdkit-plugin.pod @@ -1058,6 +1058,23 @@ before unloading the plugin. Note that it's not guaranteed this can always happen (eg. the server might be killed by C<SIGKILL> or segfault). +=head2 Requesting asynchronous shutdown + +Plugins and filters can call L<exit(3)> in the configuration phase +(before and including C<.get_ready>, but not in connected callbacks). + +Once nbdkit has started serving connections, plugins and filters +should not call L<exit(3)>. However they may instruct nbdkit to shut +down by calling C<nbdkit_shutdown>: + + void nbdkit_shutdown (void); + +This function requests an asynchronous shutdown and returns (I<note> +that it does I<not> exit the process immediately). It ensures that +the plugin and all filters are unloaded cleanly which may take some +time. Further callbacks from nbdkit into the plugin or filter may +occur after you have called this. + =head1 PARSING COMMAND LINE PARAMETERS =head2 Parsing numbers @@ -1443,4 +1460,4 @@ Pino Toscano =head1 COPYRIGHT -Copyright (C) 2013-2018 Red Hat Inc. +Copyright (C) 2013-2020 Red Hat Inc. diff --git a/include/nbdkit-common.h b/include/nbdkit-common.h index 50f3dd4f..9d1d89d0 100644 --- a/include/nbdkit-common.h +++ b/include/nbdkit-common.h @@ -111,6 +111,7 @@ extern char *nbdkit_realpath (const char *path); extern int nbdkit_nanosleep (unsigned sec, unsigned nsec); extern const char *nbdkit_export_name (void); extern int nbdkit_peer_name (struct sockaddr *addr, socklen_t *addrlen); +extern void nbdkit_shutdown (void); struct nbdkit_extents; extern int nbdkit_add_extent (struct nbdkit_extents *, diff --git a/include/nbdkit-plugin.h b/include/nbdkit-plugin.h index 7e06a4b1..7ff7bcee 100644 --- a/include/nbdkit-plugin.h +++ b/include/nbdkit-plugin.h @@ -1,5 +1,5 @@ /* nbdkit - * Copyright (C) 2013-2019 Red Hat Inc. + * Copyright (C) 2013-2020 Red Hat Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are diff --git a/tests/Makefile.am b/tests/Makefile.am index 2dc35309..eb51757a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -265,6 +265,7 @@ TESTS += \ test-debug-flags.sh \ test-long-name.sh \ test-swap.sh \ + test-shutdown.sh \ $(NULL) check_PROGRAMS += \ @@ -278,6 +279,25 @@ test_socket_activation_CPPFLAGS = \ $(NULL) test_socket_activation_CFLAGS = $(WARNINGS_CFLAGS) +# check_LTLIBRARIES won't build a shared library (see automake manual). +# So we have to do this and add a dependency. +noinst_LTLIBRARIES += \ + test-shutdown-plugin.la \ + $(NULL) +test-shutdown.sh: test-shutdown-plugin.la + +test_shutdown_plugin_la_SOURCES = \ + test-shutdown-plugin.c \ + $(top_srcdir)/include/nbdkit-plugin.h \ + $(NULL) +test_shutdown_plugin_la_CPPFLAGS = -I$(top_srcdir)/include +test_shutdown_plugin_la_CFLAGS = $(WARNINGS_CFLAGS) +# For use of the -rpath option, see: +# https://lists.gnu.org/archive/html/libtool/2007-07/msg00067.html +test_shutdown_plugin_la_LDFLAGS = \ + -module -avoid-version -shared -rpath /nowhere \ + $(NULL) + endif HAVE_PLUGINS # Test the header files can be included on their own. diff --git a/server/nbdkit.syms b/server/nbdkit.syms index 96c22c07..111223f2 100644 --- a/server/nbdkit.syms +++ b/server/nbdkit.syms @@ -1,5 +1,5 @@ # nbdkit -# Copyright (C) 2018 Red Hat Inc. +# Copyright (C) 2018-2020 Red Hat Inc. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -64,6 +64,7 @@ nbdkit_read_password; nbdkit_realpath; nbdkit_set_error; + nbdkit_shutdown; nbdkit_vdebug; nbdkit_verror; diff --git a/server/quit.c b/server/quit.c index bff8ac7c..13fef437 100644 --- a/server/quit.c +++ b/server/quit.c @@ -1,5 +1,5 @@ /* nbdkit - * Copyright (C) 2019 Red Hat Inc. + * Copyright (C) 2019-2020 Red Hat Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -104,3 +104,9 @@ handle_quit (int sig) { set_quit (); } + +void +nbdkit_shutdown (void) +{ + set_quit (); +} diff --git a/tests/test-shutdown.sh b/tests/test-shutdown.sh new file mode 100755 index 00000000..fa09dce9 --- /dev/null +++ b/tests/test-shutdown.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# nbdkit +# Copyright (C) 2019-2020 Red Hat Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +source ./functions.sh +set -x + +requires qemu-img --version +requires qemu-io --version + +plugin=.libs/test-shutdown-plugin.so +requires test -f $plugin + +sock=`mktemp -u` +files="shutdown.pid $sock" +cleanup_fn rm -f $files + +# Start nbdkit with the shutdown plugin. +start_nbdkit -P shutdown.pid -U $sock $plugin + +pid=`cat shutdown.pid` + +# Reads are fine, nbdkit should still be running afterwards. +for i in 1 2 3; do + qemu-img info "nbd:unix:$sock" + sleep 2 + kill -s 0 $pid +done + +# Writing should cause nbdkit to exit, although it may take time. +qemu-io -f raw -c 'w -P 0x55 0 1024' "nbd:unix:$sock" + +# Wait for nbdkit process to exit +for i in {1..60}; do + if ! kill -s 0 $pid; then + break + fi + sleep 1 +done +if kill -s 0 $pid; then + echo "$0: nbdkit $plugin did not exit as expected" + exit 1 +fi diff --git a/tests/test-shutdown-plugin.c b/tests/test-shutdown-plugin.c new file mode 100644 index 00000000..4ec98538 --- /dev/null +++ b/tests/test-shutdown-plugin.c @@ -0,0 +1,89 @@ +/* nbdkit + * Copyright (C) 2013-2020 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <nbdkit-plugin.h> + +static void +shutdown_unload (void) +{ + nbdkit_debug ("clean shutdown"); +} + +static void * +shutdown_open (int readonly) +{ + return NBDKIT_HANDLE_NOT_NEEDED; +} + +static int64_t +shutdown_get_size (void *handle) +{ + return INT64_C (1024*1024); +} + +#define THREAD_MODEL NBDKIT_THREAD_MODEL_PARALLEL + +static int +shutdown_pread (void *handle, void *buf, uint32_t count, uint64_t offset) +{ + memset (buf, 0, count); + return 0; +} + +/* Writing 0x55 to any location causes a shutdown. */ +static int +shutdown_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset) +{ + if (memchr (buf, 0x55, count) != NULL) { + nbdkit_debug ("shutdown triggered!"); + nbdkit_shutdown (); + } + return 0; +} + +static struct nbdkit_plugin plugin = { + .name = "shutdown", + .version = PACKAGE_VERSION, + .unload = shutdown_unload, + .open = shutdown_open, + .get_size = shutdown_get_size, + .pread = shutdown_pread, + .pwrite = shutdown_pwrite, +}; + +NBDKIT_REGISTER_PLUGIN(plugin) -- 2.25.0
Richard W.M. Jones
2020-Mar-04 15:17 UTC
[Libguestfs] [PATCH nbdkit 3/4] New filter: exitlast filter to exit on last client connection.
--- docs/nbdkit-service.pod | 1 + filters/exitlast/nbdkit-exitlast-filter.pod | 58 +++++++++++++++ filters/ip/nbdkit-ip-filter.pod | 1 + filters/rate/nbdkit-rate-filter.pod | 1 + configure.ac | 3 + filters/exitlast/Makefile.am | 60 ++++++++++++++++ tests/Makefile.am | 3 + filters/exitlast/exitlast.c | 80 +++++++++++++++++++++ tests/test-exitlast.sh | 66 +++++++++++++++++ TODO | 6 +- 10 files changed, 276 insertions(+), 3 deletions(-) diff --git a/docs/nbdkit-service.pod b/docs/nbdkit-service.pod index 44bc111f..ecc8e94b 100644 --- a/docs/nbdkit-service.pod +++ b/docs/nbdkit-service.pod @@ -143,6 +143,7 @@ L</SOCKET ACTIVATION>. =head1 SEE ALSO L<nbdkit(1)>, +L<nbdkit-exitlast-filter(1)>, L<nbdkit-ip-filter(1)>, L<systemd(1)>, L<systemd.socket(5)>, diff --git a/filters/exitlast/nbdkit-exitlast-filter.pod b/filters/exitlast/nbdkit-exitlast-filter.pod new file mode 100644 index 00000000..e0fbd6ea --- /dev/null +++ b/filters/exitlast/nbdkit-exitlast-filter.pod @@ -0,0 +1,58 @@ +=head1 NAME + +nbdkit-exitlast-filter - exit on last client connection + +=head1 SYNOPSIS + + nbdkit --filter=exitlast PLUGIN + +=head1 DESCRIPTION + +C<nbdkit-exitlast-filter> is an nbdkit filter that causes nbdkit to +exit when there are no more client connections. Note that it doesn't +exit before the first client connection. + +One use for this is in combination with a superserver, to save +resources when nbdkit is not in use (see L<nbdkit-service(1)>). +Another use is to ensure nbdkit exits after the client has finished +(but see also nbdkit-captive(1) for other ways to do this). + +=head1 PARAMETERS + +There are no parameters specific to nbdkit-exitlast-filter. Any +parameters are passed through to and processed by the underlying +plugin in the normal way. + +=head1 FILES + +=over 4 + +=item F<$filterdir/nbdkit-exitlast-filter.so> + +The filter. + +Use C<nbdkit --dump-config> to find the location of C<$filterdir>. + +=back + +=head1 VERSION + +C<nbdkit-exitlast-filter> first appeared in nbdkit 1.20. + +=head1 SEE ALSO + +L<nbdkit(1)>, +L<nbdkit-ip-filter(1)>, +L<nbdkit-rate-filter(1)>, +L<nbdkit-captive(1)>, +L<nbdkit-service(1)>, +L<nbdkit-filter(3)>, +L<nbdkit-plugin(3)>. + +=head1 AUTHORS + +Richard W.M. Jones + +=head1 COPYRIGHT + +Copyright (C) 2020 Red Hat Inc. diff --git a/filters/ip/nbdkit-ip-filter.pod b/filters/ip/nbdkit-ip-filter.pod index b91633c6..1621ebec 100644 --- a/filters/ip/nbdkit-ip-filter.pod +++ b/filters/ip/nbdkit-ip-filter.pod @@ -145,6 +145,7 @@ C<nbdkit-ip-filter> first appeared in nbdkit 1.18. =head1 SEE ALSO L<nbdkit(1)>, +L<nbdkit-exitlast-filter(1)>, L<nbdkit-filter(3)>. =head1 AUTHORS diff --git a/filters/rate/nbdkit-rate-filter.pod b/filters/rate/nbdkit-rate-filter.pod index e8bfa42b..acf7d8b0 100644 --- a/filters/rate/nbdkit-rate-filter.pod +++ b/filters/rate/nbdkit-rate-filter.pod @@ -129,6 +129,7 @@ C<nbdkit-rate-filter> first appeared in nbdkit 1.12. L<nbdkit(1)>, L<nbdkit-blocksize-filter(1)>, L<nbdkit-delay-filter(1)>, +L<nbdkit-exitlast-filter(1)>, L<nbdkit-filter(3)>, L<iptables(8)>, L<tc(8)>. diff --git a/configure.ac b/configure.ac index 0b7d8b7c..0b980238 100644 --- a/configure.ac +++ b/configure.ac @@ -97,6 +97,7 @@ filters="\ cow \ delay \ error \ + exitlast \ ext2 \ extentlist \ fua \ @@ -267,6 +268,7 @@ AC_CHECK_HEADERS([\ alloca.h \ byteswap.h \ endian.h \ + stdatomic.h \ sys/endian.h \ sys/mman.h \ sys/prctl.h \ @@ -1022,6 +1024,7 @@ AC_CONFIG_FILES([Makefile filters/cow/Makefile filters/delay/Makefile filters/error/Makefile + filters/exitlast/Makefile filters/ext2/Makefile filters/extentlist/Makefile filters/fua/Makefile diff --git a/filters/exitlast/Makefile.am b/filters/exitlast/Makefile.am new file mode 100644 index 00000000..690008f1 --- /dev/null +++ b/filters/exitlast/Makefile.am @@ -0,0 +1,60 @@ +# nbdkit +# Copyright (C) 2019-2020 Red Hat Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/common-rules.mk + +EXTRA_DIST = nbdkit-exitlast-filter.pod + +filter_LTLIBRARIES = nbdkit-exitlast-filter.la + +nbdkit_exitlast_filter_la_SOURCES = \ + exitlast.c \ + $(top_srcdir)/include/nbdkit-filter.h \ + $(NULL) + +nbdkit_exitlast_filter_la_CPPFLAGS = -I$(top_srcdir)/include +nbdkit_exitlast_filter_la_CFLAGS = $(WARNINGS_CFLAGS) +nbdkit_exitlast_filter_la_LDFLAGS = \ + -module -avoid-version -shared \ + -Wl,--version-script=$(top_srcdir)/filters/filters.syms \ + $(NULL) + +if HAVE_POD + +man_MANS = nbdkit-exitlast-filter.1 +CLEANFILES += $(man_MANS) + +nbdkit-exitlast-filter.1: nbdkit-exitlast-filter.pod + $(PODWRAPPER) --section=1 --man $@ \ + --html $(top_builddir)/html/$@.html \ + $< + +endif HAVE_POD diff --git a/tests/Makefile.am b/tests/Makefile.am index eb51757a..2ac8fb31 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1052,6 +1052,9 @@ TESTS += \ test-error-triggered.sh \ $(NULL) +# exitlast filter test. +TESTS += test-exitlast.sh + # extentlist filter test. TESTS += test-extentlist.sh diff --git a/filters/exitlast/exitlast.c b/filters/exitlast/exitlast.c new file mode 100644 index 00000000..51efda03 --- /dev/null +++ b/filters/exitlast/exitlast.c @@ -0,0 +1,80 @@ +/* nbdkit + * Copyright (C) 2019-2020 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> + +#include <nbdkit-filter.h> + +#ifdef HAVE_STDATOMIC_H +#include <stdatomic.h> +#else +/* Some old platforms lack atomic types, but 32 bit ints are usually + * "atomic enough". + */ +#define _Atomic /**/ +#endif + +/* Counts client connections. When this drops to zero we exit. */ +static _Atomic unsigned connections; + +static void * +exitlast_open (nbdkit_next_open *next, nbdkit_backend *nxdata, + int readonly) +{ + if (next (nxdata, readonly) == -1) + return NULL; + + connections++; + + return NBDKIT_HANDLE_NOT_NEEDED; +} + +static void +exitlast_close (void *handle) +{ + if (--connections == 0) { + nbdkit_debug ("exitlast: exiting on last client connection"); + nbdkit_shutdown (); + } +} + +static struct nbdkit_filter filter = { + .name = "exitlast", + .longname = "nbdkit exitlast filter", + .open = exitlast_open, + .close = exitlast_close, +}; + +NBDKIT_REGISTER_FILTER(filter) diff --git a/tests/test-exitlast.sh b/tests/test-exitlast.sh new file mode 100755 index 00000000..d24a177f --- /dev/null +++ b/tests/test-exitlast.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# nbdkit +# Copyright (C) 2019-2020 Red Hat Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +source ./functions.sh +set -x + +requires qemu-img --version + +sock=`mktemp -u` +files="exitlast.pid $sock" +cleanup_fn rm -f $files + +# Start nbdkit with the exitlast filter. +start_nbdkit -P exitlast.pid -U $sock --filter=exitlast memory size=1M + +pid=`cat exitlast.pid` + +# nbdkit should start up even though there are no client connections. +if ! kill -s 0 $pid; then + echo "$0: nbdkit exited before first connection" + exit 1 +fi + +# Connect with a client. +qemu-img info "nbd:unix:$sock" || exit 1 + +# Now nbdkit should exit. Wait for it to do so. +for i in {1..60}; do + if ! kill -s 0 $pid; then + break + fi + sleep 1 +done +if kill -s 0 $pid; then + echo "$0: nbdkit did not exit after last client connection" + exit 1 +fi diff --git a/TODO b/TODO index 21cbfe5b..cd2e47a5 100644 --- a/TODO +++ b/TODO @@ -10,9 +10,6 @@ General ideas for improvements sizes and threads, as that should make it easier to identify systematic issues. -* Exit on last connection (the default behaviour of qemu-nbd unless - you use -t). - * Limit number of incoming connections (like qemu-nbd -e). * For parallel plugins, only create threads on demand from parallel @@ -173,6 +170,9 @@ Suggestions for filters MBs of extra data) https://github.com/facebook/zstd/issues/395#issuecomment-535875379 +* nbdkit-exitlast-filter could probably use a configurable timeout so + that it hangs around in case another connection comes along quickly. + nbdkit-rate-filter: * allow other kinds of traffic shaping such as VBR -- 2.25.0
Richard W.M. Jones
2020-Mar-04 15:17 UTC
[Libguestfs] [PATCH nbdkit 4/4] New filter: limit: Limit number of clients that can connect.
--- filters/limit/nbdkit-limit-filter.pod | 61 ++++++++++++++ configure.ac | 2 + filters/limit/Makefile.am | 60 ++++++++++++++ tests/Makefile.am | 3 + filters/limit/limit.c | 115 ++++++++++++++++++++++++++ tests/test-limit.sh | 81 ++++++++++++++++++ TODO | 2 - 7 files changed, 322 insertions(+), 2 deletions(-) diff --git a/filters/limit/nbdkit-limit-filter.pod b/filters/limit/nbdkit-limit-filter.pod new file mode 100644 index 00000000..e334decb --- /dev/null +++ b/filters/limit/nbdkit-limit-filter.pod @@ -0,0 +1,61 @@ +=head1 NAME + +nbdkit-limit-filter - limit number of clients that can connect + +=head1 SYNOPSIS + + nbdkit --filter=limit PLUGIN [limit=N] + +=head1 DESCRIPTION + +C<nbdkit-limit-filter> is an nbdkit filter that limits the number of +clients which can connect concurrently. If more than C<limit=N> +(default: 1) clients try to connect at the same time then later +clients are rejected. + +=head1 PARAMETERS + +=over 4 + +=item B<limit=>N + +Limit the number of concurrent clients to C<N>. This parameter is +optional. If not specified then the limit defaults to 1. You can +also set this to 0 to make the number of clients unlimited (ie. +disable the filter). + +=back + +=head1 FILES + +=over 4 + +=item F<$filterdir/nbdkit-limit-filter.so> + +The filter. + +Use C<nbdkit --dump-config> to find the location of C<$filterdir>. + +=back + +=head1 VERSION + +C<nbdkit-limit-filter> first appeared in nbdkit 1.20. + +=head1 SEE ALSO + +L<nbdkit(1)>, +L<nbdkit-exitlast-filter(1)>, +L<nbdkit-ip-filter(1)>, +L<nbdkit-noparallel-filter(1)>, +L<nbdkit-rate-filter(1)>, +L<nbdkit-filter(3)>, +L<nbdkit-plugin(3)>. + +=head1 AUTHORS + +Richard W.M. Jones + +=head1 COPYRIGHT + +Copyright (C) 2020 Red Hat Inc. diff --git a/configure.ac b/configure.ac index 0b980238..2db4b546 100644 --- a/configure.ac +++ b/configure.ac @@ -102,6 +102,7 @@ filters="\ extentlist \ fua \ ip \ + limit \ log \ nocache \ noextents \ @@ -1029,6 +1030,7 @@ AC_CONFIG_FILES([Makefile filters/extentlist/Makefile filters/fua/Makefile filters/ip/Makefile + filters/limit/Makefile filters/log/Makefile filters/nocache/Makefile filters/noextents/Makefile diff --git a/filters/limit/Makefile.am b/filters/limit/Makefile.am new file mode 100644 index 00000000..75704082 --- /dev/null +++ b/filters/limit/Makefile.am @@ -0,0 +1,60 @@ +# nbdkit +# Copyright (C) 2019-2020 Red Hat Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/common-rules.mk + +EXTRA_DIST = nbdkit-limit-filter.pod + +filter_LTLIBRARIES = nbdkit-limit-filter.la + +nbdkit_limit_filter_la_SOURCES = \ + limit.c \ + $(top_srcdir)/include/nbdkit-filter.h \ + $(NULL) + +nbdkit_limit_filter_la_CPPFLAGS = -I$(top_srcdir)/include +nbdkit_limit_filter_la_CFLAGS = $(WARNINGS_CFLAGS) +nbdkit_limit_filter_la_LDFLAGS = \ + -module -avoid-version -shared \ + -Wl,--version-script=$(top_srcdir)/filters/filters.syms \ + $(NULL) + +if HAVE_POD + +man_MANS = nbdkit-limit-filter.1 +CLEANFILES += $(man_MANS) + +nbdkit-limit-filter.1: nbdkit-limit-filter.pod + $(PODWRAPPER) --section=1 --man $@ \ + --html $(top_builddir)/html/$@.html \ + $< + +endif HAVE_POD diff --git a/tests/Makefile.am b/tests/Makefile.am index 2ac8fb31..324339c1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1064,6 +1064,9 @@ TESTS += test-fua.sh # ip filter test. TESTS += test-ip-filter.sh +# limit filter test. +TESTS += test-limit.sh + # log filter test. TESTS += test-log.sh diff --git a/filters/limit/limit.c b/filters/limit/limit.c new file mode 100644 index 00000000..c7308e9c --- /dev/null +++ b/filters/limit/limit.c @@ -0,0 +1,115 @@ +/* nbdkit + * Copyright (C) 2019-2020 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <nbdkit-filter.h> + +#ifdef HAVE_STDATOMIC_H +#include <stdatomic.h> +#else +/* Some old platforms lack atomic types, but 32 bit ints are usually + * "atomic enough". + */ +#define _Atomic /**/ +#endif + +/* Counts client connections. */ +static _Atomic unsigned connections; + +/* Client limit (0 = filter is disabled). */ +static unsigned limit = 1; + +static int +limit_config (nbdkit_next_config *next, nbdkit_backend *nxdata, + const char *key, const char *value) +{ + if (strcmp (key, "limit") == 0) { + if (nbdkit_parse_unsigned ("limit", value, &limit) == -1) + return -1; + return 0; + } + + return next (nxdata, key, value); +} + +/* We limit connections in the preconnect stage (in particular before + * any heavyweight NBD or TLS negotiations has been done). However we + * count connections in the open/close calls since clients can drop + * out between preconnect and open. + */ +static int +limit_preconnect (nbdkit_next_preconnect *next, nbdkit_backend *nxdata, + int readonly) +{ + if (next (nxdata, readonly) == -1) + return -1; + + if (limit == 0 || connections < limit) + return 0; + + nbdkit_error ("limit: too many clients connected, connection rejected"); + return -1; +} + +static void * +limit_open (nbdkit_next_open *next, nbdkit_backend *nxdata, + int readonly) +{ + if (next (nxdata, readonly) == -1) + return NULL; + + connections++; + + return NBDKIT_HANDLE_NOT_NEEDED; +} + +static void +limit_close (void *handle) +{ + --connections; +} + +static struct nbdkit_filter filter = { + .name = "limit", + .longname = "nbdkit limit filter", + .config = limit_config, + .preconnect = limit_preconnect, + .open = limit_open, + .close = limit_close, +}; + +NBDKIT_REGISTER_FILTER(filter) diff --git a/tests/test-limit.sh b/tests/test-limit.sh new file mode 100755 index 00000000..aa7c2b19 --- /dev/null +++ b/tests/test-limit.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# nbdkit +# Copyright (C) 2019-2020 Red Hat Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +source ./functions.sh +set -e +set -x + +requires nbdsh --version + +sock=`mktemp -u` +files="limit.pid $sock" +cleanup_fn rm -f $files + +# Start nbdkit with the limit filter and a limit of 2 clients. +start_nbdkit -P limit.pid -U $sock --filter=limit memory size=1M limit=2 + +export sock + +nbdsh -c - <<'EOF' +import os +import sys +import time + +sock = os.environ["sock"] + +# It should be possible to connect two clients. +# Note that nbdsh creates the ‘h’ handle implicitly. +h.connect_unix (sock) +h2 = nbd.NBD () +h2.connect_unix (sock) + +# A third connection is expected to fail. +try: + h3 = nbd.NBD () + h3.connect_unix (sock) + # This should not happen. + sys.exit (1) +except nbd.Error: + pass + +# Close one of the existing connections. +del h2 + +# There's a possible race between closing the client socket +# and nbdkit noticing and closing the connection. +time.sleep (5) + +# Now a new connection should be possible. +h4 = nbd.NBD () +h4.connect_unix (sock) + +EOF diff --git a/TODO b/TODO index cd2e47a5..e094c332 100644 --- a/TODO +++ b/TODO @@ -10,8 +10,6 @@ General ideas for improvements sizes and threads, as that should make it easier to identify systematic issues. -* Limit number of incoming connections (like qemu-nbd -e). - * For parallel plugins, only create threads on demand from parallel client requests, rather than pre-creating all threads at connection time, up to the thread pool size limit. Of course, once created, a -- 2.25.0
Eric Blake
2020-Mar-06 22:26 UTC
Re: [Libguestfs] [PATCH nbdkit 1/4] tests: Rename test-shutdown.sh to test-delay-shutdown.sh.
On 3/4/20 9:17 AM, Richard W.M. Jones wrote:> This is testing the delay filter, and we want to use the name > ‘test-shutdown’ in a later commit to test the new nbdkit_shutdown() > API, so let’s rename it. > --- > tests/Makefile.am | 4 ++-- > tests/{test-shutdown.sh => test-delay-shutdown.sh} | 4 ++-- > 2 files changed, 4 insertions(+), 4 deletions(-)ACK -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
Eric Blake
2020-Mar-06 22:36 UTC
Re: [Libguestfs] [PATCH nbdkit 2/4] server: Add nbdkit_shutdown() call.
On 3/4/20 9:17 AM, Richard W.M. Jones wrote:> Plugins and filters may call this to initiate an asynchronous shutdown > of the server. This would only be used in the connected phase — > plugins should still call exit(3) directly for configuration failure. > > It is equivalent to sending a kill signal to self, but it's cleaner to > have an API for this and better for potential future non-POSIX platforms. > --- > docs/nbdkit-plugin.pod | 19 +++++++- > include/nbdkit-common.h | 1 + > include/nbdkit-plugin.h | 2 +- > tests/Makefile.am | 20 ++++++++ > server/nbdkit.syms | 3 +- > server/quit.c | 8 +++- > tests/test-shutdown.sh | 71 ++++++++++++++++++++++++++++ > tests/test-shutdown-plugin.c | 89 ++++++++++++++++++++++++++++++++++++ > 8 files changed, 209 insertions(+), 4 deletions(-) >> +++ b/tests/test-shutdown.sh> +# Start nbdkit with the shutdown plugin. > +start_nbdkit -P shutdown.pid -U $sock $plugin > + > +pid=`cat shutdown.pid` > + > +# Reads are fine, nbdkit should still be running afterwards. > +for i in 1 2 3; do > + qemu-img info "nbd:unix:$sock"qemu-img should support nbd+unix:///?socket=$sock URIs; any reason we aren't using them here?> +++ b/tests/test-shutdown-plugin.c > + > +static int64_t > +shutdown_get_size (void *handle) > +{ > + return INT64_C (1024*1024);This looks fishy. POSIX says that: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdint.h.html#tag_13_48 "The argument in any instance of these macros shall be an unsuffixed integer constant with a value that does not exceed the limits for the corresponding type. ...For example, if uint_least64_t is a name for the type unsigned long long, then UINT64_C(0x123) might expand to the integer constant 0x123ULL." In fact, in glibc's /usr/include/stdint.h, we have: # if __WORDSIZE == 64 # define INT64_C(c) c ## L # else # define INT64_C(c) c ## LL # endif Your code works by sheer luck (expanding to the three tokens '1024', '*', '1024L'), which in turn results in an expression with 64-bit type, but in general, INT64_C should ONLY be used on a single literal value, not an arbitrary expression. But you really don't need to use INT64_C; we can just rely on C's automatic type promotion to turn our 'int' expression 1024*1024 into the proper int64_t return value. Otherwise, this is a nice addition! -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
Eric Blake
2020-Mar-06 22:42 UTC
Re: [Libguestfs] [PATCH nbdkit 3/4] New filter: exitlast filter to exit on last client connection.
On 3/4/20 9:17 AM, Richard W.M. Jones wrote:> --- > docs/nbdkit-service.pod | 1 + > filters/exitlast/nbdkit-exitlast-filter.pod | 58 +++++++++++++++ > filters/ip/nbdkit-ip-filter.pod | 1 + > filters/rate/nbdkit-rate-filter.pod | 1 + > configure.ac | 3 + > filters/exitlast/Makefile.am | 60 ++++++++++++++++ > tests/Makefile.am | 3 + > filters/exitlast/exitlast.c | 80 +++++++++++++++++++++ > tests/test-exitlast.sh | 66 +++++++++++++++++ > TODO | 6 +- > 10 files changed, 276 insertions(+), 3 deletions(-)I'd expect docs/nbdkit-captive.pod to also gain a link to the new filter...> +++ b/filters/exitlast/nbdkit-exitlast-filter.pod > @@ -0,0 +1,58 @@ > +=head1 NAME > + > +nbdkit-exitlast-filter - exit on last client connection > + > +=head1 SYNOPSIS > + > + nbdkit --filter=exitlast PLUGIN > + > +=head1 DESCRIPTION > + > +C<nbdkit-exitlast-filter> is an nbdkit filter that causes nbdkit to > +exit when there are no more client connections. Note that it doesn't > +exit before the first client connection. > + > +One use for this is in combination with a superserver, to save > +resources when nbdkit is not in use (see L<nbdkit-service(1)>). > +Another use is to ensure nbdkit exits after the client has finished > +(but see also nbdkit-captive(1) for other ways to do this)....as a counterpart to this one.> +++ b/filters/exitlast/exitlast.c> + > +/* Counts client connections. When this drops to zero we exit. */ > +static _Atomic unsigned connections; > + > +static void * > +exitlast_open (nbdkit_next_open *next, nbdkit_backend *nxdata, > + int readonly) > +{ > + if (next (nxdata, readonly) == -1) > + return NULL; > + > + connections++; > + > + return NBDKIT_HANDLE_NOT_NEEDED; > +} > + > +static void > +exitlast_close (void *handle) > +{ > + if (--connections == 0) { > + nbdkit_debug ("exitlast: exiting on last client connection"); > + nbdkit_shutdown (); > + } > +}I suppose there's a minor race where we can close one connection just as another tries to connect, where we may actually start servicing the new connection, but the request for shutdown will eventually end that new connection fairly rapidly. Still, this is a nice way to implement one-shot servers.> +++ b/TODO > @@ -10,9 +10,6 @@ General ideas for improvements > sizes and threads, as that should make it easier to identify > systematic issues. > > -* Exit on last connection (the default behaviour of qemu-nbd unless > - you use -t). > -And it's pretty slick that you added it via a filter rather than a new command line option.> * Limit number of incoming connections (like qemu-nbd -e). > > * For parallel plugins, only create threads on demand from parallel > @@ -173,6 +170,9 @@ Suggestions for filters > MBs of extra data) > https://github.com/facebook/zstd/issues/395#issuecomment-535875379 > > +* nbdkit-exitlast-filter could probably use a configurable timeout so > + that it hangs around in case another connection comes along quickly. > + > nbdkit-rate-filter: > > * allow other kinds of traffic shaping such as VBR >Overall, I like the patch. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
Reasonably Related Threads
- [PATCH nbdkit 0/4] server: Add nbdkit_shutdown() call and two new filters.
- [PATCH nbdkit 5/9 patch split 5/5] server: Indirect slow path, non-self-contained functions through the server.
- Re: [PATCH nbdkit 2/4] server: Add nbdkit_shutdown() call.
- [nbdkit PATCH v2 1/3] server: Add nbdkit_stdio_safe
- [nbdkit PATCH 1/2] server: Add nbdkit_stdio_safe