From 677fc0562a237f6cfc1551e37673707096905ca7 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 4 Nov 2019 22:22:13 -0500 Subject: [PATCH] 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 Signed-off-by: Kent Overstreet --- fs/bcachefs/fs-io.c | 13 ++++++------- fs/bcachefs/reflink.c | 4 +++- 2 files changed, 9 insertions(+), 8 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); diff --git a/fs/bcachefs/reflink.c b/fs/bcachefs/reflink.c index 6d45ae24479d..6e71c5e8f9a2 100644 --- a/fs/bcachefs/reflink.c +++ b/fs/bcachefs/reflink.c @@ -290,10 +290,12 @@ err: ret2 = PTR_ERR_OR_ZERO(inode_iter); 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) ?: bch2_trans_commit(&trans, NULL, journal_seq, BTREE_INSERT_ATOMIC); + } } while (ret2 == -EINTR); ret = bch2_trans_exit(&trans) ?: ret;