This convenience function makes it a bit simpler to read a full set of
extents covering a range from a plugin, especially for plugins which
don't reply with a full set of extents in a single call.
---
docs/nbdkit-filter.pod | 22 +++++++++++++++++
include/nbdkit-filter.h | 5 ++++
server/extents.c | 54 +++++++++++++++++++++++++++++++++++++++++
server/nbdkit.syms | 1 +
4 files changed, 82 insertions(+)
diff --git a/docs/nbdkit-filter.pod b/docs/nbdkit-filter.pod
index 82b1ade1..98a08ca4 100644
--- a/docs/nbdkit-filter.pod
+++ b/docs/nbdkit-filter.pod
@@ -857,6 +857,28 @@ Returns the number of extents in the list.
Returns a copy of the C<i>'th extent.
+=head3 Reading the full extents from the plugin
+
+A convenience function is provided to filters only which makes one or
+more requests to the underlying plugin until we have a full set of
+extents covering the region C<[offset..offset+count-1]>.
+
+ struct nbdkit_extents *nbdkit_extents_full (
+ struct nbdkit_next_ops *next_ops,
+ nbdkit_backend *nxdata,
+ uint32_t count, uint64_t offset,
+ uint32_t flags, int *err);
+
+Note this allocates a new C<struct nbdkit_extents> which the caller
+must free. C<flags> is passed through to the underlying plugin, but
+C<NBDKIT_FLAG_REQ_ONE> is removed from the set of flags so that the
+plugin returns as much information as possible (this is usually what
+you want).
+
+On error this function can return C<NULL>. In this case it calls
+C<nbdkit_error> and/or C<nbdkit_set_error> as required. C<*err> will
+be set to a suitable value.
+
=head3 Enforcing alignment of an nbdkit_extents list
A convenience function is provided to filters only which makes it
diff --git a/include/nbdkit-filter.h b/include/nbdkit-filter.h
index afe83e0b..0964c6e7 100644
--- a/include/nbdkit-filter.h
+++ b/include/nbdkit-filter.h
@@ -124,6 +124,11 @@ NBDKIT_EXTERN_DECL (size_t, nbdkit_extents_count,
(const struct nbdkit_extents *));
NBDKIT_EXTERN_DECL (struct nbdkit_extent, nbdkit_get_extent,
(const struct nbdkit_extents *, size_t));
+NBDKIT_EXTERN_DECL (struct nbdkit_extents *, nbdkit_extents_full,
+ (struct nbdkit_next_ops *next_ops,
+ nbdkit_backend *nxdata,
+ uint32_t count, uint64_t offset,
+ uint32_t flags, int *err));
NBDKIT_EXTERN_DECL (int, nbdkit_extents_aligned,
(struct nbdkit_next_ops *next_ops,
nbdkit_backend *nxdata,
diff --git a/server/extents.c b/server/extents.c
index 5f6f3e2e..a081156e 100644
--- a/server/extents.c
+++ b/server/extents.c
@@ -292,3 +292,57 @@ nbdkit_extents_aligned (struct nbdkit_next_ops *next_ops,
/* Once we get here, all extents are aligned. */
return 0;
}
+
+/* This is a convenient wrapper around next_ops->extents which can be
+ * used from filters where you want to get a complete set of extents
+ * covering the region [offset..offset+count-1].
+ */
+struct nbdkit_extents *
+nbdkit_extents_full (struct nbdkit_next_ops *next_ops, nbdkit_backend *nxdata,
+ uint32_t count, uint64_t offset, uint32_t flags,
+ int *err)
+{
+ struct nbdkit_extents *ret;
+
+ /* Clear REQ_ONE to ask the plugin for as much information as it is
+ * willing to return (the plugin may still truncate if it is too
+ * costly to provide everything).
+ */
+ flags &= ~NBDKIT_FLAG_REQ_ONE;
+
+ ret = nbdkit_extents_new (offset, offset+count);
+ if (ret == NULL) goto error0;
+
+ while (count > 0) {
+ const uint64_t old_offset = offset;
+ size_t i;
+
+ CLEANUP_EXTENTS_FREE struct nbdkit_extents *t
+ = nbdkit_extents_new (offset, offset+count);
+ if (t == NULL) goto error1;
+
+ if (next_ops->extents (nxdata, count, offset, flags, t, err) == -1)
+ goto error0;
+
+ for (i = 0; i < nbdkit_extents_count (t); ++i) {
+ const struct nbdkit_extent e = nbdkit_get_extent (t, i);
+ if (nbdkit_add_extent (ret, e.offset, e.length, e.type) == -1)
+ goto error1;
+
+ assert (e.length <= count);
+ offset += e.length;
+ count -= e.length;
+ }
+
+ /* If the plugin is behaving we must make forward progress. */
+ assert (offset > old_offset);
+ }
+
+ return ret;
+
+ error1:
+ *err = errno;
+ error0:
+ if (ret) nbdkit_extents_free (ret);
+ return NULL;
+}
diff --git a/server/nbdkit.syms b/server/nbdkit.syms
index 3d6b2235..20ee27f3 100644
--- a/server/nbdkit.syms
+++ b/server/nbdkit.syms
@@ -51,6 +51,7 @@
nbdkit_extents_aligned;
nbdkit_extents_count;
nbdkit_extents_free;
+ nbdkit_extents_full;
nbdkit_extents_new;
nbdkit_get_extent;
nbdkit_is_tls;
--
2.29.0.rc2