Commit a99b1caf authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Truncate/fpunch now works on block boundaries, not page

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 2ba5d38b
...@@ -2324,8 +2324,10 @@ static int __bch2_truncate_page(struct bch_inode_info *inode, ...@@ -2324,8 +2324,10 @@ static int __bch2_truncate_page(struct bch_inode_info *inode,
{ {
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct address_space *mapping = inode->v.i_mapping; struct address_space *mapping = inode->v.i_mapping;
struct bch_page_state *s;
unsigned start_offset = start & (PAGE_SIZE - 1); unsigned start_offset = start & (PAGE_SIZE - 1);
unsigned end_offset = ((end - 1) & (PAGE_SIZE - 1)) + 1; unsigned end_offset = ((end - 1) & (PAGE_SIZE - 1)) + 1;
unsigned i;
struct page *page; struct page *page;
int ret = 0; int ret = 0;
...@@ -2357,12 +2359,32 @@ static int __bch2_truncate_page(struct bch_inode_info *inode, ...@@ -2357,12 +2359,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)) { if (!PageUptodate(page)) {
ret = bch2_read_single_page(page, mapping); ret = bch2_read_single_page(page, mapping);
if (ret) if (ret)
goto unlock; 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. * Bit of a hack - we don't want truncate to fail due to -ENOSPC.
* *
...@@ -2372,14 +2394,6 @@ static int __bch2_truncate_page(struct bch_inode_info *inode, ...@@ -2372,14 +2394,6 @@ static int __bch2_truncate_page(struct bch_inode_info *inode,
ret = bch2_get_page_disk_reservation(c, inode, page, false); ret = bch2_get_page_disk_reservation(c, inode, page, false);
BUG_ON(ret); 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);
filemap_dirty_folio(mapping, page_folio(page)); filemap_dirty_folio(mapping, page_folio(page));
unlock: unlock:
unlock_page(page); unlock_page(page);
...@@ -2391,7 +2405,7 @@ static int __bch2_truncate_page(struct bch_inode_info *inode, ...@@ -2391,7 +2405,7 @@ static int __bch2_truncate_page(struct bch_inode_info *inode,
static int bch2_truncate_page(struct bch_inode_info *inode, loff_t from) static int bch2_truncate_page(struct bch_inode_info *inode, loff_t from)
{ {
return __bch2_truncate_page(inode, from >> PAGE_SHIFT, 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) static int bch2_extend(struct bch_inode_info *inode, struct iattr *iattr)
...@@ -2483,12 +2497,8 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr) ...@@ -2483,12 +2497,8 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr)
truncate_setsize(&inode->v, iattr->ia_size); 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, 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); U64_MAX, &inode->ei_journal_seq);
if (unlikely(ret)) if (unlikely(ret))
goto err; goto err;
...@@ -2510,8 +2520,8 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr) ...@@ -2510,8 +2520,8 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr)
static long bch2_fpunch(struct bch_inode_info *inode, loff_t offset, loff_t len) 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 bch_fs *c = inode->v.i_sb->s_fs_info;
u64 discard_start = round_up(offset, PAGE_SIZE) >> 9; u64 discard_start = round_up(offset, block_bytes(c)) >> 9;
u64 discard_end = round_down(offset + len, PAGE_SIZE) >> 9; u64 discard_end = round_down(offset + len, block_bytes(c)) >> 9;
int ret = 0; int ret = 0;
inode_lock(&inode->v); inode_lock(&inode->v);
...@@ -2596,7 +2606,7 @@ static long bch2_fcollapse(struct bch_inode_info *inode, ...@@ -2596,7 +2606,7 @@ static long bch2_fcollapse(struct bch_inode_info *inode,
while (bkey_cmp(dst->pos, while (bkey_cmp(dst->pos,
POS(inode->v.i_ino, 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; struct disk_reservation disk_res;
ret = bch2_btree_iter_traverse(dst); ret = bch2_btree_iter_traverse(dst);
...@@ -2671,8 +2681,9 @@ static long bch2_fallocate(struct bch_inode_info *inode, int mode, ...@@ -2671,8 +2681,9 @@ static long bch2_fallocate(struct bch_inode_info *inode, int mode,
struct btree_trans trans; struct btree_trans trans;
struct btree_iter *iter; struct btree_iter *iter;
struct bpos end_pos; 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 sectors;
unsigned replicas = io_opts(c, inode).data_replicas; unsigned replicas = io_opts(c, inode).data_replicas;
int ret; int ret;
...@@ -2704,12 +2715,6 @@ static long bch2_fallocate(struct bch_inode_info *inode, int mode, ...@@ -2704,12 +2715,6 @@ static long bch2_fallocate(struct bch_inode_info *inode, int mode,
goto err; goto err;
truncate_pagecache_range(&inode->v, offset, end - 1); 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, iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS,
......
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