Commit 877dfb34 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Fix for partial buffered writes

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent bbd8d203
...@@ -756,8 +756,8 @@ static void bch2_set_page_dirty(struct bch_fs *c, ...@@ -756,8 +756,8 @@ static void bch2_set_page_dirty(struct bch_fs *c,
struct bch_page_state *s = bch2_page_state(page); struct bch_page_state *s = bch2_page_state(page);
unsigned i, dirty_sectors = 0; unsigned i, dirty_sectors = 0;
WARN_ON(page_offset(page) + offset + len > WARN_ON((u64) page_offset(page) + offset + len >
round_up(i_size_read(&inode->v), block_bytes(c))); round_up((u64) i_size_read(&inode->v), block_bytes(c)));
for (i = round_down(offset, block_bytes(c)) >> 9; for (i = round_down(offset, block_bytes(c)) >> 9;
i < round_up(offset + len, block_bytes(c)) >> 9; i < round_up(offset + len, block_bytes(c)) >> 9;
...@@ -1704,14 +1704,6 @@ static int __bch2_buffered_write(struct bch_inode_info *inode, ...@@ -1704,14 +1704,6 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
if (!copied) if (!copied)
goto out; goto out;
nr_pages_copied = DIV_ROUND_UP(offset + copied, PAGE_SIZE);
inode->ei_last_dirtied = (unsigned long) current;
spin_lock(&inode->v.i_lock);
if (pos + copied > inode->v.i_size)
i_size_write(&inode->v, pos + copied);
spin_unlock(&inode->v.i_lock);
if (copied < len && if (copied < len &&
((offset + copied) & (PAGE_SIZE - 1))) { ((offset + copied) & (PAGE_SIZE - 1))) {
struct page *page = pages[(offset + copied) >> PAGE_SHIFT]; struct page *page = pages[(offset + copied) >> PAGE_SHIFT];
...@@ -1722,6 +1714,11 @@ static int __bch2_buffered_write(struct bch_inode_info *inode, ...@@ -1722,6 +1714,11 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
} }
} }
spin_lock(&inode->v.i_lock);
if (pos + copied > inode->v.i_size)
i_size_write(&inode->v, pos + copied);
spin_unlock(&inode->v.i_lock);
while (set_dirty < copied) { while (set_dirty < copied) {
struct page *page = pages[(offset + set_dirty) >> PAGE_SHIFT]; struct page *page = pages[(offset + set_dirty) >> PAGE_SHIFT];
unsigned pg_offset = (offset + set_dirty) & (PAGE_SIZE - 1); unsigned pg_offset = (offset + set_dirty) & (PAGE_SIZE - 1);
...@@ -1737,6 +1734,9 @@ static int __bch2_buffered_write(struct bch_inode_info *inode, ...@@ -1737,6 +1734,9 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
set_dirty += pg_len; set_dirty += pg_len;
} }
nr_pages_copied = DIV_ROUND_UP(offset + copied, PAGE_SIZE);
inode->ei_last_dirtied = (unsigned long) current;
out: out:
for (i = nr_pages_copied; i < nr_pages; i++) { for (i = nr_pages_copied; i < nr_pages; i++) {
unlock_page(pages[i]); unlock_page(pages[i]);
......
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