From ea7882ad73690e22282572e3777f3b793b0024a1 Mon Sep 17 00:00:00 2001
From: Peter Hjalmarsson <kanelxake@gmail.com>
Date: Thu, 18 Feb 2016 20:07:40 +0100
Subject: [PATCH] Added support for reflink/clone with BTRFS
---
lib/vfs/vfs.c | 34 ++++++++++++++++++++++++++++++++++
lib/vfs/vfs.h | 2 ++
src/filemanager/file.c | 7 +++++++
3 files changed, 43 insertions(+)
diff --git a/lib/vfs/vfs.c b/lib/vfs/vfs.c
index 5000fcab3..5dd5aed2e 100644
|
|
|
45 | 45 | #include <errno.h> |
46 | 46 | #include <stdlib.h> |
47 | 47 | |
| 48 | #ifdef __linux |
| 49 | #include <linux/fs.h> |
| 50 | #ifdef HAVE_SYS_IOCTL_H |
| 51 | #include <sys/ioctl.h> |
| 52 | #endif |
| 53 | #endif |
| 54 | |
48 | 55 | #include "lib/global.h" |
49 | 56 | #include "lib/strutil.h" |
50 | 57 | #include "lib/util.h" |
… |
… |
vfs_preallocate (int dest_vfs_fd, off_t src_fsize, off_t dest_fsize) |
656 | 663 | #endif /* HAVE_POSIX_FALLOCATE */ |
657 | 664 | } |
658 | 665 | |
| 666 | int |
| 667 | vfs_clone_file (int dest_vfs_fd, int src_vfs_fd) |
| 668 | { |
| 669 | #ifdef __linux__ |
| 670 | void *dest_fd = NULL; |
| 671 | void *src_fd = NULL; |
| 672 | struct vfs_class *dest_class; |
| 673 | struct vfs_class *src_class; |
| 674 | |
| 675 | dest_class = vfs_class_find_by_handle (dest_vfs_fd, &dest_fd); |
| 676 | if ((dest_class->flags & VFSF_LOCAL) == 0 || dest_fd == NULL) |
| 677 | return 0; |
| 678 | |
| 679 | src_class = vfs_class_find_by_handle (src_vfs_fd, &src_fd); |
| 680 | if ((src_class->flags & VFSF_LOCAL) == 0 || src_fd == NULL) |
| 681 | return 0; |
| 682 | |
| 683 | return ioctl (*(int *) dest_fd, FICLONE, *(int *) src_fd); |
| 684 | |
| 685 | |
| 686 | #else |
| 687 | (void) dest_vfs_fd; |
| 688 | (void) src_vfs_fd; |
| 689 | return 0; |
| 690 | #endif |
| 691 | } |
| 692 | |
659 | 693 | /* --------------------------------------------------------------------------------------------- */ |
diff --git a/lib/vfs/vfs.h b/lib/vfs/vfs.h
index 2510195a6..58ba4b59d 100644
|
|
char *_vfs_get_cwd (void); |
287 | 287 | |
288 | 288 | int vfs_preallocate (int dest_desc, off_t src_fsize, off_t dest_fsize); |
289 | 289 | |
| 290 | int vfs_clone_file (int dest_vfs_fd, int src_vfs_fd); |
| 291 | |
290 | 292 | /** |
291 | 293 | * Interface functions described in interface.c |
292 | 294 | */ |
diff --git a/src/filemanager/file.c b/src/filemanager/file.c
index b61821a86..708967e00 100644
|
|
copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx, |
1738 | 1738 | appending = ctx->do_append; |
1739 | 1739 | ctx->do_append = FALSE; |
1740 | 1740 | |
| 1741 | /* Try clone the file first */ |
| 1742 | if (vfs_clone_file(dest_desc,src_desc) == 0) |
| 1743 | { |
| 1744 | dst_status = DEST_FULL; |
| 1745 | goto ret; |
| 1746 | } |
| 1747 | |
1741 | 1748 | /* Find out the optimal buffer size. */ |
1742 | 1749 | while (mc_fstat (dest_desc, &dst_stat) != 0) |
1743 | 1750 | { |