[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