[Libguestfs] [PATCH nbdkit 4/4] New filter: limit: Limit number of clients that can connect.

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


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




More information about the Libguestfs mailing list