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