summaryrefslogtreecommitdiff
path: root/fs/bcachefs/fs-io.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-11-04 22:22:13 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:31 -0400
commit677fc0562a237f6cfc1551e37673707096905ca7 (patch)
tree092384642a5c7af378eb1ad62fcc8e9c5c5d7850 /fs/bcachefs/fs-io.c
parent4a1d8d3efcdedd0911941f236b2e3a6347f518c3 (diff)
downloadlwn-677fc0562a237f6cfc1551e37673707096905ca7.tar.gz
lwn-677fc0562a237f6cfc1551e37673707096905ca7.zip
bcachefs: Some reflink fixes
len might fit into a loff_t when aligned_len does not - make sure we use a u64 for aligned_len. Also, we weren't always extending the inode correctly. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/fs-io.c')
-rw-r--r--fs/bcachefs/fs-io.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index a1767ee85591..d17621b0713e 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -2799,8 +2799,8 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src,
struct bch_inode_info *dst = file_bch_inode(file_dst);
struct bch_fs *c = src->v.i_sb->s_fs_info;
s64 i_sectors_delta = 0;
+ u64 aligned_len;
loff_t ret = 0;
- loff_t aligned_len;
if (remap_flags & ~(REMAP_FILE_DEDUP|REMAP_FILE_ADVISORY))
return -EINVAL;
@@ -2829,10 +2829,10 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src,
if (ret < 0 || len == 0)
goto err;
- aligned_len = round_up(len, block_bytes(c));
+ aligned_len = round_up((u64) len, block_bytes(c));
ret = write_invalidate_inode_pages_range(dst->v.i_mapping,
- pos_dst, pos_dst + aligned_len);
+ pos_dst, pos_dst + len - 1);
if (ret)
goto err;
@@ -2847,18 +2847,17 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src,
if (ret < 0)
goto err;
- ret <<= 9;
/*
* due to alignment, we might have remapped slightly more than requsted
*/
- ret = min(ret, len);
+ ret = min((u64) ret << 9, (u64) len);
/* XXX get a quota reservation */
i_sectors_acct(c, dst, NULL, i_sectors_delta);
spin_lock(&dst->v.i_lock);
- if (pos_dst + len > dst->v.i_size)
- i_size_write(&dst->v, pos_dst + len);
+ if (pos_dst + ret > dst->v.i_size)
+ i_size_write(&dst->v, pos_dst + ret);
spin_unlock(&dst->v.i_lock);
err:
bch2_unlock_inodes(INODE_LOCK|INODE_PAGECACHE_BLOCK, src, dst);