[Libguestfs] [nbdkit PATCH v3 13/16] ext2: Simplify use of next_ops

Eric Blake eblake at redhat.com
Fri Mar 5 23:31:17 UTC 2021


We no longer need a 'struct nbdkit_next' now that a single pointer is
sufficient for calling into the backend.

There's still more to do with the filter to allow multiple client
plugins to share a single context into the plugin, but that requires a
bit more work (for starters, we need a way to clean up that single
context; .unload is too late, but doing it in .close requires tracking
how many open client connections there are).
---
 filters/ext2/io.h   | 12 +++-----
 filters/ext2/ext2.c | 43 +++++++++++++-------------
 filters/ext2/io.c   | 73 ++++++++++++++++++++++-----------------------
 3 files changed, 61 insertions(+), 67 deletions(-)

diff --git a/filters/ext2/io.h b/filters/ext2/io.h
index da286812..2112e541 100644
--- a/filters/ext2/io.h
+++ b/filters/ext2/io.h
@@ -1,5 +1,5 @@
 /* nbdkit
- * Copyright (C) 2020 Red Hat Inc.
+ * Copyright (C) 2020-2021 Red Hat Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -35,19 +35,15 @@

 #include <ext2_io.h>

+#define NBDKIT_TYPESAFE /* HACK to get type-safe parameters. */
 #include <nbdkit-filter.h>

 #define EXT2_ET_MAGIC_NBDKIT_IO_CHANNEL EXT2_ET_MAGIC_RESERVED_19

-struct nbdkit_next {
-  struct nbdkit_next_ops *next_ops;
-  void *nxdata;
-};
-
 /* Utility functions for encoding nbdkit_next as a name usable by ext2fs */
-extern char *nbdkit_io_encode(const struct nbdkit_next *next)
+extern char *nbdkit_io_encode(const nbdkit_next *next)
   __attribute__ ((__nonnull__ (1)));
-extern int nbdkit_io_decode(const char *name, struct nbdkit_next *out)
+extern int nbdkit_io_decode(const char *name, nbdkit_next **out)
   __attribute__ ((__nonnull__ (1, 2)));

 /* Custom io manager that performs all ext2fs I/O on the next nbdkit layer */
diff --git a/filters/ext2/ext2.c b/filters/ext2/ext2.c
index 1151effd..9a6eec94 100644
--- a/filters/ext2/ext2.c
+++ b/filters/ext2/ext2.c
@@ -45,6 +45,7 @@

 #define NBDKIT_API_VERSION 2

+#define NBDKIT_TYPESAFE /* HACK to get type-safe parameters. */
 #include <nbdkit-filter.h>

 #include "cleanup.h"
@@ -62,7 +63,7 @@ ext2_load (void)
 }

 static int
-ext2_config (nbdkit_next_config *next, void *nxdata,
+ext2_config (nbdkit_next_config *next, nbdkit_backend *nxdata,
              const char *key, const char *value)
 {
   if (strcmp (key, "ext2file") == 0) {
@@ -78,7 +79,7 @@ ext2_config (nbdkit_next_config *next, void *nxdata,
 }

 static int
-ext2_config_complete (nbdkit_next_config_complete *next, void *nxdata)
+ext2_config_complete (nbdkit_next_config_complete *next, nbdkit_backend *nxdata)
 {
   if (file == NULL) {
     nbdkit_error ("you must supply ext2file=<FILE> parameter "
@@ -106,12 +107,12 @@ struct handle {
   ext2_filsys fs;               /* Filesystem handle. */
   ext2_ino_t ino;               /* Inode of open file. */
   ext2_file_t file;             /* File handle. */
-  struct nbdkit_next next;      /* "name" parameter to ext2fs_open. */
+  nbdkit_next *next;            /* "name" parameter to ext2fs_open. */
 };

 /* Export list. */
 static int
-ext2_list_exports (nbdkit_next_list_exports *next, void *nxdata,
+ext2_list_exports (nbdkit_next_list_exports *next, nbdkit_backend *nxdata,
                    int readonly, int is_tls, struct nbdkit_exports *exports)
 {
   /* If we are honoring export names, the default export "" won't
@@ -133,7 +134,7 @@ ext2_list_exports (nbdkit_next_list_exports *next, void *nxdata,

 /* Default export. */
 static const char *
-ext2_default_export (nbdkit_next_default_export *next, void *nxdata,
+ext2_default_export (nbdkit_next_default_export *next, nbdkit_backend *nxdata,
                      int readonly, int is_tls)
 {
   /* If we are honoring exports, "" will fail (even if we resolve to
@@ -152,7 +153,7 @@ ext2_default_export (nbdkit_next_default_export *next, void *nxdata,

 /* Create the per-connection handle. */
 static void *
-ext2_open (nbdkit_next_open *next, void *nxdata,
+ext2_open (nbdkit_next_open *next, nbdkit_context *nxdata,
            int readonly, const char *exportname, int is_tls)
 {
   struct handle *h;
@@ -185,7 +186,7 @@ ext2_open (nbdkit_next_open *next, void *nxdata,
 }

 static int
-ext2_prepare (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle,
+ext2_prepare (nbdkit_next *next_ops, nbdkit_next *nxdata, void *handle,
               int readonly)
 {
   struct handle *h = handle;
@@ -214,9 +215,8 @@ ext2_prepare (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle,
   if (!readonly)
     fs_flags |= EXT2_FLAG_RW;

-  h->next.next_ops = next_ops;
-  h->next.nxdata = nxdata;
-  name = nbdkit_io_encode (&h->next);
+  h->next = next_ops;
+  name = nbdkit_io_encode (next_ops);
   if (!name) {
     nbdkit_error ("nbdkit_io_encode: %m");
     return -1;
@@ -293,20 +293,20 @@ ext2_close (void *handle)
 }

 static int
-ext2_can_fua (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle)
+ext2_can_fua (nbdkit_next *next_ops, nbdkit_next *nxdata, void *handle)
 {
   return NBDKIT_FUA_NATIVE;
 }

 static int
-ext2_can_cache (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle)
+ext2_can_cache (nbdkit_next *next_ops, nbdkit_next *nxdata, void *handle)
 {
   /* Let nbdkit call pread to populate the file system cache. */
   return NBDKIT_CACHE_EMULATE;
 }

 static int
-ext2_can_multi_conn (struct nbdkit_next_ops *next_ops, void *nxdata,
+ext2_can_multi_conn (nbdkit_next *next_ops, nbdkit_next *nxdata,
                      void *handle)
 {
   /* Since we do not permit parallel connections, it does not matter
@@ -320,7 +320,8 @@ ext2_can_multi_conn (struct nbdkit_next_ops *next_ops, void *nxdata,
 }

 static int
-ext2_can_flush (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle)
+ext2_can_flush (nbdkit_next *next_ops, nbdkit_next *nxdata,
+                void *handle)
 {
   /* Regardless of the underlying plugin, we handle flush at the level
    * of the filesystem.  However, we also need to cache the underlying
@@ -337,7 +338,7 @@ ext2_can_flush (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle)
  * is very obscure.
  */
 static int
-ext2_can_zero (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle)
+ext2_can_zero (nbdkit_next *next_ops, nbdkit_next *nxdata, void *handle)
 {
   /* For now, tell nbdkit to call .pwrite instead of any optimization.
    * However, we also want to cache the underlying plugin support.
@@ -348,7 +349,7 @@ ext2_can_zero (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle)
 }

 static int
-ext2_can_trim (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle)
+ext2_can_trim (nbdkit_next *next_ops, nbdkit_next *nxdata, void *handle)
 {
   /* For now, tell nbdkit to never call .trim.  However, we also want
    * to cache the underlying plugin support.
@@ -377,7 +378,7 @@ static int ext2_thread_model (void)

 /* Description. */
 static const char *
-ext2_export_description (struct nbdkit_next_ops *next_ops, void *nxdata,
+ext2_export_description (nbdkit_next *next_ops, nbdkit_next *nxdata,
                          void *handle)
 {
   struct handle *h = handle;
@@ -393,7 +394,7 @@ ext2_export_description (struct nbdkit_next_ops *next_ops, void *nxdata,

 /* Get the disk size. */
 static int64_t
-ext2_get_size (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle)
+ext2_get_size (nbdkit_next *next_ops, nbdkit_next *nxdata, void *handle)
 {
   struct handle *h = handle;
   errcode_t err;
@@ -409,7 +410,7 @@ ext2_get_size (struct nbdkit_next_ops *next_ops, void *nxdata, void *handle)

 /* Read data. */
 static int
-ext2_pread (struct nbdkit_next_ops *next_ops, void *nxdata,
+ext2_pread (nbdkit_next *next_ops, nbdkit_next *nxdata,
             void *handle, void *buf, uint32_t count, uint64_t offset,
             uint32_t flags, int *errp)
 {
@@ -446,7 +447,7 @@ ext2_pread (struct nbdkit_next_ops *next_ops, void *nxdata,

 /* Write data to the file. */
 static int
-ext2_pwrite (struct nbdkit_next_ops *next_ops, void *nxdata,
+ext2_pwrite (nbdkit_next *next_ops, nbdkit_next *nxdata,
              void *handle, const void *buf, uint32_t count, uint64_t offset,
              uint32_t flags, int *errp)
 {
@@ -487,7 +488,7 @@ ext2_pwrite (struct nbdkit_next_ops *next_ops, void *nxdata,
 }

 static int
-ext2_flush (struct nbdkit_next_ops *next_ops, void *nxdata,
+ext2_flush (nbdkit_next *next_ops, nbdkit_next *nxdata,
             void *handle, uint32_t flags, int *errp)
 {
   struct handle *h = handle;
diff --git a/filters/ext2/io.c b/filters/ext2/io.c
index 32c50683..e2f7e43e 100644
--- a/filters/ext2/io.c
+++ b/filters/ext2/io.c
@@ -60,8 +60,7 @@

 struct io_private_data {
   int magic;
-  struct nbdkit_next_ops *next_ops;
-  void *nxdata;
+  nbdkit_next *next;
   ext2_loff_t offset;
   struct struct_io_stats io_stats;
 };
@@ -103,7 +102,7 @@ raw_read_blk (io_channel channel,
   location = ((ext2_loff_t) block * channel->block_size) + data->offset;

   /* TODO is 32-bit overflow ever likely to be a problem? */
-  if (data->next_ops->pread (data->nxdata, buf, size, location, 0, &errno) == 0)
+  if (data->next->pread (data->next, buf, size, location, 0, &errno) == 0)
     return 0;

   retval = errno;
@@ -138,8 +137,8 @@ raw_write_blk (io_channel channel,
   location = ((ext2_loff_t) block * channel->block_size) + data->offset;

   /* TODO is 32-bit overflow ever likely to be a problem? */
-  if (data->next_ops->pwrite (data->nxdata, buf, size, location, 0,
-                              &errno) == 0)
+  if (data->next->pwrite (data->next, buf, size, location, 0,
+                          &errno) == 0)
     return 0;

   retval = errno;
@@ -150,22 +149,21 @@ raw_write_blk (io_channel channel,
 }

 char *
-nbdkit_io_encode (const struct nbdkit_next *next)
+nbdkit_io_encode (const nbdkit_next *next)
 {
   char *ret;

-  if (asprintf (&ret, "nbdkit:%p:%p", next->next_ops, next->nxdata) < 0)
+  if (asprintf (&ret, "nbdkit:%p", next) < 0)
     return NULL;
   return ret;
 }

 int
-nbdkit_io_decode (const char *name, struct nbdkit_next *next)
+nbdkit_io_decode (const char *name, nbdkit_next **next)
 {
   int n;

-  if (sscanf (name, "nbdkit:%p:%p%n", &next->next_ops, &next->nxdata,
-              &n) != 2 || n != strlen (name))
+  if (sscanf (name, "nbdkit:%p%n", next, &n) != 1 || n != strlen (name))
     return -1;
   return 0;
 }
@@ -174,7 +172,7 @@ static errcode_t
 io_open (const char *name, int flags,
          io_channel *channel)
 {
-  struct nbdkit_next next;
+  nbdkit_next *next;
   io_channel io = NULL;
   struct io_private_data *data = NULL;
   errcode_t retval;
@@ -206,14 +204,13 @@ io_open (const char *name, int flags,
   memset (data, 0, sizeof (struct io_private_data));
   data->magic = EXT2_ET_MAGIC_NBDKIT_IO_CHANNEL;
   data->io_stats.num_fields = 2;
-  data->next_ops = next.next_ops;
-  data->nxdata = next.nxdata;
+  data->next = next;

-  /* Too bad NBD doesn't tell us if next_ops->trim guarantees read as zero. */
-  /* if (next_ops-> XXX (...)
+  /* Too bad NBD doesn't tell us if next->trim guarantees read as zero. */
+  /* if (next-> XXX (...)
      io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; */

-  if (flags & IO_FLAG_RW && next.next_ops->can_write (next.nxdata) != 1) {
+  if (flags & IO_FLAG_RW && next->can_write (next) != 1) {
     retval = EPERM;
     goto cleanup;
   }
@@ -310,13 +307,13 @@ io_cache_readahead (io_channel channel,
   data = (struct io_private_data *)channel->private_data;
   EXT2_CHECK_MAGIC (data, EXT2_ET_MAGIC_NBDKIT_IO_CHANNEL);

-  if (data->next_ops->can_cache (data->nxdata) == NBDKIT_CACHE_NATIVE) {
+  if (data->next->can_cache (data->next) == NBDKIT_CACHE_NATIVE) {
     /* TODO is 32-bit overflow ever likely to be a problem? */
-    if (data->next_ops->cache (data->nxdata,
-                               (ext2_loff_t)count * channel->block_size,
-                               ((ext2_loff_t)block * channel->block_size +
-                                data->offset),
-                               0, &errno) == -1)
+    if (data->next->cache (data->next,
+                           (ext2_loff_t)count * channel->block_size,
+                           ((ext2_loff_t)block * channel->block_size +
+                            data->offset),
+                           0, &errno) == -1)
       return errno;
     return 0;
   }
@@ -342,8 +339,8 @@ io_write_byte (io_channel channel, unsigned long offset,
   data = (struct io_private_data *) channel->private_data;
   EXT2_CHECK_MAGIC (data, EXT2_ET_MAGIC_NBDKIT_IO_CHANNEL);

-  if (data->next_ops->pwrite (data->nxdata, buf, size,
-                              offset + data->offset, 0, &errno) == -1)
+  if (data->next->pwrite (data->next, buf, size,
+                          offset + data->offset, 0, &errno) == -1)
     return errno;

   return 0;
@@ -362,8 +359,8 @@ io_flush (io_channel channel)
   data = (struct io_private_data *) channel->private_data;
   EXT2_CHECK_MAGIC (data, EXT2_ET_MAGIC_NBDKIT_IO_CHANNEL);

-  if (data->next_ops->can_flush (data->nxdata) == 1)
-    if (data->next_ops->flush (data->nxdata, 0, &errno) == -1)
+  if (data->next->can_flush (data->next) == 1)
+    if (data->next->flush (data->next, 0, &errno) == -1)
       return errno;
   return retval;
 }
@@ -405,13 +402,13 @@ io_discard (io_channel channel, unsigned long long block,
   data = (struct io_private_data *) channel->private_data;
   EXT2_CHECK_MAGIC (data, EXT2_ET_MAGIC_NBDKIT_IO_CHANNEL);

-  if (data->next_ops->can_trim (data->nxdata) == 1) {
+  if (data->next->can_trim (data->next) == 1) {
     /* TODO is 32-bit overflow ever likely to be a problem? */
-    if (data->next_ops->trim (data->nxdata,
-                              (off_t)(count) * channel->block_size,
-                              ((off_t)(block) * channel->block_size +
-                               data->offset),
-                              0, &errno) == 0)
+    if (data->next->trim (data->next,
+                          (off_t)(count) * channel->block_size,
+                          ((off_t)(block) * channel->block_size +
+                           data->offset),
+                          0, &errno) == 0)
       return 0;
     if (errno == EOPNOTSUPP)
       goto unimplemented;
@@ -433,13 +430,13 @@ io_zeroout (io_channel channel, unsigned long long block,
   data = (struct io_private_data *) channel->private_data;
   EXT2_CHECK_MAGIC (data, EXT2_ET_MAGIC_NBDKIT_IO_CHANNEL);

-  if (data->next_ops->can_zero (data->nxdata) > NBDKIT_ZERO_NONE) {
+  if (data->next->can_zero (data->next) > NBDKIT_ZERO_NONE) {
     /* TODO is 32-bit overflow ever likely to be a problem? */
-    if (data->next_ops->zero (data->nxdata,
-                              (off_t)(count) * channel->block_size,
-                              ((off_t)(block) * channel->block_size +
-                               data->offset),
-                              NBDKIT_FLAG_MAY_TRIM, &errno) == 0)
+    if (data->next->zero (data->next,
+                          (off_t)(count) * channel->block_size,
+                          ((off_t)(block) * channel->block_size +
+                           data->offset),
+                          NBDKIT_FLAG_MAY_TRIM, &errno) == 0)
       return 0;
     if (errno == EOPNOTSUPP)
       goto unimplemented;
-- 
2.30.1




More information about the Libguestfs mailing list