diff options
author | Nick Piggin <npiggin@suse.de> | 2007-10-16 04:25:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:42:55 -0400 |
commit | 637aff46f94a754207c80c8c64bf1b74f24b967d (patch) | |
tree | 837fb3196236998c3c3ae44762ed3167ef0256f4 /fs/buffer.c | |
parent | 2f718ffc16c43a435d12919c75dbfad518abd056 (diff) |
fs: fix data-loss on error
New buffers against uptodate pages are simply be marked uptodate, while the
buffer_new bit remains set. This causes error-case code to zero out parts of
those buffers because it thinks they contain stale data: wrong, they are
actually uptodate so this is a data loss situation.
Fix this by actually clearning buffer_new and marking the buffer dirty. It
makes sense to always clear buffer_new before setting a buffer uptodate.
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/buffer.c')
-rw-r--r-- | fs/buffer.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 09bb80c479d8..9ece6c2086d0 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -1813,7 +1813,9 @@ static int __block_prepare_write(struct inode *inode, struct page *page, | |||
1813 | unmap_underlying_metadata(bh->b_bdev, | 1813 | unmap_underlying_metadata(bh->b_bdev, |
1814 | bh->b_blocknr); | 1814 | bh->b_blocknr); |
1815 | if (PageUptodate(page)) { | 1815 | if (PageUptodate(page)) { |
1816 | clear_buffer_new(bh); | ||
1816 | set_buffer_uptodate(bh); | 1817 | set_buffer_uptodate(bh); |
1818 | mark_buffer_dirty(bh); | ||
1817 | continue; | 1819 | continue; |
1818 | } | 1820 | } |
1819 | if (block_end > to || block_start < from) { | 1821 | if (block_end > to || block_start < from) { |