Commit 3fc9f5e4 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Dave Chinner

xfs: remove xfs_reflink_remap_range

Since xfs_file_remap_range is a thin wrapper, move the contents of
xfs_reflink_remap_range into the shell.  This cuts down on the vfs
calls being made from internal xfs code.
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 7a6ccf00
...@@ -919,20 +919,67 @@ xfs_file_fallocate( ...@@ -919,20 +919,67 @@ xfs_file_fallocate(
return error; return error;
} }
STATIC loff_t
loff_t
xfs_file_remap_range( xfs_file_remap_range(
struct file *file_in, struct file *file_in,
loff_t pos_in, loff_t pos_in,
struct file *file_out, struct file *file_out,
loff_t pos_out, loff_t pos_out,
loff_t len, loff_t len,
unsigned int remap_flags) unsigned int remap_flags)
{ {
struct inode *inode_in = file_inode(file_in);
struct xfs_inode *src = XFS_I(inode_in);
struct inode *inode_out = file_inode(file_out);
struct xfs_inode *dest = XFS_I(inode_out);
struct xfs_mount *mp = src->i_mount;
loff_t remapped = 0;
xfs_extlen_t cowextsize;
int ret;
if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
return -EINVAL; return -EINVAL;
return xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out, if (!xfs_sb_version_hasreflink(&mp->m_sb))
len, remap_flags); return -EOPNOTSUPP;
if (XFS_FORCED_SHUTDOWN(mp))
return -EIO;
/* Prepare and then clone file data. */
ret = xfs_reflink_remap_prep(file_in, pos_in, file_out, pos_out,
&len, remap_flags);
if (ret < 0 || len == 0)
return ret;
trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out);
ret = xfs_reflink_remap_blocks(src, pos_in, dest, pos_out, len,
&remapped);
if (ret)
goto out_unlock;
/*
* Carry the cowextsize hint from src to dest if we're sharing the
* entire source file to the entire destination file, the source file
* has a cowextsize hint, and the destination file does not.
*/
cowextsize = 0;
if (pos_in == 0 && len == i_size_read(inode_in) &&
(src->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) &&
pos_out == 0 && len >= i_size_read(inode_out) &&
!(dest->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE))
cowextsize = src->i_d.di_cowextsize;
ret = xfs_reflink_update_dest(dest, pos_out + len, cowextsize,
remap_flags);
out_unlock:
xfs_reflink_remap_unlock(file_in, file_out);
if (ret)
trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
return remapped > 0 ? remapped : ret;
} }
STATIC int STATIC int
......
...@@ -916,7 +916,7 @@ xfs_reflink_set_inode_flag( ...@@ -916,7 +916,7 @@ xfs_reflink_set_inode_flag(
/* /*
* Update destination inode size & cowextsize hint, if necessary. * Update destination inode size & cowextsize hint, if necessary.
*/ */
STATIC int int
xfs_reflink_update_dest( xfs_reflink_update_dest(
struct xfs_inode *dest, struct xfs_inode *dest,
xfs_off_t newlen, xfs_off_t newlen,
...@@ -1116,7 +1116,7 @@ xfs_reflink_remap_extent( ...@@ -1116,7 +1116,7 @@ xfs_reflink_remap_extent(
/* /*
* Iteratively remap one file's extents (and holes) to another's. * Iteratively remap one file's extents (and holes) to another's.
*/ */
STATIC int int
xfs_reflink_remap_blocks( xfs_reflink_remap_blocks(
struct xfs_inode *src, struct xfs_inode *src,
loff_t pos_in, loff_t pos_in,
...@@ -1232,7 +1232,7 @@ xfs_iolock_two_inodes_and_break_layout( ...@@ -1232,7 +1232,7 @@ xfs_iolock_two_inodes_and_break_layout(
} }
/* Unlock both inodes after they've been prepped for a range clone. */ /* Unlock both inodes after they've been prepped for a range clone. */
STATIC void void
xfs_reflink_remap_unlock( xfs_reflink_remap_unlock(
struct file *file_in, struct file *file_in,
struct file *file_out) struct file *file_out)
...@@ -1300,7 +1300,7 @@ xfs_reflink_zero_posteof( ...@@ -1300,7 +1300,7 @@ xfs_reflink_zero_posteof(
* stale data in the destination file. Hence we reject these clone attempts with * stale data in the destination file. Hence we reject these clone attempts with
* -EINVAL in this case. * -EINVAL in this case.
*/ */
STATIC int int
xfs_reflink_remap_prep( xfs_reflink_remap_prep(
struct file *file_in, struct file *file_in,
loff_t pos_in, loff_t pos_in,
...@@ -1370,68 +1370,6 @@ xfs_reflink_remap_prep( ...@@ -1370,68 +1370,6 @@ xfs_reflink_remap_prep(
return ret; return ret;
} }
/*
* Link a range of blocks from one file to another.
*/
loff_t
xfs_reflink_remap_range(
struct file *file_in,
loff_t pos_in,
struct file *file_out,
loff_t pos_out,
loff_t len,
unsigned int remap_flags)
{
struct inode *inode_in = file_inode(file_in);
struct xfs_inode *src = XFS_I(inode_in);
struct inode *inode_out = file_inode(file_out);
struct xfs_inode *dest = XFS_I(inode_out);
struct xfs_mount *mp = src->i_mount;
loff_t remapped = 0;
xfs_extlen_t cowextsize;
int ret;
if (!xfs_sb_version_hasreflink(&mp->m_sb))
return -EOPNOTSUPP;
if (XFS_FORCED_SHUTDOWN(mp))
return -EIO;
/* Prepare and then clone file data. */
ret = xfs_reflink_remap_prep(file_in, pos_in, file_out, pos_out,
&len, remap_flags);
if (ret < 0 || len == 0)
return ret;
trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out);
ret = xfs_reflink_remap_blocks(src, pos_in, dest, pos_out, len,
&remapped);
if (ret)
goto out_unlock;
/*
* Carry the cowextsize hint from src to dest if we're sharing the
* entire source file to the entire destination file, the source file
* has a cowextsize hint, and the destination file does not.
*/
cowextsize = 0;
if (pos_in == 0 && len == i_size_read(inode_in) &&
(src->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) &&
pos_out == 0 && len >= i_size_read(inode_out) &&
!(dest->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE))
cowextsize = src->i_d.di_cowextsize;
ret = xfs_reflink_update_dest(dest, pos_out + len, cowextsize,
remap_flags);
out_unlock:
xfs_reflink_remap_unlock(file_in, file_out);
if (ret)
trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
return remapped > 0 ? remapped : ret;
}
/* /*
* The user wants to preemptively CoW all shared blocks in this file, * The user wants to preemptively CoW all shared blocks in this file,
* which enables us to turn off the reflink flag. Iterate all * which enables us to turn off the reflink flag. Iterate all
......
...@@ -36,5 +36,15 @@ extern int xfs_reflink_clear_inode_flag(struct xfs_inode *ip, ...@@ -36,5 +36,15 @@ extern int xfs_reflink_clear_inode_flag(struct xfs_inode *ip,
struct xfs_trans **tpp); struct xfs_trans **tpp);
extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset, extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset,
xfs_off_t len); xfs_off_t len);
extern int xfs_reflink_remap_prep(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, loff_t *len,
unsigned int remap_flags);
extern int xfs_reflink_remap_blocks(struct xfs_inode *src, loff_t pos_in,
struct xfs_inode *dest, loff_t pos_out, loff_t remap_len,
loff_t *remapped);
extern int xfs_reflink_update_dest(struct xfs_inode *dest, xfs_off_t newlen,
xfs_extlen_t cowextsize, unsigned int remap_flags);
extern void xfs_reflink_remap_unlock(struct file *file_in,
struct file *file_out);
#endif /* __XFS_REFLINK_H */ #endif /* __XFS_REFLINK_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment