aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/file.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2016-11-09 17:13:11 -0500
committerDarrick J. Wong <darrick.wong@oracle.com>2016-12-10 15:39:45 -0500
commit29ac8e856cb3694e004037de595dec4ec53d42f2 (patch)
tree006df64270ecc128a4b837215c7ef78bd259ff51 /fs/ocfs2/file.c
parent86e59436d406d833a5da4a94aefb3c3be6b26053 (diff)
ocfs2: implement the VFS clone_range, copy_range, and dedupe_range features
Connect the new VFS clone_range, copy_range, and dedupe_range features to the existing reflink capability of ocfs2. Compared to the existing ocfs2 reflink ioctl We have to do things a little differently to support the VFS semantics (we can clone subranges of a file but we don't clone xattrs), but the VFS ioctls are more broadly supported. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> --- v2: Convert inline data files to extents files before reflinking, and fix i_blocks so that stat(2) output is correct. v3: Make zero-length dedupe consistent with btrfs behavior. v4: Use VFS double-inode lock routines and remove MAX_DEDUPE_LEN.
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r--fs/ocfs2/file.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index d261f3a91870..c4889655d32b 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1667,9 +1667,9 @@ static void ocfs2_calc_trunc_pos(struct inode *inode,
1667 *done = ret; 1667 *done = ret;
1668} 1668}
1669 1669
1670static int ocfs2_remove_inode_range(struct inode *inode, 1670int ocfs2_remove_inode_range(struct inode *inode,
1671 struct buffer_head *di_bh, u64 byte_start, 1671 struct buffer_head *di_bh, u64 byte_start,
1672 u64 byte_len) 1672 u64 byte_len)
1673{ 1673{
1674 int ret = 0, flags = 0, done = 0, i; 1674 int ret = 0, flags = 0, done = 0, i;
1675 u32 trunc_start, trunc_len, trunc_end, trunc_cpos, phys_cpos; 1675 u32 trunc_start, trunc_len, trunc_end, trunc_cpos, phys_cpos;
@@ -2439,6 +2439,31 @@ out:
2439 return offset; 2439 return offset;
2440} 2440}
2441 2441
2442static int ocfs2_file_clone_range(struct file *file_in,
2443 loff_t pos_in,
2444 struct file *file_out,
2445 loff_t pos_out,
2446 u64 len)
2447{
2448 return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out,
2449 len, false);
2450}
2451
2452static ssize_t ocfs2_file_dedupe_range(struct file *src_file,
2453 u64 loff,
2454 u64 len,
2455 struct file *dst_file,
2456 u64 dst_loff)
2457{
2458 int error;
2459
2460 error = ocfs2_reflink_remap_range(src_file, loff, dst_file, dst_loff,
2461 len, true);
2462 if (error)
2463 return error;
2464 return len;
2465}
2466
2442const struct inode_operations ocfs2_file_iops = { 2467const struct inode_operations ocfs2_file_iops = {
2443 .setattr = ocfs2_setattr, 2468 .setattr = ocfs2_setattr,
2444 .getattr = ocfs2_getattr, 2469 .getattr = ocfs2_getattr,
@@ -2478,6 +2503,8 @@ const struct file_operations ocfs2_fops = {
2478 .splice_read = generic_file_splice_read, 2503 .splice_read = generic_file_splice_read,
2479 .splice_write = iter_file_splice_write, 2504 .splice_write = iter_file_splice_write,
2480 .fallocate = ocfs2_fallocate, 2505 .fallocate = ocfs2_fallocate,
2506 .clone_file_range = ocfs2_file_clone_range,
2507 .dedupe_file_range = ocfs2_file_dedupe_range,
2481}; 2508};
2482 2509
2483const struct file_operations ocfs2_dops = { 2510const struct file_operations ocfs2_dops = {
@@ -2523,6 +2550,8 @@ const struct file_operations ocfs2_fops_no_plocks = {
2523 .splice_read = generic_file_splice_read, 2550 .splice_read = generic_file_splice_read,
2524 .splice_write = iter_file_splice_write, 2551 .splice_write = iter_file_splice_write,
2525 .fallocate = ocfs2_fallocate, 2552 .fallocate = ocfs2_fallocate,
2553 .clone_file_range = ocfs2_file_clone_range,
2554 .dedupe_file_range = ocfs2_file_dedupe_range,
2526}; 2555};
2527 2556
2528const struct file_operations ocfs2_dops_no_plocks = { 2557const struct file_operations ocfs2_dops_no_plocks = {