[Libguestfs] [PATCH v2 2/4] file: Support zero without ZERO_RANGE

Nir Soffer nsoffer at redhat.com
Sat Aug 18 20:12:49 UTC 2018


On Fri, Aug 3, 2018 at 10:28 PM Nir Soffer <nirsof at gmail.com> wrote:

> File systems not supporting FALLOC_FL_ZERO_RANGE yet fall back to manual
> zeroing.
>
> We can avoid this by combining two fallocate calls:
>
>     fallocate(FALLOC_FL_PUNCH_HOLE)
>     fallocate(0)
>
> Based on my tests this is much more efficient compared to manual
> zeroing. The idea came from this qemu patch:
> https://github.com/qemu/qemu/commit/1cdc3239f1bb
>
> Here is an example run with NFS 4.2 without this change, converting
> fedora 27 image created with virt-builder:
>
> $ export SOCK=/tmp/nbd.sock
> $ export FILE=/nfs-mount/fedora-27.img
> $ src/nbdkit plugins/file/.libs/nbdkit-file-plugin.so file=$FILE -U $SOCK
>
> $ time qemu-img convert -n -f raw -O raw /var/tmp/fedora-27.img
> nbd:unix:/tmp/nbd.sock
>
> real    0m17.481s
> user    0m0.199s
> sys     0m0.691s
>
> $ time qemu-img convert -n -f raw -O raw -W /var/tmp/fedora-27.img
> nbd:unix:/tmp/nbd.sock
>
> real    0m17.072s
> user    0m0.191s
> sys     0m0.738s
>
> With this change:
>
> $ time qemu-img convert -n -f raw -O raw /var/tmp/fedora-27.img
> nbd:unix:/tmp/nbd.sock
>
> real    0m6.285s
> user    0m0.217s
> sys     0m0.829s
>
> $ time qemu-img convert -n -f raw -O raw -W /var/tmp/fedora-27.img
> nbd:unix:/tmp/nbd.sock
>
> real    0m3.967s
> user    0m0.193s
> sys     0m0.702s
>
> Note: the image is sparse, but nbdkit creates a fully allocated image.
> This may be a bug in nbdkit or qemu-img.
> ---
>  plugins/file/file.c | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>
> diff --git a/plugins/file/file.c b/plugins/file/file.c
> index 5daab63..a2cea4a 100644
> --- a/plugins/file/file.c
> +++ b/plugins/file/file.c
> @@ -121,6 +121,7 @@ struct handle {
>    int fd;
>    bool can_punch_hole;
>    bool can_zero_range;
> +  bool can_fallocate;
>  };
>
>  /* Create the per-connection handle. */
> @@ -161,6 +162,8 @@ file_open (int readonly)
>    h->can_zero_range = false;
>  #endif
>
> +  h->can_fallocate = true;
> +
>    return h;
>  }
>
> @@ -301,6 +304,35 @@ file_zero (void *handle, uint32_t count, uint64_t
> offset, int may_trim)
>    }
>  #endif
>
> +#ifdef FALLOC_FL_PUNCH_HOLE
> +  /* If we can punch hole but may not trim, we can combine punching hole
> and
> +   * fallocate to zero a range. This is expected to be more efficient than
> +   * writing zeros manually. */
> +  if (h->can_punch_hole && h->can_fallocate) {
> +    r = do_fallocate (h->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
> +                      offset, count);
> +    if (r == 0) {
> +      r = do_fallocate(h->fd, 0, offset, count);
>

Space after the function name is missing here, fixing it in v3.


> +      if (r == 0)
> +        return r;
> +
> +      if (errno != EOPNOTSUPP) {
> +        nbdkit_error ("zero: %m");
> +        return r;
> +      }
> +
> +      h->can_fallocate = false;
> +    } else {
> +      if (errno != EOPNOTSUPP) {
> +        nbdkit_error ("zero: %m");
> +        return r;
> +      }
> +
> +      h->can_punch_hole = false;
> +    }
> +  }
> +#endif
> +
>    /* Trigger a fall back to writing */
>    errno = EOPNOTSUPP;
>    return r;
> --
> 2.17.1
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/libguestfs/attachments/20180818/9b0ecb10/attachment.htm>


More information about the Libguestfs mailing list