On Wed, Aug 14, 2019 at 05:38:31PM -0500, Eric Blake wrote:
When we introduced valid_flags, there was an incentive to do as few
callbacks as possible, favoring cb(VALID|FREE) calls over the sequence
cb(VALID);cb(FREE). To make it work, we set .callback=NULL after an
early free, so that the later check during retirement didn't free
again.
But now that our .free callback is distinct from our other callbacks,
there is no longer an advantage to bundling things, and a significant
reduction in lines of code by just doing it in one place. This
basically reverts 9c8fccdf (which had slightly-questionable C
type-punning anyway) and 57150880.
I didn't see this one before implementing an alternate version here:
https://www.redhat.com/archives/libguestfs/2019-August/msg00251.html
https://www.redhat.com/archives/libguestfs/2019-August/msg00253.html
They're fairly similar, but I didn't get rid of the FREE_CALLBACK
macro for reasons which are clearer later in the series.
Rich.
---
lib/internal.h | 14 --------------
generator/states-reply-simple.c | 1 -
generator/states-reply-structured.c | 20 +-------------------
generator/states-reply.c | 1 -
generator/states.c | 1 -
lib/aio.c | 11 ++++++-----
lib/debug.c | 4 +++-
7 files changed, 10 insertions(+), 42 deletions(-)
diff --git a/lib/internal.h b/lib/internal.h
index dc3676a..1971613 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -277,20 +277,6 @@ struct command {
#define CALL_CALLBACK(cb, ...) \
(cb).callback ((cb).user_data, ##__VA_ARGS__)
-/* Free a callback.
- *
- * Note this works for any type of callback because the basic layout
- * of the struct is the same for all of them. Therefore casting cb to
- * nbd_completion_callback does not change the effective code.
- */
-#define FREE_CALLBACK(cb) \
- do { \
- nbd_completion_callback *_cb = (nbd_completion_callback *)&(cb); \
- if (_cb->callback != NULL && _cb->free != NULL) \
- _cb->free (_cb->user_data); \
- _cb->callback = NULL; \
- } while (0)
-
/* aio.c */
extern void nbd_internal_retire_and_free_command (struct command *);
diff --git a/generator/states-reply-simple.c b/generator/states-reply-simple.c
index 8e3d7f1..2f83e6f 100644
--- a/generator/states-reply-simple.c
+++ b/generator/states-reply-simple.c
@@ -69,7 +69,6 @@
cmd->offset, LIBNBD_READ_DATA,
&error) == -1)
cmd->error = error ? error : EPROTO;
- FREE_CALLBACK (cmd->cb.fn.chunk);
}
SET_NEXT_STATE (%^FINISH_COMMAND);
diff --git a/generator/states-reply-structured.c b/generator/states-reply-structured.c
index 2e327ce..58e83d4 100644
--- a/generator/states-reply-structured.c
+++ b/generator/states-reply-structured.c
@@ -295,7 +295,6 @@
}
if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk.callback) {
int scratch = error;
- uint16_t flags = be16toh (h->sbuf.sr.structured_reply.flags);
/* Different from successful reads: inform the callback about the
* current error rather than any earlier one. If the callback fails
@@ -307,8 +306,6 @@
&scratch) == -1)
if (cmd->error == 0)
cmd->error = scratch;
- if (flags & NBD_REPLY_FLAG_DONE)
- FREE_CALLBACK (cmd->cb.fn.chunk);
}
}
@@ -390,15 +387,12 @@
assert (cmd); /* guaranteed by CHECK */
if (cmd->cb.fn.chunk.callback) {
int error = cmd->error;
- uint16_t flags = be16toh (h->sbuf.sr.structured_reply.flags);
if (CALL_CALLBACK (cmd->cb.fn.chunk, cmd->data + (offset - cmd->offset),
length - sizeof offset, offset,
LIBNBD_READ_DATA, &error) == -1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
- if (flags & NBD_REPLY_FLAG_DONE)
- FREE_CALLBACK (cmd->cb.fn.chunk);
}
SET_NEXT_STATE (%FINISH);
@@ -454,7 +448,6 @@
memset (cmd->data + offset, 0, length);
if (cmd->cb.fn.chunk.callback) {
int error = cmd->error;
- uint16_t flags = be16toh (h->sbuf.sr.structured_reply.flags);
if (CALL_CALLBACK (cmd->cb.fn.chunk,
cmd->data + offset, length,
@@ -462,8 +455,6 @@
LIBNBD_READ_HOLE, &error) == -1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
- if (flags & NBD_REPLY_FLAG_DONE)
- FREE_CALLBACK (cmd->cb.fn.chunk);
}
SET_NEXT_STATE(%FINISH);
@@ -509,7 +500,6 @@
if (meta_context) {
/* Call the caller's extent function. */
int error = cmd->error;
- uint16_t flags = be16toh (h->sbuf.sr.structured_reply.flags);
if (CALL_CALLBACK (cmd->cb.fn.extent,
meta_context->name, cmd->offset,
@@ -517,8 +507,6 @@
&error) == -1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
- if (flags & NBD_REPLY_FLAG_DONE)
- FREE_CALLBACK (cmd->cb.fn.extent);
}
else
/* Emit a debug message, but ignore it. */
@@ -530,17 +518,11 @@
return 0;
REPLY.STRUCTURED_REPLY.FINISH:
- struct command *cmd = h->reply_cmd;
uint16_t flags;
flags = be16toh (h->sbuf.sr.structured_reply.flags);
- if (flags & NBD_REPLY_FLAG_DONE) {
- if (cmd->type == NBD_CMD_BLOCK_STATUS)
- FREE_CALLBACK (cmd->cb.fn.extent);
- if (cmd->type == NBD_CMD_READ)
- FREE_CALLBACK (cmd->cb.fn.chunk);
+ if (flags & NBD_REPLY_FLAG_DONE)
SET_NEXT_STATE (%^FINISH_COMMAND);
- }
else {
h->reply_cmd = NULL;
SET_NEXT_STATE (%.READY);
diff --git a/generator/states-reply.c b/generator/states-reply.c
index 41dcf8d..575a6d1 100644
--- a/generator/states-reply.c
+++ b/generator/states-reply.c
@@ -174,7 +174,6 @@ save_reply_state (struct nbd_handle *h)
assert (cmd->type != NBD_CMD_DISC);
r = CALL_CALLBACK (cmd->cb.completion, &error);
- FREE_CALLBACK (cmd->cb.completion);
switch (r) {
case -1:
if (error)
diff --git a/generator/states.c b/generator/states.c
index 263f60e..cfa9957 100644
--- a/generator/states.c
+++ b/generator/states.c
@@ -127,7 +127,6 @@ void abort_commands (struct nbd_handle *h,
assert (cmd->type != NBD_CMD_DISC);
r = CALL_CALLBACK (cmd->cb.completion, &error);
- FREE_CALLBACK (cmd->cb.completion);
switch (r) {
case -1:
if (error)
diff --git a/lib/aio.c b/lib/aio.c
index 38a27d0..4a219e4 100644
--- a/lib/aio.c
+++ b/lib/aio.c
@@ -32,11 +32,12 @@ void
nbd_internal_retire_and_free_command (struct command *cmd)
{
/* Free the callbacks. */
- if (cmd->type == NBD_CMD_BLOCK_STATUS)
- FREE_CALLBACK (cmd->cb.fn.extent);
- if (cmd->type == NBD_CMD_READ)
- FREE_CALLBACK (cmd->cb.fn.chunk);
- FREE_CALLBACK (cmd->cb.completion);
+ if (cmd->type == NBD_CMD_BLOCK_STATUS && cmd->cb.fn.extent.free)
+ cmd->cb.fn.extent.free (cmd->cb.fn.extent.user_data);
+ if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk.free)
+ cmd->cb.fn.chunk.free (cmd->cb.fn.chunk.user_data);
+ if (cmd->cb.completion.free)
+ cmd->cb.completion.free (cmd->cb.completion.user_data);
free (cmd);
}
diff --git a/lib/debug.c b/lib/debug.c
index eec2051..a0e6636 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -41,7 +41,9 @@ nbd_unlocked_get_debug (struct nbd_handle *h)
int
nbd_unlocked_clear_debug_callback (struct nbd_handle *h)
{
- FREE_CALLBACK (h->debug_callback);
+ if (h->debug_callback.free)
+ h->debug_callback.free (h->debug_callback.user_data);
+ memset (&h->debug_callback, 0, sizeof h->debug_callback);
return 0;
}
--
2.20.1
_______________________________________________
Libguestfs mailing list
Libguestfs(a)redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html