Commit 677fc056 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

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: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 4a1d8d3e
...@@ -2799,8 +2799,8 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src, ...@@ -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_inode_info *dst = file_bch_inode(file_dst);
struct bch_fs *c = src->v.i_sb->s_fs_info; struct bch_fs *c = src->v.i_sb->s_fs_info;
s64 i_sectors_delta = 0; s64 i_sectors_delta = 0;
u64 aligned_len;
loff_t ret = 0; loff_t ret = 0;
loff_t aligned_len;
if (remap_flags & ~(REMAP_FILE_DEDUP|REMAP_FILE_ADVISORY)) if (remap_flags & ~(REMAP_FILE_DEDUP|REMAP_FILE_ADVISORY))
return -EINVAL; return -EINVAL;
...@@ -2829,10 +2829,10 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src, ...@@ -2829,10 +2829,10 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src,
if (ret < 0 || len == 0) if (ret < 0 || len == 0)
goto err; 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, ret = write_invalidate_inode_pages_range(dst->v.i_mapping,
pos_dst, pos_dst + aligned_len); pos_dst, pos_dst + len - 1);
if (ret) if (ret)
goto err; goto err;
...@@ -2847,18 +2847,17 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src, ...@@ -2847,18 +2847,17 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src,
if (ret < 0) if (ret < 0)
goto err; goto err;
ret <<= 9;
/* /*
* due to alignment, we might have remapped slightly more than requsted * 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 */ /* XXX get a quota reservation */
i_sectors_acct(c, dst, NULL, i_sectors_delta); i_sectors_acct(c, dst, NULL, i_sectors_delta);
spin_lock(&dst->v.i_lock); spin_lock(&dst->v.i_lock);
if (pos_dst + len > dst->v.i_size) if (pos_dst + ret > dst->v.i_size)
i_size_write(&dst->v, pos_dst + len); i_size_write(&dst->v, pos_dst + ret);
spin_unlock(&dst->v.i_lock); spin_unlock(&dst->v.i_lock);
err: err:
bch2_unlock_inodes(INODE_LOCK|INODE_PAGECACHE_BLOCK, src, dst); bch2_unlock_inodes(INODE_LOCK|INODE_PAGECACHE_BLOCK, src, dst);
......
...@@ -290,10 +290,12 @@ s64 bch2_remap_range(struct bch_fs *c, ...@@ -290,10 +290,12 @@ s64 bch2_remap_range(struct bch_fs *c,
ret2 = PTR_ERR_OR_ZERO(inode_iter); ret2 = PTR_ERR_OR_ZERO(inode_iter);
if (!ret2 && if (!ret2 &&
inode_u.bi_size < new_i_size) inode_u.bi_size < new_i_size) {
inode_u.bi_size = new_i_size;
ret2 = bch2_inode_write(&trans, inode_iter, &inode_u) ?: ret2 = bch2_inode_write(&trans, inode_iter, &inode_u) ?:
bch2_trans_commit(&trans, NULL, journal_seq, bch2_trans_commit(&trans, NULL, journal_seq,
BTREE_INSERT_ATOMIC); BTREE_INSERT_ATOMIC);
}
} while (ret2 == -EINTR); } while (ret2 == -EINTR);
ret = bch2_trans_exit(&trans) ?: ret; ret = bch2_trans_exit(&trans) ?: ret;
......
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