When querying the extents of the underlying plugin, we should only translate the starting offset, and let the plugin report for at least as many bytes as our range permits. Otherwise, short-changing the range causes bad behavior such as returning 0 extents, or even failing the creation of an extents tracker: $ cat script case "$1" in get_size) echo 1m;; can_extents) ;; extents) echo 0 1m;; *) exit 2 ;; esac $ nbdkit -U - --filter=offset sh script offset=64k \ --run 'qemu-io -r -f raw -c map $nbd' nbdkit: sh[1]: error: extents: plugin must return at least one extent 896 KiB (0xe0000) bytes allocated at offset 0 bytes (0x0) nbdkit: sh[1]: error: extents: plugin must return at least one extent qemu-io: Failed to get allocation status: Invalid argument $ nbdkit -U - --filter=offset sh script offset=640k \ --run 'qemu-io -r -f raw -c map $nbd' nbdkit: sh[1]: error: nbdkit_extents_new: start (655360) >= end (393216) qemu-io: Failed to get allocation status: Invalid argument Fixes: 1a5e2d9c, 624abb36 Signed-off-by: Eric Blake <eblake@redhat.com> --- At least we're catching this now before 1.14. docs/nbdkit-filter.pod | 2 +- filters/offset/offset.c | 4 ++-- filters/partition/partition.c | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/nbdkit-filter.pod b/docs/nbdkit-filter.pod index 6e2bea61..cfd664eb 100644 --- a/docs/nbdkit-filter.pod +++ b/docs/nbdkit-filter.pod @@ -560,7 +560,7 @@ from the layer below. Without error checking it would look like this: int64_t size; size = next_ops->get_size (nxdata); - extents2 = nbdkit_extents_new (offset + shift, size - shift); + extents2 = nbdkit_extents_new (offset + shift, size); next_ops->extents (nxdata, count, offset + shift, flags, extents2, err); for (i = 0; i < nbdkit_extents_count (extents2); ++i) { e = nbdkit_get_extent (extents2, i); diff --git a/filters/offset/offset.c b/filters/offset/offset.c index efe5c6d1..00122770 100644 --- a/filters/offset/offset.c +++ b/filters/offset/offset.c @@ -140,9 +140,9 @@ offset_extents (struct nbdkit_next_ops *next_ops, void *nxdata, size_t i; CLEANUP_EXTENTS_FREE struct nbdkit_extents *extents2 = NULL; struct nbdkit_extent e; - int64_t real_size = next_ops->get_size (nxdata); + int64_t real_size = range >= 0 ? offset + range : next_ops->get_size (nxdata); - extents2 = nbdkit_extents_new (offs + offset, real_size - offset); + extents2 = nbdkit_extents_new (offs + offset, real_size); if (extents2 == NULL) { *err = errno; return -1; diff --git a/filters/partition/partition.c b/filters/partition/partition.c index 56ad05e2..b1b1945d 100644 --- a/filters/partition/partition.c +++ b/filters/partition/partition.c @@ -230,9 +230,8 @@ partition_extents (struct nbdkit_next_ops *next_ops, void *nxdata, size_t i; CLEANUP_EXTENTS_FREE struct nbdkit_extents *extents2 = NULL; struct nbdkit_extent e; - int64_t real_size = next_ops->get_size (nxdata); - extents2 = nbdkit_extents_new (offs + h->offset, real_size - h->offset); + extents2 = nbdkit_extents_new (offs + h->offset, h->offset + h->range); if (extents2 == NULL) { *err = errno; return -1; -- 2.21.0