[Libguestfs] [PATCH 5/9] connections: Allow multiple handles to be stored in the connection object.

Richard W.M. Jones
Wed, 17 Jan 2018 20:53:52 -0000

Previously only one handle could be stored, but we will need to store
multiple handles when we have filters.

The plugin handle is defined as index 0.  Filters will use indices > 0.
---
 src/connections.c | 37 ++++++++++++++++++++++++++++++-------
 src/internal.h    |  4 ++--
 src/plugins.c     | 53 +++++++++++++++++++++++++++--------------------------
 3 files changed, 59 insertions(+), 35 deletions(-)

diff --git a/src/connections.c b/src/connections.c
index e1ac543..51a9772 100644
--- a/src/connections.c
+++ b/src/connections.c
@@ -69,10 +69,12 @@ struct connection {
   pthread_mutex_t write_lock;
   pthread_mutex_t status_lock;
   int status; /* 1 for more I/O with client, 0 for shutdown, -1 on error */
-  void *handle;
   void *crypto_session;
   int nworkers;

+  void **handles;
+  size_t nr_handles;
+
   uint64_t exportsize;
   int readonly;
   int can_flush;
@@ -100,16 +102,37 @@ static void raw_close (struct connection *);
 /* Accessors for public fields in the connection structure.
  * Everything else is private to this file.
  */
-void
-connection_set_handle (struct connection *conn, void *handle)
+int
+connection_set_handle (struct connection *conn, size_t i, void *handle)
 {
-  conn->handle = handle;
+  size_t j;
+
+  if (i < conn->nr_handles)
+    conn->handles[i] = handle;
+  else {
+    j = conn->nr_handles;
+    conn->nr_handles = i+1;
+    conn->handles = realloc (conn->handles,
+                             conn->nr_handles * sizeof (void *));
+    if (conn->handles == NULL) {
+      perror ("realloc");
+      conn->nr_handles = 0;
+      return -1;
+    }
+    for (; j < i; ++j)
+      conn->handles[j] = NULL;
+    conn->handles[i] = handle;
+  }
+  return 0;
 }

 void *
-connection_get_handle (struct connection *conn)
+connection_get_handle (struct connection *conn, size_t i)
 {
-  return conn->handle;
+  if (i < conn->nr_handles)
+    return conn->handles[i];
+  else
+    return NULL;
 }

 pthread_mutex_t *
@@ -341,7 +364,7 @@ free_connection (struct connection *conn)
    * callback should always be called.
    */
   if (!quit) {
-    if (conn->handle)
+    if (conn->nr_handles > 0 && conn->handles[0])
       backend->close (backend, conn);
   }

diff --git a/src/internal.h b/src/internal.h
index dc26665..5a68d59 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -131,8 +131,8 @@ typedef int (*connection_recv_function) (struct connection
*, void *buf, size_t
 typedef int (*connection_send_function) (struct connection *, const void *buf,
size_t len);
 typedef void (*connection_close_function) (struct connection *);
 extern int handle_single_connection (int sockin, int sockout);
-extern void connection_set_handle (struct connection *conn, void *handle);
-extern void *connection_get_handle (struct connection *conn);
+extern int connection_set_handle (struct connection *conn, size_t i, void
*handle);
+extern void *connection_get_handle (struct connection *conn, size_t i);
 extern pthread_mutex_t *connection_get_request_lock (struct connection *conn);
 extern void connection_set_crypto_session (struct connection *conn, void
*session);
 extern void *connection_get_crypto_session (struct connection *conn);
diff --git a/src/plugins.c b/src/plugins.c
index f0fe864..e732587 100644
--- a/src/plugins.c
+++ b/src/plugins.c
@@ -238,7 +238,7 @@ plugin_open (struct backend *b, struct connection *conn, int
readonly)
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
   void *handle;

-  assert (connection_get_handle (conn) == NULL);
+  assert (connection_get_handle (conn, 0) == NULL);
   assert (p->plugin.open != NULL);

   debug ("%s: open readonly=%d", p->filename, readonly);
@@ -247,7 +247,7 @@ plugin_open (struct backend *b, struct connection *conn, int
readonly)
   if (!handle)
     return -1;

-  connection_set_handle (conn, handle);
+  connection_set_handle (conn, 0, handle);
   return 0;
 }

@@ -256,14 +256,14 @@ plugin_close (struct backend *b, struct connection *conn)
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));

   debug ("close");

   if (p->plugin.close)
-    p->plugin.close (connection_get_handle (conn));
+    p->plugin.close (connection_get_handle (conn, 0));

-  connection_set_handle (conn, NULL);
+  connection_set_handle (conn, 0, NULL);
 }

 static int64_t
@@ -271,12 +271,12 @@ plugin_get_size (struct backend *b, struct connection
*conn)
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));
   assert (p->plugin.get_size != NULL);

   debug ("get_size");

-  return p->plugin.get_size (connection_get_handle (conn));
+  return p->plugin.get_size (connection_get_handle (conn, 0));
 }

 static int
@@ -284,12 +284,12 @@ plugin_can_write (struct backend *b, struct connection
*conn)
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));

   debug ("can_write");

   if (p->plugin.can_write)
-    return p->plugin.can_write (connection_get_handle (conn));
+    return p->plugin.can_write (connection_get_handle (conn, 0));
   else
     return p->plugin.pwrite != NULL;
 }
@@ -299,12 +299,12 @@ plugin_can_flush (struct backend *b, struct connection
*conn)
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));

   debug ("can_flush");

   if (p->plugin.can_flush)
-    return p->plugin.can_flush (connection_get_handle (conn));
+    return p->plugin.can_flush (connection_get_handle (conn, 0));
   else
     return p->plugin.flush != NULL;
 }
@@ -314,12 +314,12 @@ plugin_is_rotational (struct backend *b, struct connection
*conn)
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));

   debug ("is_rotational");

   if (p->plugin.is_rotational)
-    return p->plugin.is_rotational (connection_get_handle (conn));
+    return p->plugin.is_rotational (connection_get_handle (conn, 0));
   else
     return 0; /* assume false */
 }
@@ -329,12 +329,12 @@ plugin_can_trim (struct backend *b, struct connection
*conn)
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));

   debug ("can_trim");

   if (p->plugin.can_trim)
-    return p->plugin.can_trim (connection_get_handle (conn));
+    return p->plugin.can_trim (connection_get_handle (conn, 0));
   else
     return p->plugin.trim != NULL;
 }
@@ -345,12 +345,12 @@ plugin_pread (struct backend *b, struct connection *conn,
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));
   assert (p->plugin.pread != NULL);

   debug ("pread count=%" PRIu32 " offset=%" PRIu64, count,
offset);

-  return p->plugin.pread (connection_get_handle (conn), buf, count, offset);
+  return p->plugin.pread (connection_get_handle (conn, 0), buf, count,
offset);
 }

 static int
@@ -359,12 +359,13 @@ plugin_pwrite (struct backend *b, struct connection *conn,
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));

   debug ("pwrite count=%" PRIu32 " offset=%" PRIu64, count,
offset);

   if (p->plugin.pwrite != NULL)
-    return p->plugin.pwrite (connection_get_handle (conn), buf, count,
offset);
+    return p->plugin.pwrite (connection_get_handle (conn, 0),
+                             buf, count, offset);
   else {
     errno = EROFS;
     return -1;
@@ -376,12 +377,12 @@ plugin_flush (struct backend *b, struct connection *conn)
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));

   debug ("flush");

   if (p->plugin.flush != NULL)
-    return p->plugin.flush (connection_get_handle (conn));
+    return p->plugin.flush (connection_get_handle (conn, 0));
   else {
     errno = EINVAL;
     return -1;
@@ -394,12 +395,12 @@ plugin_trim (struct backend *b, struct connection *conn,
 {
   struct backend_plugin *p = container_of (b, struct backend_plugin, backend);

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));

   debug ("trim count=%" PRIu32 " offset=%" PRIu64, count,
offset);

   if (p->plugin.trim != NULL)
-    return p->plugin.trim (connection_get_handle (conn), count, offset);
+    return p->plugin.trim (connection_get_handle (conn, 0), count, offset);
   else {
     errno = EINVAL;
     return -1;
@@ -416,7 +417,7 @@ plugin_zero (struct backend *b, struct connection *conn,
   int result;
   int err = 0;

-  assert (connection_get_handle (conn));
+  assert (connection_get_handle (conn, 0));

   debug ("zero count=%" PRIu32 " offset=%" PRIu64 "
may_trim=%d",
          count, offset, may_trim);
@@ -425,7 +426,7 @@ plugin_zero (struct backend *b, struct connection *conn,
     return 0;
   if (p->plugin.zero) {
     errno = 0;
-    result = p->plugin.zero (connection_get_handle (conn),
+    result = p->plugin.zero (connection_get_handle (conn, 0),
                              count, offset, may_trim);
     if (result == -1) {
       err = threadlocal_get_error ();
@@ -446,7 +447,7 @@ plugin_zero (struct backend *b, struct connection *conn,
   }

   while (count) {
-    result = p->plugin.pwrite (connection_get_handle (conn),
+    result = p->plugin.pwrite (connection_get_handle (conn, 0),
                                buf, limit, offset);
     if (result < 0)
       break;
--
2.15.1