[Libguestfs] [nbdkit PATCH 1/3] server: Add threadlocal_get_conn

Eric Blake eblake at redhat.com
Sat Aug 3 16:01:42 UTC 2019


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




More information about the Libguestfs mailing list