From c69a717d4f5dfbc509bd783e03974ebf25e12a5b Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Tue, 31 Aug 2010 11:40:34 +0900 Subject: [PATCH] --- yaml --- r: 213758 b: refs/heads/master c: b1f6a4f294088b3fcf9ae67915ca550a1ded2819 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/nilfs2/mdt.c | 67 +++++++++++++++++++++++++++++++++++++++ trunk/fs/nilfs2/mdt.h | 3 ++ trunk/fs/nilfs2/page.c | 2 ++ trunk/fs/nilfs2/page.h | 2 ++ trunk/fs/nilfs2/segment.c | 1 + 6 files changed, 76 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 7e75bf427b60..7548d1fa3b40 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ebdfed4dc59d177cf26013a0c9b8ee9652e9a140 +refs/heads/master: b1f6a4f294088b3fcf9ae67915ca550a1ded2819 diff --git a/trunk/fs/nilfs2/mdt.c b/trunk/fs/nilfs2/mdt.c index 0066468609da..532f85acf273 100644 --- a/trunk/fs/nilfs2/mdt.c +++ b/trunk/fs/nilfs2/mdt.c @@ -622,6 +622,72 @@ int nilfs_mdt_save_to_shadow_map(struct inode *inode) return ret; } +int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh) +{ + struct nilfs_shadow_map *shadow = NILFS_MDT(inode)->mi_shadow; + struct buffer_head *bh_frozen; + struct page *page; + int blkbits = inode->i_blkbits; + int ret = -ENOMEM; + + page = grab_cache_page(&shadow->frozen_data, bh->b_page->index); + if (!page) + return ret; + + if (!page_has_buffers(page)) + create_empty_buffers(page, 1 << blkbits, 0); + + bh_frozen = nilfs_page_get_nth_block(page, bh_offset(bh) >> blkbits); + if (bh_frozen) { + if (!buffer_uptodate(bh_frozen)) + nilfs_copy_buffer(bh_frozen, bh); + if (list_empty(&bh_frozen->b_assoc_buffers)) { + list_add_tail(&bh_frozen->b_assoc_buffers, + &shadow->frozen_buffers); + set_buffer_nilfs_redirected(bh); + } else { + brelse(bh_frozen); /* already frozen */ + } + ret = 0; + } + unlock_page(page); + page_cache_release(page); + return ret; +} + +struct buffer_head * +nilfs_mdt_get_frozen_buffer(struct inode *inode, struct buffer_head *bh) +{ + struct nilfs_shadow_map *shadow = NILFS_MDT(inode)->mi_shadow; + struct buffer_head *bh_frozen = NULL; + struct page *page; + int n; + + page = find_lock_page(&shadow->frozen_data, bh->b_page->index); + if (page) { + if (page_has_buffers(page)) { + n = bh_offset(bh) >> inode->i_blkbits; + bh_frozen = nilfs_page_get_nth_block(page, n); + } + unlock_page(page); + page_cache_release(page); + } + return bh_frozen; +} + +static void nilfs_release_frozen_buffers(struct nilfs_shadow_map *shadow) +{ + struct list_head *head = &shadow->frozen_buffers; + struct buffer_head *bh; + + while (!list_empty(head)) { + bh = list_first_entry(head, struct buffer_head, + b_assoc_buffers); + list_del_init(&bh->b_assoc_buffers); + brelse(bh); /* drop ref-count to make it releasable */ + } +} + /** * nilfs_mdt_restore_from_shadow_map - restore dirty pages and bmap state * @inode: inode of the metadata file @@ -658,6 +724,7 @@ void nilfs_mdt_clear_shadow_map(struct inode *inode) struct nilfs_shadow_map *shadow = mi->mi_shadow; down_write(&mi->mi_sem); + nilfs_release_frozen_buffers(shadow); truncate_inode_pages(&shadow->frozen_data, 0); truncate_inode_pages(&shadow->frozen_btnodes, 0); up_write(&mi->mi_sem); diff --git a/trunk/fs/nilfs2/mdt.h b/trunk/fs/nilfs2/mdt.h index e7f0d158c527..e60bbfe899f1 100644 --- a/trunk/fs/nilfs2/mdt.h +++ b/trunk/fs/nilfs2/mdt.h @@ -100,6 +100,9 @@ int nilfs_mdt_setup_shadow_map(struct inode *inode, int nilfs_mdt_save_to_shadow_map(struct inode *inode); void nilfs_mdt_restore_from_shadow_map(struct inode *inode); void nilfs_mdt_clear_shadow_map(struct inode *inode); +int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh); +struct buffer_head *nilfs_mdt_get_frozen_buffer(struct inode *inode, + struct buffer_head *bh); #define nilfs_mdt_mark_buffer_dirty(bh) nilfs_mark_buffer_dirty(bh) diff --git a/trunk/fs/nilfs2/page.c b/trunk/fs/nilfs2/page.c index 6384ac14c0c8..7083344ac881 100644 --- a/trunk/fs/nilfs2/page.c +++ b/trunk/fs/nilfs2/page.c @@ -131,6 +131,7 @@ void nilfs_forget_buffer(struct buffer_head *bh) lock_buffer(bh); clear_buffer_nilfs_volatile(bh); clear_buffer_nilfs_checked(bh); + clear_buffer_nilfs_redirected(bh); clear_buffer_dirty(bh); if (nilfs_page_buffers_clean(page)) __nilfs_clear_page_dirty(page); @@ -483,6 +484,7 @@ void nilfs_clear_dirty_pages(struct address_space *mapping) clear_buffer_dirty(bh); clear_buffer_nilfs_volatile(bh); clear_buffer_nilfs_checked(bh); + clear_buffer_nilfs_redirected(bh); clear_buffer_uptodate(bh); clear_buffer_mapped(bh); unlock_buffer(bh); diff --git a/trunk/fs/nilfs2/page.h b/trunk/fs/nilfs2/page.h index 6ec4f498fc2b..fb9e8a8a2038 100644 --- a/trunk/fs/nilfs2/page.h +++ b/trunk/fs/nilfs2/page.h @@ -35,12 +35,14 @@ enum { BH_NILFS_Node, BH_NILFS_Volatile, BH_NILFS_Checked, + BH_NILFS_Redirected, }; BUFFER_FNS(NILFS_Allocated, nilfs_allocated) /* nilfs private buffers */ BUFFER_FNS(NILFS_Node, nilfs_node) /* nilfs node buffers */ BUFFER_FNS(NILFS_Volatile, nilfs_volatile) BUFFER_FNS(NILFS_Checked, nilfs_checked) /* buffer is verified */ +BUFFER_FNS(NILFS_Redirected, nilfs_redirected) /* redirected to a copy */ void nilfs_mark_buffer_dirty(struct buffer_head *bh); diff --git a/trunk/fs/nilfs2/segment.c b/trunk/fs/nilfs2/segment.c index b75306d642c2..91dc0668ec83 100644 --- a/trunk/fs/nilfs2/segment.c +++ b/trunk/fs/nilfs2/segment.c @@ -1908,6 +1908,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) set_buffer_uptodate(bh); clear_buffer_dirty(bh); clear_buffer_nilfs_volatile(bh); + clear_buffer_nilfs_redirected(bh); if (bh == segbuf->sb_super_root) { if (bh->b_page != bd_page) { end_page_writeback(bd_page);