This was previously used as ‘nxdata’ and stored a tuple of ’b->next’
and the real filter handle. However after recent changes we don't
need it. We can use ‘b->next’ as nxdata, and the handle is passed to
us by the calling functions.
Inspired by Eric Blakes observations in this email:
https://www.redhat.com/archives/libguestfs/2020-February/msg00092.html
---
server/filters.c | 217 ++++++++++++++++-------------------------------
1 file changed, 73 insertions(+), 144 deletions(-)
diff --git a/server/filters.c b/server/filters.c
index c916217c..92b0ceb3 100644
--- a/server/filters.c
+++ b/server/filters.c
@@ -49,16 +49,6 @@ struct backend_filter {
struct nbdkit_filter filter;
};
-/* Literally a backend and the filter's handle.
- *
- * This is the implementation of our handle in .open, and serves as
- * a stable ‘void *nxdata’ in the filter API.
- */
-struct b_h {
- struct backend *b;
- void *handle;
-};
-
/* Note this frees the whole chain. */
static void
filter_free (struct backend *b)
@@ -186,20 +176,19 @@ filter_config_complete (struct backend *b)
static int
next_preconnect (void *nxdata, int readonly)
{
- struct b_h *b_h = nxdata;
- return b_h->b->preconnect (b_h->b, readonly);
+ struct backend *b_next = nxdata;
+ return b_next->preconnect (b_next, readonly);
}
static int
filter_preconnect (struct backend *b, int readonly)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h nxdata = { .b = b->next };
debug ("%s: preconnect", b->name);
if (f->filter.preconnect)
- return f->filter.preconnect (next_preconnect, &nxdata, readonly);
+ return f->filter.preconnect (next_preconnect, b->next, readonly);
else
return b->next->preconnect (b->next, readonly);
}
@@ -216,201 +205,181 @@ plugin_magic_config_key (struct backend *b)
static int
next_open (void *nxdata, int readonly)
{
- struct b_h *b_h = nxdata;
+ struct backend *b_next = nxdata;
- return backend_open (b_h->b, readonly);
+ return backend_open (b_next, readonly);
}
static void *
filter_open (struct backend *b, int readonly)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = malloc (sizeof *nxdata);
-
- if (!nxdata) {
- nbdkit_error ("malloc: %m");
- return NULL;
- }
-
- nxdata->b = b->next;
- nxdata->handle = NULL;
+ void *handle;
/* Most filters will call next_open first, resulting in
* inner-to-outer ordering.
*/
if (f->filter.open)
- nxdata->handle = f->filter.open (next_open, nxdata, readonly);
+ handle = f->filter.open (next_open, b->next, readonly);
else if (backend_open (b->next, readonly) == -1)
- nxdata->handle = NULL;
+ handle = NULL;
else
- nxdata->handle = NBDKIT_HANDLE_NOT_NEEDED;
- if (nxdata->handle == NULL) {
- free (nxdata);
- return NULL;
- }
- return nxdata;
+ handle = NBDKIT_HANDLE_NOT_NEEDED;
+ return handle;
}
static void
filter_close (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- if (handle && f->filter.close) {
- assert (nxdata->b == b->next);
- f->filter.close (nxdata->handle);
- free (nxdata);
- }
+ if (handle && f->filter.close)
+ f->filter.close (handle);
}
/* The next_functions structure contains pointers to backend
- * functions. However because these functions are all expecting a
- * backend and a handle, we cannot call them directly, but must
- * write some next_* functions that unpack the two parameters from a
- * single ‘void *nxdata’ struct pointer (‘b_h’).
+ * functions. These are only needed for type safety (nxdata is void
+ * pointer, backend_* functions expect a struct backend * parameter).
+ * nxdata is a pointer to the next backend in the linked list.
*/
static int
next_reopen (void *nxdata, int readonly)
{
- struct b_h *b_h = nxdata;
- return backend_reopen (b_h->b, readonly);
+ struct backend *b_next = nxdata;
+ return backend_reopen (b_next, readonly);
}
static int64_t
next_get_size (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_get_size (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_get_size (b_next);
}
static int
next_can_write (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_can_write (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_can_write (b_next);
}
static int
next_can_flush (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_can_flush (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_can_flush (b_next);
}
static int
next_is_rotational (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_is_rotational (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_is_rotational (b_next);
}
static int
next_can_trim (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_can_trim (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_can_trim (b_next);
}
static int
next_can_zero (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_can_zero (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_can_zero (b_next);
}
static int
next_can_fast_zero (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_can_fast_zero (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_can_fast_zero (b_next);
}
static int
next_can_extents (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_can_extents (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_can_extents (b_next);
}
static int
next_can_fua (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_can_fua (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_can_fua (b_next);
}
static int
next_can_multi_conn (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_can_multi_conn (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_can_multi_conn (b_next);
}
static int
next_can_cache (void *nxdata)
{
- struct b_h *b_h = nxdata;
- return backend_can_cache (b_h->b);
+ struct backend *b_next = nxdata;
+ return backend_can_cache (b_next);
}
static int
next_pread (void *nxdata, void *buf, uint32_t count, uint64_t offset,
uint32_t flags, int *err)
{
- struct b_h *b_h = nxdata;
- return backend_pread (b_h->b, buf, count, offset, flags,
- err);
+ struct backend *b_next = nxdata;
+ return backend_pread (b_next, buf, count, offset, flags, err);
}
static int
next_pwrite (void *nxdata, const void *buf, uint32_t count, uint64_t offset,
uint32_t flags, int *err)
{
- struct b_h *b_h = nxdata;
- return backend_pwrite (b_h->b, buf, count, offset, flags,
- err);
+ struct backend *b_next = nxdata;
+ return backend_pwrite (b_next, buf, count, offset, flags, err);
}
static int
next_flush (void *nxdata, uint32_t flags, int *err)
{
- struct b_h *b_h = nxdata;
- return backend_flush (b_h->b, flags, err);
+ struct backend *b_next = nxdata;
+ return backend_flush (b_next, flags, err);
}
static int
next_trim (void *nxdata, uint32_t count, uint64_t offset, uint32_t flags,
int *err)
{
- struct b_h *b_h = nxdata;
- return backend_trim (b_h->b, count, offset, flags, err);
+ struct backend *b_next = nxdata;
+ return backend_trim (b_next, count, offset, flags, err);
}
static int
next_zero (void *nxdata, uint32_t count, uint64_t offset, uint32_t flags,
int *err)
{
- struct b_h *b_h = nxdata;
- return backend_zero (b_h->b, count, offset, flags, err);
+ struct backend *b_next = nxdata;
+ return backend_zero (b_next, count, offset, flags, err);
}
static int
next_extents (void *nxdata, uint32_t count, uint64_t offset, uint32_t flags,
struct nbdkit_extents *extents, int *err)
{
- struct b_h *b_h = nxdata;
- return backend_extents (b_h->b, count, offset, flags,
- extents, err);
+ struct backend *b_next = nxdata;
+ return backend_extents (b_next, count, offset, flags, extents, err);
}
static int
next_cache (void *nxdata, uint32_t count, uint64_t offset,
uint32_t flags, int *err)
{
- struct b_h *b_h = nxdata;
- return backend_cache (b_h->b, count, offset, flags, err);
+ struct backend *b_next = nxdata;
+ return backend_cache (b_next, count, offset, flags, err);
}
static struct nbdkit_next_ops next_ops = {
@@ -439,11 +408,9 @@ static int
filter_prepare (struct backend *b, void *handle, int readonly)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.prepare &&
- f->filter.prepare (&next_ops, nxdata, nxdata->handle, readonly) == -1)
+ f->filter.prepare (&next_ops, b->next, handle, readonly) == -1)
return -1;
return 0;
@@ -453,11 +420,9 @@ static int
filter_finalize (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.finalize &&
- f->filter.finalize (&next_ops, nxdata, nxdata->handle) == -1)
+ f->filter.finalize (&next_ops, b->next, handle) == -1)
return -1;
return 0;
}
@@ -466,11 +431,9 @@ static int64_t
filter_get_size (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.get_size)
- return f->filter.get_size (&next_ops, nxdata, nxdata->handle);
+ return f->filter.get_size (&next_ops, b->next, handle);
else
return backend_get_size (b->next);
}
@@ -479,11 +442,9 @@ static int
filter_can_write (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.can_write)
- return f->filter.can_write (&next_ops, nxdata, nxdata->handle);
+ return f->filter.can_write (&next_ops, b->next, handle);
else
return backend_can_write (b->next);
}
@@ -492,11 +453,9 @@ static int
filter_can_flush (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.can_flush)
- return f->filter.can_flush (&next_ops, nxdata, nxdata->handle);
+ return f->filter.can_flush (&next_ops, b->next, handle);
else
return backend_can_flush (b->next);
}
@@ -505,11 +464,9 @@ static int
filter_is_rotational (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.is_rotational)
- return f->filter.is_rotational (&next_ops, nxdata, nxdata->handle);
+ return f->filter.is_rotational (&next_ops, b->next, handle);
else
return backend_is_rotational (b->next);
}
@@ -518,11 +475,9 @@ static int
filter_can_trim (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.can_trim)
- return f->filter.can_trim (&next_ops, nxdata, nxdata->handle);
+ return f->filter.can_trim (&next_ops, b->next, handle);
else
return backend_can_trim (b->next);
}
@@ -531,11 +486,9 @@ static int
filter_can_zero (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.can_zero)
- return f->filter.can_zero (&next_ops, nxdata, nxdata->handle);
+ return f->filter.can_zero (&next_ops, b->next, handle);
else
return backend_can_zero (b->next);
}
@@ -544,11 +497,9 @@ static int
filter_can_fast_zero (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.can_fast_zero)
- return f->filter.can_fast_zero (&next_ops, nxdata, nxdata->handle);
+ return f->filter.can_fast_zero (&next_ops, b->next, handle);
else
return backend_can_fast_zero (b->next);
}
@@ -557,11 +508,9 @@ static int
filter_can_extents (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.can_extents)
- return f->filter.can_extents (&next_ops, nxdata, nxdata->handle);
+ return f->filter.can_extents (&next_ops, b->next, handle);
else
return backend_can_extents (b->next);
}
@@ -570,11 +519,9 @@ static int
filter_can_fua (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.can_fua)
- return f->filter.can_fua (&next_ops, nxdata, nxdata->handle);
+ return f->filter.can_fua (&next_ops, b->next, handle);
else
return backend_can_fua (b->next);
}
@@ -583,11 +530,9 @@ static int
filter_can_multi_conn (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.can_multi_conn)
- return f->filter.can_multi_conn (&next_ops, nxdata, nxdata->handle);
+ return f->filter.can_multi_conn (&next_ops, b->next, handle);
else
return backend_can_multi_conn (b->next);
}
@@ -596,11 +541,9 @@ static int
filter_can_cache (struct backend *b, void *handle)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.can_cache)
- return f->filter.can_cache (&next_ops, nxdata, nxdata->handle);
+ return f->filter.can_cache (&next_ops, b->next, handle);
else
return backend_can_cache (b->next);
}
@@ -611,11 +554,9 @@ filter_pread (struct backend *b, void *handle,
uint32_t flags, int *err)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.pread)
- return f->filter.pread (&next_ops, nxdata, nxdata->handle,
+ return f->filter.pread (&next_ops, b->next, handle,
buf, count, offset, flags, err);
else
return backend_pread (b->next, buf, count, offset, flags, err);
@@ -627,11 +568,9 @@ filter_pwrite (struct backend *b, void *handle,
uint32_t flags, int *err)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.pwrite)
- return f->filter.pwrite (&next_ops, nxdata, nxdata->handle,
+ return f->filter.pwrite (&next_ops, b->next, handle,
buf, count, offset, flags, err);
else
return backend_pwrite (b->next, buf, count, offset, flags, err);
@@ -642,11 +581,9 @@ filter_flush (struct backend *b, void *handle,
uint32_t flags, int *err)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.flush)
- return f->filter.flush (&next_ops, nxdata, nxdata->handle, flags, err);
+ return f->filter.flush (&next_ops, b->next, handle, flags, err);
else
return backend_flush (b->next, flags, err);
}
@@ -657,11 +594,9 @@ filter_trim (struct backend *b, void *handle,
uint32_t flags, int *err)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.trim)
- return f->filter.trim (&next_ops, nxdata, nxdata->handle, count, offset,
+ return f->filter.trim (&next_ops, b->next, handle, count, offset,
flags, err);
else
return backend_trim (b->next, count, offset, flags, err);
@@ -672,11 +607,9 @@ filter_zero (struct backend *b, void *handle,
uint32_t count, uint64_t offset, uint32_t flags, int *err)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.zero)
- return f->filter.zero (&next_ops, nxdata, nxdata->handle,
+ return f->filter.zero (&next_ops, b->next, handle,
count, offset, flags, err);
else
return backend_zero (b->next, count, offset, flags, err);
@@ -688,11 +621,9 @@ filter_extents (struct backend *b, void *handle,
struct nbdkit_extents *extents, int *err)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.extents)
- return f->filter.extents (&next_ops, nxdata, nxdata->handle,
+ return f->filter.extents (&next_ops, b->next, handle,
count, offset, flags,
extents, err);
else
@@ -706,11 +637,9 @@ filter_cache (struct backend *b, void *handle,
uint32_t flags, int *err)
{
struct backend_filter *f = container_of (b, struct backend_filter, backend);
- struct b_h *nxdata = handle;
- assert (nxdata->b == b->next);
if (f->filter.cache)
- return f->filter.cache (&next_ops, nxdata, nxdata->handle,
+ return f->filter.cache (&next_ops, b->next, handle,
count, offset, flags, err);
else
return backend_cache (b->next, count, offset, flags, err);
--
2.25.0