summaryrefslogtreecommitdiffstats
path: root/fs/bcachefs/fs-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/fs-io.c')
-rw-r--r--fs/bcachefs/fs-io.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index 8477e1df3397..acb2135a3235 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -1860,6 +1860,7 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
struct folio **fi, *f;
unsigned copied = 0, f_offset;
loff_t end = pos + len, f_pos;
+ loff_t last_folio_pos = inode->v.i_size;
int ret = 0;
BUG_ON(!len);
@@ -1876,8 +1877,6 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
BUG_ON(!folios.nr);
- end = min(end, folio_end_pos(darray_last(folios)));
-
f = darray_first(folios);
if (pos != folio_pos(f) && !folio_test_uptodate(f)) {
ret = bch2_read_single_folio(f, mapping);
@@ -1886,6 +1885,8 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
}
f = darray_last(folios);
+ end = min(end, folio_end_pos(f));
+ last_folio_pos = folio_pos(f);
if (end != folio_end_pos(f) && !folio_test_uptodate(f)) {
if (end >= inode->v.i_size) {
folio_zero_range(f, 0, folio_size(f));
@@ -1999,6 +2000,14 @@ out:
folio_put(*fi);
}
+ /*
+ * If the last folio added to the mapping starts beyond current EOF, we
+ * performed a short write but left around at least one post-EOF folio.
+ * Clean up the mapping before we return.
+ */
+ if (last_folio_pos >= inode->v.i_size)
+ truncate_pagecache(&inode->v, inode->v.i_size);
+
darray_exit(&folios);
bch2_folio_reservation_put(c, inode, &res);