[Libguestfs] [nbdkit PATCH 5/6] retry: Avoid assertion during retried extents

Eric Blake eblake at redhat.com
Tue Oct 1 03:17:05 UTC 2019


If the plugin's .extents made progress before failing, retrying the
call with the original offset that differs from the offset expected by
extents will cause an assertion failure.  We have to perform each
retry iteration with a fresh extents object, and copy it on success.

The sh plugin could trigger this with an extents callback that
produces valid data followed by garbage, as will be shown in the next
patch.

Fixes: f0f0ec49
Signed-off-by: Eric Blake <eblake at redhat.com>
---
 filters/retry/retry.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/filters/retry/retry.c b/filters/retry/retry.c
index 00dbd091..9747b4eb 100644
--- a/filters/retry/retry.c
+++ b/filters/retry/retry.c
@@ -322,17 +322,39 @@ retry_extents (struct nbdkit_next_ops *next_ops, void *nxdata,
 {
   struct retry_handle *h = handle;
   struct retry_data data = {0};
+  CLEANUP_EXTENTS_FREE struct nbdkit_extents *extents2 = NULL;
   int r;
+  size_t i;

  again:
   if (next_ops->can_extents (nxdata) != 1) {
     *err = EIO;
     r = -1;
   }
-  else
-    r = next_ops->extents (nxdata, count, offset, flags, extents, err);
+  else {
+    /* Each retry must begin with extents reset to the right beginning. */
+    nbdkit_extents_free (extents2);
+    extents2 = nbdkit_extents_new (offset, next_ops->get_size (nxdata));
+    if (extents2 == NULL) {
+      *err = errno;
+      return -1; /* Not worth a retry after ENOMEM. */
+    }
+    r = next_ops->extents (nxdata, count, offset, flags, extents2, err);
+  }
   if (r == -1 && do_retry (h, &data, next_ops, nxdata, err)) goto again;

+  if (r == 0) {
+    /* Transfer the successful extents back to the caller. */
+    for (i = 0; i < nbdkit_extents_count (extents2); ++i) {
+      struct nbdkit_extent e = nbdkit_get_extent (extents2, i);
+
+      if (nbdkit_add_extent (extents, e.offset, e.length, e.type) == -1) {
+        *err = errno;
+        return -1;
+      }
+    }
+  }
+
   return r;
 }

-- 
2.21.0




More information about the Libguestfs mailing list