nilfs2: another dat for garbage collection
[linux-2.6] / fs / nilfs2 / gcdat.c
1 /*
2  * gcdat.c - NILFS shadow DAT inode for GC
3  *
4  * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * Written by Seiji Kihara <kihara@osrg.net>, Amagai Yoshiji <amagai@osrg.net>,
21  *            and Ryusuke Konishi <ryusuke@osrg.net>.
22  *
23  */
24
25 #include <linux/buffer_head.h>
26 #include "nilfs.h"
27 #include "page.h"
28 #include "mdt.h"
29
30 int nilfs_init_gcdat_inode(struct the_nilfs *nilfs)
31 {
32         struct inode *dat = nilfs->ns_dat, *gcdat = nilfs->ns_gc_dat;
33         struct nilfs_inode_info *dii = NILFS_I(dat), *gii = NILFS_I(gcdat);
34         int err;
35
36         gcdat->i_state = 0;
37         gcdat->i_blocks = dat->i_blocks;
38         gii->i_flags = dii->i_flags;
39         gii->i_state = dii->i_state | (1 << NILFS_I_GCDAT);
40         gii->i_cno = 0;
41         nilfs_bmap_init_gcdat(gii->i_bmap, dii->i_bmap);
42         err = nilfs_copy_dirty_pages(gcdat->i_mapping, dat->i_mapping);
43         if (unlikely(err))
44                 return err;
45
46         return nilfs_copy_dirty_pages(&gii->i_btnode_cache,
47                                       &dii->i_btnode_cache);
48 }
49
50 void nilfs_commit_gcdat_inode(struct the_nilfs *nilfs)
51 {
52         struct inode *dat = nilfs->ns_dat, *gcdat = nilfs->ns_gc_dat;
53         struct nilfs_inode_info *dii = NILFS_I(dat), *gii = NILFS_I(gcdat);
54         struct address_space *mapping = dat->i_mapping;
55         struct address_space *gmapping = gcdat->i_mapping;
56
57         down_write(&NILFS_MDT(dat)->mi_sem);
58         dat->i_blocks = gcdat->i_blocks;
59         dii->i_flags = gii->i_flags;
60         dii->i_state = gii->i_state & ~(1 << NILFS_I_GCDAT);
61
62         nilfs_bmap_commit_gcdat(gii->i_bmap, dii->i_bmap);
63
64         nilfs_clear_dirty_pages(mapping);
65         nilfs_copy_back_pages(mapping, gmapping);
66         /* note: mdt dirty flags should be cleared by segctor. */
67
68         nilfs_clear_dirty_pages(&dii->i_btnode_cache);
69         nilfs_copy_back_pages(&dii->i_btnode_cache, &gii->i_btnode_cache);
70
71         up_write(&NILFS_MDT(dat)->mi_sem);
72 }
73
74 void nilfs_clear_gcdat_inode(struct the_nilfs *nilfs)
75 {
76         struct inode *gcdat = nilfs->ns_gc_dat;
77         struct nilfs_inode_info *gii = NILFS_I(gcdat);
78
79         gcdat->i_state = I_CLEAR;
80         gii->i_flags = 0;
81
82         truncate_inode_pages(gcdat->i_mapping, 0);
83         truncate_inode_pages(&gii->i_btnode_cache, 0);
84 }