Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e5dfc99 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Dave Chinner
Browse files

vfs: combine the clone and dedupe into a single remap_file_range



Combine the clone_file_range and dedupe_file_range operations into a
single remap_file_range file operation dispatch since they're
fundamentally the same operation.  The differences between the two can
be made in the prep functions.

Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarAmir Goldstein <amir73il@gmail.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 6095028b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -622,3 +622,8 @@ in your dentry operations instead.
	alloc_file_clone(file, flags, ops) does not affect any caller's references.
	On success you get a new struct file sharing the mount/dentry with the
	original, on failure - ERR_PTR().
--
[mandatory]
	->clone_file_range() and ->dedupe_file_range have been replaced with
	->remap_file_range().  See Documentation/filesystems/vfs.txt for more
	information.
+13 −7
Original line number Diff line number Diff line
@@ -883,8 +883,9 @@ struct file_operations {
	unsigned (*mmap_capabilities)(struct file *);
#endif
	ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, loff_t, size_t, unsigned int);
	int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t, u64);
	int (*dedupe_file_range)(struct file *, loff_t, struct file *, loff_t, u64);
	int (*remap_file_range)(struct file *file_in, loff_t pos_in,
				struct file *file_out, loff_t pos_out,
				u64 len, unsigned int remap_flags);
	int (*fadvise)(struct file *, loff_t, loff_t, int);
};

@@ -960,11 +961,16 @@ otherwise noted.

  copy_file_range: called by the copy_file_range(2) system call.

  clone_file_range: called by the ioctl(2) system call for FICLONERANGE and
	FICLONE commands.

  dedupe_file_range: called by the ioctl(2) system call for FIDEDUPERANGE
	command.
  remap_file_range: called by the ioctl(2) system call for FICLONERANGE and
	FICLONE and FIDEDUPERANGE commands to remap file ranges.  An
	implementation should remap len bytes at pos_in of the source file into
	the dest file at pos_out.  Implementations must handle callers passing
	in len == 0; this means "remap to the end of the source file".  The
	return value should be zero if all bytes were remapped, or the usual
	negative error code if the remapping did not succeed completely.
	The remap_flags parameter accepts REMAP_FILE_* flags.  If
	REMAP_FILE_DEDUP is set then the implementation must only remap if the
	requested file ranges have identical contents.

  fadvise: possibly called by the fadvise64() system call.

+3 −5
Original line number Diff line number Diff line
@@ -3218,9 +3218,6 @@ void btrfs_get_block_group_info(struct list_head *groups_list,
				struct btrfs_ioctl_space_info *space);
void btrfs_update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
			       struct btrfs_ioctl_balance_args *bargs);
int btrfs_dedupe_file_range(struct file *src_file, loff_t src_loff,
			    struct file *dst_file, loff_t dst_loff,
			    u64 olen);

/* file.c */
int __init btrfs_auto_defrag_init(void);
@@ -3250,8 +3247,9 @@ int btrfs_dirty_pages(struct inode *inode, struct page **pages,
		      size_t num_pages, loff_t pos, size_t write_bytes,
		      struct extent_state **cached);
int btrfs_fdatawrite_range(struct inode *inode, loff_t start, loff_t end);
int btrfs_clone_file_range(struct file *file_in, loff_t pos_in,
			   struct file *file_out, loff_t pos_out, u64 len);
int btrfs_remap_file_range(struct file *file_in, loff_t pos_in,
			   struct file *file_out, loff_t pos_out, u64 len,
			   unsigned int remap_flags);

/* tree-defrag.c */
int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
+1 −2
Original line number Diff line number Diff line
@@ -3269,8 +3269,7 @@ const struct file_operations btrfs_file_operations = {
#ifdef CONFIG_COMPAT
	.compat_ioctl	= btrfs_compat_ioctl,
#endif
	.clone_file_range = btrfs_clone_file_range,
	.dedupe_file_range = btrfs_dedupe_file_range,
	.remap_file_range = btrfs_remap_file_range,
};

void __cold btrfs_auto_defrag_exit(void)
+23 −22
Original line number Diff line number Diff line
@@ -3627,26 +3627,6 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
	return ret;
}

int btrfs_dedupe_file_range(struct file *src_file, loff_t src_loff,
			    struct file *dst_file, loff_t dst_loff,
			    u64 olen)
{
	struct inode *src = file_inode(src_file);
	struct inode *dst = file_inode(dst_file);
	u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;

	if (WARN_ON_ONCE(bs < PAGE_SIZE)) {
		/*
		 * Btrfs does not support blocksize < page_size. As a
		 * result, btrfs_cmp_data() won't correctly handle
		 * this situation without an update.
		 */
		return -EINVAL;
	}

	return btrfs_extent_same(src, src_loff, olen, dst, dst_loff);
}

static int clone_finish_inode_update(struct btrfs_trans_handle *trans,
				     struct inode *inode,
				     u64 endoff,
@@ -4348,9 +4328,30 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
	return ret;
}

int btrfs_clone_file_range(struct file *src_file, loff_t off,
		struct file *dst_file, loff_t destoff, u64 len)
int btrfs_remap_file_range(struct file *src_file, loff_t off,
		struct file *dst_file, loff_t destoff, u64 len,
		unsigned int remap_flags)
{
	if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
		return -EINVAL;

	if (remap_flags & REMAP_FILE_DEDUP) {
		struct inode *src = file_inode(src_file);
		struct inode *dst = file_inode(dst_file);
		u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;

		if (WARN_ON_ONCE(bs < PAGE_SIZE)) {
			/*
			 * Btrfs does not support blocksize < page_size. As a
			 * result, btrfs_cmp_data() won't correctly handle
			 * this situation without an update.
			 */
			return -EINVAL;
		}

		return btrfs_extent_same(src, off, len, dst, destoff);
	}

	return btrfs_clone_files(dst_file, src_file, off, len, destoff);
}

Loading