[PATCH 73/76] xfs: use new vfs reflink and dedup function pointers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Use the new VFS function pointers for copy_file_range and dedupe_data.

Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
---
 fs/xfs/xfs_file.c  |   61 ++++++++++++++++
 fs/xfs/xfs_ioctl.c |  199 ----------------------------------------------------
 2 files changed, 60 insertions(+), 200 deletions(-)


diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index e6bc6ab..0d96a37 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1081,7 +1081,7 @@ xfs_file_wait_for_io(
 }
 
 /* Hook up to the VFS reflink function */
-int
+STATIC int
 xfs_file_share_range(
 	struct file	*file_in,
 	loff_t		pos_in,
@@ -1175,6 +1175,62 @@ out_unlock:
 	return ret;
 }
 
+STATIC ssize_t
+xfs_file_copy_range(
+	struct file	*file_in,
+	loff_t		pos_in,
+	struct file	*file_out,
+	loff_t		pos_out,
+	size_t		len,
+	unsigned int	flags)
+{
+	int		error;
+
+	error = xfs_file_share_range(file_in, pos_in, file_out, pos_out,
+				     len, false);
+	if (error)
+		return error;
+	return len;
+}
+
+STATIC int
+xfs_file_clone_range(
+	struct file	*file_in,
+	loff_t		pos_in,
+	struct file	*file_out,
+	loff_t		pos_out,
+	u64		len)
+{
+	return xfs_file_share_range(file_in, pos_in, file_out, pos_out,
+				     len, false);
+}
+
+#define XFS_MAX_DEDUPE_LEN	(16 * 1024 * 1024)
+STATIC ssize_t
+xfs_file_dedupe_range(
+	struct file	*src_file,
+	u64		loff,
+	u64		len,
+	struct file	*dst_file,
+	u64		dst_loff)
+{
+	int		error;
+
+	/*
+	 * Limit the total length we will dedupe for each operation.
+	 * This is intended to bound the total time spent in this
+	 * ioctl to something sane.
+	 */
+	if (len > XFS_MAX_DEDUPE_LEN)
+		len = XFS_MAX_DEDUPE_LEN;
+
+	error = xfs_file_share_range(src_file, loff, dst_file, dst_loff,
+				     len, true);
+	if (error)
+		return error;
+	return len;
+}
+
 STATIC int
 xfs_file_open(
 	struct inode	*inode,
@@ -1811,6 +1867,9 @@ const struct file_operations xfs_file_operations = {
 	.release	= xfs_file_release,
 	.fsync		= xfs_file_fsync,
 	.fallocate	= xfs_file_fallocate,
+	.copy_file_range = xfs_file_copy_range,
+	.clone_file_range = xfs_file_clone_range,
+	.dedupe_file_range = xfs_file_dedupe_range,
 };
 
 const struct file_operations xfs_dir_file_operations = {
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 29dc36c..7562f14 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1536,159 +1536,6 @@ xfs_ioc_swapext(
 	return error;
 }
 
-extern int xfs_file_share_range(struct file *file_in, loff_t pos_in,
-		struct file *file_out, loff_t pos_out, size_t len,
-		bool is_dedupe);
-
-/*
- * For reflink, validate the VFS parameters, convert them into the XFS
- * equivalents, and then call the internal reflink function.
- */
-STATIC int
-xfs_ioctl_reflink(
-	struct file	*file_in,
-	loff_t		pos_in,
-	struct file	*file_out,
-	loff_t		pos_out,
-	size_t		len,
-	bool		is_dedupe)
-{
-	int		error;
-
-	/* Do we have the correct permissions? */
-	if (!(file_in->f_mode & FMODE_READ) ||
-	    !(file_out->f_mode & FMODE_WRITE) ||
-	    (file_out->f_flags & O_APPEND))
-		return -EBADF;
-
-	error = mnt_want_write_file(file_out);
-	if (error)
-		return error;
-
-	error = xfs_file_share_range(file_in, pos_in, file_out, pos_out, len,
-			is_dedupe);
-	if (error)
-		goto out_drop;
-
-	fsnotify_access(file_in);
-	add_rchar(current, len);
-	fsnotify_modify(file_out);
-	add_wchar(current, len);
-	inc_syscr(current);
-	inc_syscw(current);
-
-out_drop:
-	mnt_drop_write_file(file_out);
-	return error;
-}
-
-#define XFS_MAX_DEDUPE_LEN	(16 * 1024 * 1024)
-
-static long
-xfs_ioctl_file_extent_same(
-	struct file			*file,
-	struct xfs_extent_data __user	*argp)
-{
-	struct xfs_extent_data		*same = NULL;
-	struct xfs_extent_data_info	*info;
-	struct inode			*src;
-	u64				off;
-	u64				len;
-	int				i;
-	int				ret;
-	unsigned long			size;
-	bool				is_admin;
-	u16				count;
-
-	is_admin = capable(CAP_SYS_ADMIN);
-	src = file_inode(file);
-	if (!(file->f_mode & FMODE_READ))
-		return -EINVAL;
-
-	if (get_user(count, &argp->dest_count)) {
-		ret = -EFAULT;
-		goto out;
-	}
-
-	size = offsetof(struct xfs_extent_data __user,
-			info[count]);
-
-	same = memdup_user(argp, size);
-
-	if (IS_ERR(same)) {
-		ret = PTR_ERR(same);
-		goto out;
-	}
-
-	off = same->logical_offset;
-	len = same->length;
-
-	/*
-	 * Limit the total length we will dedupe for each operation.
-	 * This is intended to bound the total time spent in this
-	 * ioctl to something sane.
-	 */
-	if (len > XFS_MAX_DEDUPE_LEN)
-		len = XFS_MAX_DEDUPE_LEN;
-
-	ret = -EISDIR;
-	if (S_ISDIR(src->i_mode))
-		goto out;
-
-	ret = -EACCES;
-	if (!S_ISREG(src->i_mode))
-		goto out;
-
-	/* pre-format output fields to sane values */
-	for (i = 0; i < count; i++) {
-		same->info[i].bytes_deduped = 0ULL;
-		same->info[i].status = 0;
-	}
-
-	for (i = 0, info = same->info; i < count; i++, info++) {
-		struct inode *dst;
-		struct fd dst_file = fdget(info->fd);
-
-		if (!dst_file.file) {
-			info->status = -EBADF;
-			continue;
-		}
-		dst = file_inode(dst_file.file);
-
-		trace_xfs_ioctl_file_extent_same(file_inode(file), off, len,
-				dst, info->logical_offset);
-
-		info->bytes_deduped = 0;
-		if (!(is_admin || (dst_file.file->f_mode & FMODE_WRITE))) {
-			info->status = -EINVAL;
-		} else if (file->f_path.mnt != dst_file.file->f_path.mnt) {
-			info->status = -EXDEV;
-		} else if (S_ISDIR(dst->i_mode)) {
-			info->status = -EISDIR;
-		} else if (!S_ISREG(dst->i_mode)) {
-			info->status = -EOPNOTSUPP;
-		} else {
-			ret = xfs_ioctl_reflink(file, off, dst_file.file,
-					info->logical_offset, len, true);
-			if (ret == -EBADE)
-				info->status = XFS_EXTENT_DATA_DIFFERS;
-			else if (ret == 0)
-				info->bytes_deduped = len;
-			else
-				info->status = ret;
-		}
-		fdput(dst_file);
-	}
-
-	ret = copy_to_user(argp, same, size);
-	if (ret)
-		ret = -EFAULT;
-
-out:
-	kfree(same);
-	return ret;
-}
-
 /*
  * Note: some of the ioctl's return positive numbers as a
  * byte count indicating success, such as readlink_by_handle.
@@ -1987,52 +1834,6 @@ xfs_file_ioctl(
 		return xfs_icache_free_eofblocks(mp, &keofb);
 	}
 
-	case XFS_IOC_CLONE: {
-		struct fd src;
-
-		src = fdget(p);
-		if (!src.file)
-			return -EBADF;
-
-		trace_xfs_ioctl_clone(file_inode(src.file), file_inode(filp));
-
-		error = xfs_ioctl_reflink(src.file, 0, filp, 0, ~0ULL, false);
-		fdput(src);
-		if (error > 0)
-			error = 0;
-
-		return error;
-	}
-
-	case XFS_IOC_CLONE_RANGE: {
-		struct fd src;
-		struct xfs_clone_args args;
-
-		if (copy_from_user(&args, arg, sizeof(args)))
-			return -EFAULT;
-		src = fdget(args.src_fd);
-		if (!src.file)
-			return -EBADF;
-		if (args.src_length == 0)
-			args.src_length = ~0ULL;
-
-		trace_xfs_ioctl_clone_range(file_inode(src.file),
-				args.src_offset, args.src_length,
-				file_inode(filp), args.dest_offset);
-
-		error = xfs_ioctl_reflink(src.file, args.src_offset, filp,
-					  args.dest_offset, args.src_length,
-					  false);
-		fdput(src);
-		if (error > 0)
-			error = 0;
-
-		return error;
-	}
-
-	case XFS_IOC_FILE_EXTENT_SAME:
-		return xfs_ioctl_file_extent_same(filp, arg);
-
 	default:
 		return -ENOTTY;
 	}

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs



[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux