bug#68504: [PATCH v3] Add copy-on-write support to scm_copy_file.

Ludovic Courtès <[email protected]>
Newsgroups gmane.lisp.guile.bugs
Message-ID <[email protected]>
Hi Tomas,

Tomas Volf <[email protected]> skribis:

> On modern file-systems (BTRFS, ZFS) it is possible to copy a file using
> copy-on-write method.  For large files it has the advantage of being
> much faster and saving disk space (since identical extents are not
> duplicated).  This feature is stable and for example coreutils' `cp'
> does use it automatically (see --reflink).
>
> This commit adds support for this feature into our copy-file procedure.
> Same as `cp', it defaults to 'auto, meaning the copy-on-write is
> attempted, and in case of failure the regular copy is performed.
>
> No tests are provided, because the behavior depends on the system,
> underlying file-system and its configuration.  That makes it challenging
> to write a test for it.  Manual testing was performed instead:
>
>     $ btrfs filesystem du /tmp/cow*
>          Total   Exclusive  Set shared  Filename
>       36.00KiB    36.00KiB       0.00B  /tmp/cow
>
>     $ cat cow-test.scm
>     (copy-file "/tmp/cow" "/tmp/cow-unspecified")
>     (copy-file "/tmp/cow" "/tmp/cow-always" #:copy-on-write 'always)
>     (copy-file "/tmp/cow" "/tmp/cow-auto" #:copy-on-write 'auto)
>     (copy-file "/tmp/cow" "/tmp/cow-never" #:copy-on-write 'never)
>     (copy-file "/tmp/cow" "/dev/shm/cow-unspecified")
>     (copy-file "/tmp/cow" "/dev/shm/cow-auto" #:copy-on-write 'auto)
>     (copy-file "/tmp/cow" "/dev/shm/cow-never" #:copy-on-write 'never)
>     $ ./meta/guile -s cow-test.scm
>
>     $ btrfs filesystem du /tmp/cow*
>          Total   Exclusive  Set shared  Filename
>       36.00KiB       0.00B    36.00KiB  /tmp/cow
>       36.00KiB       0.00B    36.00KiB  /tmp/cow-always
>       36.00KiB       0.00B    36.00KiB  /tmp/cow-auto
>       36.00KiB    36.00KiB       0.00B  /tmp/cow-never
>       36.00KiB       0.00B    36.00KiB  /tmp/cow-unspecified
>
>     $ sha1sum /tmp/cow* /dev/shm/cow*
>     4c665f87b5dc2e7d26279c4b48968d085e1ace32  /tmp/cow
>     4c665f87b5dc2e7d26279c4b48968d085e1ace32  /tmp/cow-always
>     4c665f87b5dc2e7d26279c4b48968d085e1ace32  /tmp/cow-auto
>     4c665f87b5dc2e7d26279c4b48968d085e1ace32  /tmp/cow-never
>     4c665f87b5dc2e7d26279c4b48968d085e1ace32  /tmp/cow-unspecified
>     4c665f87b5dc2e7d26279c4b48968d085e1ace32  /dev/shm/cow-auto
>     4c665f87b5dc2e7d26279c4b48968d085e1ace32  /dev/shm/cow-never
>     4c665f87b5dc2e7d26279c4b48968d085e1ace32  /dev/shm/cow-unspecified
>
> This commit also adds to new failure modes for (copy-file).
>
> Failure to copy-on-write when 'always was passed in:
>
>     scheme@(guile-user)> (copy-file "/tmp/cow" "/dev/shm/cow" #:copy-on-write 'always)
>     ice-9/boot-9.scm:1676:22: In procedure raise-exception:
>     In procedure copy-file: copy-on-write failed: Invalid cross-device link
>
> Passing in invalid value for the #:copy-on-write keyword argument:
>
>     scheme@(guile-user)> (copy-file "/tmp/cow" "/dev/shm/cow" #:copy-on-write 'nevr)
>     ice-9/boot-9.scm:1676:22: In procedure raise-exception:
>     In procedure copy-file: invalid value for #:copy-on-write: nevr
>
> * NEWS: Add note for copy-file supporting copy-on-write.
> * configure.ac: Check for linux/fs.h.
> * doc/ref/posix.texi (File System)[copy-file]: Document the new
> signature.
> * libguile/filesys.c (clone_file): New function cloning a file using
> FICLONE, if supported.
> (k_copy_on_write): New keyword.
> (sym_always, sym_auto, sym_never): New symbols.
> (scm_copy_file2): Renamed from scm_copy_file.  New #:copy-on-write
> keyword argument.  Attempt copy-on-write copy by default.
> (scm_copy_file): Call scm_copy_file2.
> * libguile/filesys.h: Add scm_copy_file2 as SCM_INTERNAL.
> ---
> v2: Introduce scm_copy_file2 in order to preserve backwards compatibility.
>
> v3: Remove mention of scm_copy_file from the commit message.

Finally pushed as e1690f3fd251d69b3687ec12c6f4b41034047f0f.  Note that I
added copyright lines for you, let me know if I got it wrong.

As a followup, we should add support for ‘copy_file_range’ when FICLONE
cannot be used; glibc supports it on all platforms but it returns ENOSYS
on GNU/Hurd currently.

WDYT?

Thank you!

Ludo’.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.