Merge branch '1983_btrfs_clone'

* 1983_btrfs_clone:
  Check linux/fs.h file.
  (vfs_clone_file): clarify errno in case of bad file descriptors.
  Ticket #1983: support BTRFS's file clone operation.
This commit is contained in:
Andrew Borodin 2018-09-03 09:45:41 +03:00
commit 388dad9899
4 changed files with 69 additions and 0 deletions

View File

@ -304,6 +304,12 @@ AC_EGREP_CPP([yes],
AC_MSG_RESULT(no)
])
dnl Check linux/fs.h for FICLONE to support BTRFS's file clone operation
case $host_os in
linux*)
AC_CHECK_HEADERS([linux/fs.h])
esac
dnl Check if the OS is supported by the console saver.
cons_saver=""
case $host_os in

View File

@ -45,6 +45,15 @@
#include <errno.h>
#include <stdlib.h>
#ifdef __linux__
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
#endif /* HAVE_LINUX_FS_H */
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif /* HAVE_SYS_IOCTL_H */
#endif /* __linux__ */
#include "lib/global.h"
#include "lib/strutil.h"
#include "lib/util.h"
@ -654,6 +663,50 @@ vfs_preallocate (int dest_vfs_fd, off_t src_fsize, off_t dest_fsize)
return posix_fallocate (*(int *) dest_fd, dest_fsize, src_fsize - dest_fsize);
#endif /* HAVE_POSIX_FALLOCATE */
}
/* --------------------------------------------------------------------------------------------- */
int
vfs_clone_file (int dest_vfs_fd, int src_vfs_fd)
{
#ifdef FICLONE
void *dest_fd = NULL;
void *src_fd = NULL;
struct vfs_class *dest_class;
struct vfs_class *src_class;
dest_class = vfs_class_find_by_handle (dest_vfs_fd, &dest_fd);
if ((dest_class->flags & VFSF_LOCAL) == 0)
{
errno = EOPNOTSUPP;
return (-1);
}
if (dest_fd == NULL)
{
errno = EBADF;
return (-1);
}
src_class = vfs_class_find_by_handle (src_vfs_fd, &src_fd);
if ((src_class->flags & VFSF_LOCAL) == 0)
{
errno = EOPNOTSUPP;
return (-1);
}
if (src_fd == NULL)
{
errno = EBADF;
return (-1);
}
return ioctl (*(int *) dest_fd, FICLONE, *(int *) src_fd);
#else
(void) dest_vfs_fd;
(void) src_vfs_fd;
errno = EOPNOTSUPP;
return (-1);
#endif
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -287,6 +287,8 @@ char *_vfs_get_cwd (void);
int vfs_preallocate (int dest_desc, off_t src_fsize, off_t dest_fsize);
int vfs_clone_file (int dest_vfs_fd, int src_vfs_fd);
/**
* Interface functions described in interface.c
*/

View File

@ -2345,6 +2345,14 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
appending = ctx->do_append;
ctx->do_append = FALSE;
/* Try clone the file first. */
if (vfs_clone_file (dest_desc, src_desc) == 0)
{
dst_status = DEST_FULL;
return_status = FILE_CONT;
goto ret;
}
/* Find out the optimal buffer size. */
while (mc_fstat (dest_desc, &dst_stat) != 0)
{