[Libguestfs] [PATCH nbdkit 3/4] New filter: exitlast filter to exit on last client connection.

Richard W.M. Jones rjones at redhat.com
Wed Mar 4 15:17:25 UTC 2020


---
 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




More information about the Libguestfs mailing list