2021-08-19 07:53:56 +00:00
|
|
|
From be7252bada79ee542356dffaf5f3c568a5c7fec3 Mon Sep 17 00:00:00 2001
|
2021-08-10 15:09:59 +00:00
|
|
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
|
|
Date: Tue, 10 Aug 2021 08:39:15 +0100
|
|
|
|
Subject: [PATCH] delay: Fix delay-close
|
|
|
|
|
|
|
|
See comments in the code for how this has been fixed.
|
|
|
|
|
|
|
|
This only delays clients which use NBD_CMD_DISC (libnbd
|
|
|
|
nbd_shutdown(3)). Clients which drop the connection obviously cannot
|
|
|
|
be delayed. For example:
|
|
|
|
|
|
|
|
$ nbdkit --filter=delay null delay-close=3 \
|
|
|
|
--run 'time nbdsh -u $uri -c "h.shutdown()"
|
|
|
|
time nbdsh -u $uri -c "pass"'
|
|
|
|
|
|
|
|
real 0m3.061s # Client used shutdown, was delayed
|
|
|
|
user 0m0.028s
|
|
|
|
sys 0m0.030s
|
|
|
|
|
|
|
|
real 0m0.058s # Client disconnected, was not delayed
|
|
|
|
user 0m0.029s
|
|
|
|
sys 0m0.027s
|
|
|
|
|
|
|
|
Reported-by: Ming Xie
|
|
|
|
Fixes: commit de8dcd3a34a38b088a0f9a6f8ca754702ad1f598
|
|
|
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1991652
|
|
|
|
(cherry picked from commit 0cafebdb67d0d557ba1be8ea306b8acc5d9b2203)
|
|
|
|
---
|
|
|
|
filters/delay/delay.c | 42 +++++++++++++++++++--------
|
|
|
|
filters/delay/nbdkit-delay-filter.pod | 14 +++++++--
|
|
|
|
2 files changed, 41 insertions(+), 15 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/filters/delay/delay.c b/filters/delay/delay.c
|
|
|
|
index df3729a7..9252b855 100644
|
|
|
|
--- a/filters/delay/delay.c
|
|
|
|
+++ b/filters/delay/delay.c
|
|
|
|
@@ -39,6 +39,7 @@
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <limits.h>
|
|
|
|
+#include <time.h>
|
|
|
|
|
|
|
|
#include <nbdkit-filter.h>
|
|
|
|
|
|
|
|
@@ -134,12 +135,6 @@ open_delay (int *err)
|
|
|
|
return delay (delay_open_ms, err);
|
|
|
|
}
|
|
|
|
|
|
|
|
-static int
|
|
|
|
-close_delay (int *err)
|
|
|
|
-{
|
|
|
|
- return delay (delay_close_ms, err);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/* Called for each key=value passed on the command line. */
|
|
|
|
static int
|
|
|
|
delay_config (nbdkit_next_config *next, nbdkit_backend *nxdata,
|
|
|
|
@@ -253,13 +248,36 @@ delay_open (nbdkit_next_open *next, nbdkit_context *nxdata,
|
|
|
|
return NBDKIT_HANDLE_NOT_NEEDED;
|
|
|
|
}
|
|
|
|
|
|
|
|
-/* Close connection. */
|
|
|
|
-static void
|
|
|
|
-delay_close (void *handle)
|
|
|
|
+/* Close connection.
|
|
|
|
+ *
|
|
|
|
+ * We cannot call nbdkit_nanosleep here because the socket may have
|
|
|
|
+ * been closed and that function will abort and return immediately.
|
|
|
|
+ * However we want to force a sleep (even if the server is shutting
|
|
|
|
+ * down) so use regular nanosleep instead.
|
|
|
|
+ *
|
|
|
|
+ * We cannot use the .close callback because that happens after the
|
|
|
|
+ * socket has closed, thus not delaying the client. By using
|
|
|
|
+ * .finalize we can delay well-behaved clients (those that use
|
|
|
|
+ * NBD_CMD_DISC). We cannot delay clients that drop the connection.
|
|
|
|
+ */
|
|
|
|
+static int
|
|
|
|
+delay_finalize (nbdkit_next *next, void *handle)
|
|
|
|
{
|
|
|
|
- int err;
|
|
|
|
+ const unsigned ms = delay_close_ms;
|
|
|
|
|
|
|
|
- close_delay (&err);
|
|
|
|
+ if (ms > 0) {
|
|
|
|
+ struct timespec ts;
|
|
|
|
+
|
|
|
|
+ ts.tv_sec = ms / 1000;
|
|
|
|
+ ts.tv_nsec = (ms % 1000) * 1000000;
|
|
|
|
+ /* If nanosleep fails we don't really want to interrupt the chain
|
|
|
|
+ * of finalize calls through the other filters, so ignore any
|
|
|
|
+ * error here.
|
|
|
|
+ */
|
|
|
|
+ nanosleep (&ts, NULL);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return next->finalize (next);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read data. */
|
|
|
|
@@ -340,7 +358,7 @@ static struct nbdkit_filter filter = {
|
|
|
|
.config_help = delay_config_help,
|
|
|
|
.can_fast_zero = delay_can_fast_zero,
|
|
|
|
.open = delay_open,
|
|
|
|
- .close = delay_close,
|
|
|
|
+ .finalize = delay_finalize,
|
|
|
|
.pread = delay_pread,
|
|
|
|
.pwrite = delay_pwrite,
|
|
|
|
.zero = delay_zero,
|
|
|
|
diff --git a/filters/delay/nbdkit-delay-filter.pod b/filters/delay/nbdkit-delay-filter.pod
|
|
|
|
index 11ae544b..76614736 100644
|
|
|
|
--- a/filters/delay/nbdkit-delay-filter.pod
|
|
|
|
+++ b/filters/delay/nbdkit-delay-filter.pod
|
|
|
|
@@ -117,15 +117,23 @@ the plugin.
|
|
|
|
|
|
|
|
=item B<delay-open=>NNB<ms>
|
|
|
|
|
|
|
|
+(nbdkit E<ge> 1.28)
|
|
|
|
+
|
|
|
|
+Delay open (client connection) by C<SECS> seconds or C<NN>
|
|
|
|
+milliseconds.
|
|
|
|
+
|
|
|
|
=item B<delay-close=>SECS
|
|
|
|
|
|
|
|
=item B<delay-close=>NNB<ms>
|
|
|
|
|
|
|
|
(nbdkit E<ge> 1.28)
|
|
|
|
|
|
|
|
-Delay open and close operations by C<SECS> seconds or C<NN>
|
|
|
|
-milliseconds. Open corresponds to client connection. Close may not
|
|
|
|
-be visible to clients if they abruptly disconnect.
|
|
|
|
+Delay close (client disconnection) by C<SECS> seconds or C<NN>
|
|
|
|
+milliseconds. This can also cause server shutdown to be delayed if
|
|
|
|
+clients are connected at the time. This only affects clients that
|
|
|
|
+gracefully disconnect (using C<NBD_CMD_DISC> / libnbd function
|
|
|
|
+L<nbd_shutdown(3)>). Clients that abruptly disconnect from the server
|
|
|
|
+cannot be delayed.
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
--
|
|
|
|
2.31.1
|
|
|
|
|