We'd like to interrupt a sleep during a filter/plugin transaction if
it is obvious that finishing the transaction is pointless (because the
client has delivered NBD_CMD_DISC or hit EOF). But to do that, we
need to get back at the connection object from a function called from
the plugin thread. Passing the connection as an opaque object would
be a major API change, so it's easier to just add a thread-local
tracking the current connection.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
server/internal.h | 2 ++
server/connections.c | 4 ++++
server/threadlocal.c | 22 +++++++++++++++++++++-
3 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/server/internal.h b/server/internal.h
index 76f2139f..df4df0f2 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -342,6 +342,8 @@ extern void threadlocal_set_sockaddr (const struct sockaddr *addr,
extern void threadlocal_set_error (int err);
extern int threadlocal_get_error (void);
extern void *threadlocal_buffer (size_t size);
+extern void threadlocal_set_conn (struct connection *conn);
+extern struct connection *threadlocal_get_conn (void);
/* Declare program_name. */
#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME == 1
diff --git a/server/connections.c b/server/connections.c
index f56590c2..f49a74ee 100644
--- a/server/connections.c
+++ b/server/connections.c
@@ -137,6 +137,7 @@ connection_worker (void *data)
debug ("starting worker thread %s", name);
threadlocal_new_server_thread ();
threadlocal_set_name (name);
+ threadlocal_set_conn (conn);
free (worker);
while (!quit && connection_get_status (conn) > 0)
@@ -297,6 +298,8 @@ new_connection (int sockin, int sockout, int nworkers)
conn->send = raw_send_other;
conn->close = raw_close;
+ threadlocal_set_conn (conn);
+
return conn;
}
@@ -306,6 +309,7 @@ free_connection (struct connection *conn)
if (!conn)
return;
+ threadlocal_set_conn (NULL);
conn->close (conn);
/* Don't call the plugin again if quit has been set because the main
diff --git a/server/threadlocal.c b/server/threadlocal.c
index 49ae1ac2..a796fce8 100644
--- a/server/threadlocal.c
+++ b/server/threadlocal.c
@@ -1,5 +1,5 @@
/* nbdkit
- * Copyright (C) 2013-2018 Red Hat Inc.
+ * Copyright (C) 2013-2019 Red Hat Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -60,6 +60,7 @@ struct threadlocal {
int err;
void *buffer;
size_t buffer_size;
+ struct connection *conn;
};
static pthread_key_t threadlocal_key;
@@ -226,3 +227,22 @@ threadlocal_buffer (size_t size)
return threadlocal->buffer;
}
+
+/* Set (or clear) the connection that is using the current thread */
+void
+threadlocal_set_conn (struct connection *conn)
+{
+ struct threadlocal *threadlocal = pthread_getspecific (threadlocal_key);
+
+ if (threadlocal)
+ threadlocal->conn = conn;
+}
+
+/* Get the connection associated with this thread, if available */
+struct connection *
+threadlocal_get_conn (void)
+{
+ struct threadlocal *threadlocal = pthread_getspecific (threadlocal_key);
+
+ return threadlocal ? threadlocal->conn : NULL;
+}
--
2.20.1