mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
vfs: enable remap callers that can handle short operations
Plumb in a remap flag that enables the filesystem remap handler to shorten remapping requests for callers that can handle it. Now copy_file_range can report partial success (in case we run up against alignment problems, resource limits, etc.). We also enable CAN_SHORTEN for fideduperange to maintain existing userspace-visible behavior where xfs/btrfs shorten the dedupe range to avoid stale post-eof data exposure. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
committed by
Dave Chinner
parent
df36583619
commit
eca3654e3c
@@ -1593,7 +1593,8 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
|
||||
|
||||
cloned = file_in->f_op->remap_file_range(file_in, pos_in,
|
||||
file_out, pos_out,
|
||||
min_t(loff_t, MAX_RW_COUNT, len), 0);
|
||||
min_t(loff_t, MAX_RW_COUNT, len),
|
||||
REMAP_FILE_CAN_SHORTEN);
|
||||
if (cloned > 0) {
|
||||
ret = cloned;
|
||||
goto done;
|
||||
@@ -1721,6 +1722,8 @@ static int remap_verify_area(struct file *file, loff_t pos, loff_t len,
|
||||
* can't meaningfully compare post-EOF contents.
|
||||
*
|
||||
* For clone we only link a partial EOF block above the destination file's EOF.
|
||||
*
|
||||
* Shorten the request if possible.
|
||||
*/
|
||||
static int generic_remap_check_len(struct inode *inode_in,
|
||||
struct inode *inode_out,
|
||||
@@ -1729,16 +1732,24 @@ static int generic_remap_check_len(struct inode *inode_in,
|
||||
unsigned int remap_flags)
|
||||
{
|
||||
u64 blkmask = i_blocksize(inode_in) - 1;
|
||||
loff_t new_len = *len;
|
||||
|
||||
if ((*len & blkmask) == 0)
|
||||
return 0;
|
||||
|
||||
if (remap_flags & REMAP_FILE_DEDUP)
|
||||
*len &= ~blkmask;
|
||||
else if (pos_out + *len < i_size_read(inode_out))
|
||||
return -EINVAL;
|
||||
if ((remap_flags & REMAP_FILE_DEDUP) ||
|
||||
pos_out + *len < i_size_read(inode_out))
|
||||
new_len &= ~blkmask;
|
||||
|
||||
return 0;
|
||||
if (new_len == *len)
|
||||
return 0;
|
||||
|
||||
if (remap_flags & REMAP_FILE_CAN_SHORTEN) {
|
||||
*len = new_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (remap_flags & REMAP_FILE_DEDUP) ? -EBADE : -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2014,7 +2025,8 @@ loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos,
|
||||
{
|
||||
loff_t ret;
|
||||
|
||||
WARN_ON_ONCE(remap_flags & ~(REMAP_FILE_DEDUP));
|
||||
WARN_ON_ONCE(remap_flags & ~(REMAP_FILE_DEDUP |
|
||||
REMAP_FILE_CAN_SHORTEN));
|
||||
|
||||
ret = mnt_want_write_file(dst_file);
|
||||
if (ret)
|
||||
@@ -2115,7 +2127,7 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
|
||||
|
||||
deduped = vfs_dedupe_file_range_one(file, off, dst_file,
|
||||
info->dest_offset, len,
|
||||
0);
|
||||
REMAP_FILE_CAN_SHORTEN);
|
||||
if (deduped == -EBADE)
|
||||
info->status = FILE_DEDUPE_RANGE_DIFFERS;
|
||||
else if (deduped < 0)
|
||||
|
Reference in New Issue
Block a user