aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-05-05 21:52:06 +0900
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-05-10 17:04:42 +0900
commit843382370ec614768ac13582405f93635cf3637c (patch)
tree6447e8318d2c2a22bebfd0c7e70f825fbdeeebdb
parent201913ed746c7724a40d33ee5a0b6a1fd2ef3193 (diff)
nilfs2: ensure to clear dirty state when deleting metadata file block
This would fix the following failure during GC: nilfs_cpfile_delete_checkpoints: cannot delete block NILFS: GC failed during preparation: cannot delete checkpoints: err=-2 The problem was caused by a break in state consistency between page cache and btree; the above block was removed from the btree but the page buffering the block was remaining in the page cache in dirty state. This resolves the inconsistency by ensuring to clear dirty state of the page buffering the deleted block. Reported-by: David Arendt <admin@prnet.org> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
-rw-r--r--fs/nilfs2/mdt.c2
-rw-r--r--fs/nilfs2/page.c3
2 files changed, 3 insertions, 2 deletions
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index e1c6777931b..bb78745a0e3 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -300,7 +300,7 @@ int nilfs_mdt_delete_block(struct inode *inode, unsigned long block)
int err;
err = nilfs_bmap_delete(ii->i_bmap, block);
- if (likely(!err)) {
+ if (!err || err == -ENOENT) {
nilfs_mdt_mark_dirty(inode);
nilfs_mdt_forget_block(inode, block);
}
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 1bfbba9c0e9..a2692bbc7b5 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -128,7 +128,8 @@ void nilfs_forget_buffer(struct buffer_head *bh)
lock_buffer(bh);
clear_buffer_nilfs_volatile(bh);
- if (test_clear_buffer_dirty(bh) && nilfs_page_buffers_clean(page))
+ clear_buffer_dirty(bh);
+ if (nilfs_page_buffers_clean(page))
__nilfs_clear_page_dirty(page);
clear_buffer_uptodate(bh);