diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-08-06 11:19:58 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2019-08-09 16:41:08 -0400 |
commit | e6cf56e2c3003cfe7108d9df80720cb2e07395f9 (patch) | |
tree | 24e725eff5a623958eb3ba42dc8c7f438995d61c | |
parent | fe89105140f3f4aec4b6590bd3be10ace5fb2ffe (diff) |
bcachefs: Truncate/fpunch now works on block boundaries, not page
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/fs-io.c | 55 |
1 files changed, 30 insertions, 25 deletions
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c index 7e8303b6cc23..2cb1d4f61ad2 100644 --- a/fs/bcachefs/fs-io.c +++ b/fs/bcachefs/fs-io.c @@ -2338,8 +2338,10 @@ static int __bch2_truncate_page(struct bch_inode_info *inode, { struct bch_fs *c = inode->v.i_sb->s_fs_info; struct address_space *mapping = inode->v.i_mapping; + struct bch_page_state *s; unsigned start_offset = start & (PAGE_SIZE - 1); unsigned end_offset = ((end - 1) & (PAGE_SIZE - 1)) + 1; + unsigned i; struct page *page; int ret = 0; @@ -2371,12 +2373,32 @@ static int __bch2_truncate_page(struct bch_inode_info *inode, } } + s = bch2_page_state_create(page, 0); + if (!s) { + ret = -ENOMEM; + goto unlock; + } + if (!PageUptodate(page)) { ret = bch2_read_single_page(page, mapping); if (ret) goto unlock; } + if (index != start >> PAGE_SHIFT) + start_offset = 0; + if (index != end >> PAGE_SHIFT) + end_offset = PAGE_SIZE; + + for (i = round_up(start_offset, block_bytes(c)) >> 9; + i < round_down(end_offset, block_bytes(c)) >> 9; + i++) { + s->s[i].nr_replicas = 0; + s->s[i].state = SECTOR_UNALLOCATED; + } + + zero_user_segment(page, start_offset, end_offset); + /* * Bit of a hack - we don't want truncate to fail due to -ENOSPC. * @@ -2386,14 +2408,6 @@ static int __bch2_truncate_page(struct bch_inode_info *inode, ret = bch2_get_page_disk_reservation(c, inode, page, false); BUG_ON(ret); - if (index == start >> PAGE_SHIFT && - index == end >> PAGE_SHIFT) - zero_user_segment(page, start_offset, end_offset); - else if (index == start >> PAGE_SHIFT) - zero_user_segment(page, start_offset, PAGE_SIZE); - else if (index == end >> PAGE_SHIFT) - zero_user_segment(page, 0, end_offset); - __set_page_dirty_nobuffers(page); unlock: unlock_page(page); @@ -2405,7 +2419,7 @@ out: static int bch2_truncate_page(struct bch_inode_info *inode, loff_t from) { return __bch2_truncate_page(inode, from >> PAGE_SHIFT, - from, from + PAGE_SIZE); + from, round_up(from, PAGE_SIZE)); } static int bch2_extend(struct bch_inode_info *inode, struct iattr *iattr) @@ -2496,12 +2510,8 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr) truncate_setsize(&inode->v, iattr->ia_size); - /* - * XXX: need a comment explaining why PAGE_SIZE and not block_bytes() - * here: - */ ret = __bch2_fpunch(c, inode, - round_up(iattr->ia_size, PAGE_SIZE) >> 9, + round_up(iattr->ia_size, block_bytes(c)) >> 9, U64_MAX, &inode->ei_journal_seq); if (unlikely(ret)) goto err; @@ -2523,8 +2533,8 @@ static long bch2_fpunch(struct bch_inode_info *inode, loff_t offset, loff_t len) { struct bch_fs *c = inode->v.i_sb->s_fs_info; struct address_space *mapping = inode->v.i_mapping; - u64 discard_start = round_up(offset, PAGE_SIZE) >> 9; - u64 discard_end = round_down(offset + len, PAGE_SIZE) >> 9; + u64 discard_start = round_up(offset, block_bytes(c)) >> 9; + u64 discard_end = round_down(offset + len, block_bytes(c)) >> 9; int ret = 0; inode_lock(&inode->v); @@ -2609,7 +2619,7 @@ static long bch2_fcollapse(struct bch_inode_info *inode, while (bkey_cmp(dst->pos, POS(inode->v.i_ino, - round_up(new_size, PAGE_SIZE) >> 9)) < 0) { + round_up(new_size, block_bytes(c)) >> 9)) < 0) { struct disk_reservation disk_res; ret = bch2_btree_iter_traverse(dst); @@ -2684,8 +2694,9 @@ static long bch2_fallocate(struct bch_inode_info *inode, int mode, struct btree_trans trans; struct btree_iter *iter; struct bpos end_pos; - loff_t block_start, block_end; - loff_t end = offset + len; + loff_t end = offset + len; + loff_t block_start = round_down(offset, block_bytes(c)); + loff_t block_end = round_up(end, block_bytes(c)); unsigned sectors; unsigned replicas = io_opts(c, inode).data_replicas; int ret; @@ -2717,12 +2728,6 @@ static long bch2_fallocate(struct bch_inode_info *inode, int mode, goto err; truncate_pagecache_range(&inode->v, offset, end - 1); - - block_start = round_up(offset, PAGE_SIZE); - block_end = round_down(end, PAGE_SIZE); - } else { - block_start = round_down(offset, PAGE_SIZE); - block_end = round_up(end, PAGE_SIZE); } iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, |