aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/gcinode.c
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-08-20 06:06:11 -0400
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-10-22 20:24:34 -0400
commit263d90cefc7d82a01c296c59532ff59d67c63509 (patch)
treedf289cc3bbb8681b3a42e3c0a25202b085fc9362 /fs/nilfs2/gcinode.c
parent5e19a995f4ad8a8f20749a396bb01ebb6d4df96c (diff)
nilfs2: remove own inode hash used for GC
This uses inode hash function that vfs provides instead of the own hash table for caching gc inodes. This finally removes the own inode hash from nilfs. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/gcinode.c')
-rw-r--r--fs/nilfs2/gcinode.c140
1 files changed, 25 insertions, 115 deletions
diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c
index cd19a3709bda..34f8f84a22e3 100644
--- a/fs/nilfs2/gcinode.c
+++ b/fs/nilfs2/gcinode.c
@@ -28,13 +28,6 @@
28 * gcinodes), and this file provides lookup function of the dummy 28 * gcinodes), and this file provides lookup function of the dummy
29 * inodes and their buffer read function. 29 * inodes and their buffer read function.
30 * 30 *
31 * Since NILFS2 keeps up multiple checkpoints/snapshots across GC, it
32 * has to treat blocks that belong to a same file but have different
33 * checkpoint numbers. To avoid interference among generations, dummy
34 * inodes are managed separately from actual inodes, and their lookup
35 * function (nilfs_gc_iget) is designed to be specified with a
36 * checkpoint number argument as well as an inode number.
37 *
38 * Buffers and pages held by the dummy inodes will be released each 31 * Buffers and pages held by the dummy inodes will be released each
39 * time after they are copied to a new log. Dirty blocks made on the 32 * time after they are copied to a new log. Dirty blocks made on the
40 * current generation and the blocks to be moved by GC never overlap 33 * current generation and the blocks to be moved by GC never overlap
@@ -180,124 +173,41 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh)
180 return 0; 173 return 0;
181} 174}
182 175
183/* 176int nilfs_init_gcinode(struct inode *inode)
184 * nilfs_init_gccache() - allocate and initialize gc_inode hash table
185 * @nilfs - the_nilfs
186 *
187 * Return Value: On success, 0.
188 * On error, a negative error code is returned.
189 */
190int nilfs_init_gccache(struct the_nilfs *nilfs)
191{
192 int loop;
193
194 BUG_ON(nilfs->ns_gc_inodes_h);
195
196 INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
197
198 nilfs->ns_gc_inodes_h =
199 kmalloc(sizeof(struct hlist_head) * NILFS_GCINODE_HASH_SIZE,
200 GFP_NOFS);
201 if (nilfs->ns_gc_inodes_h == NULL)
202 return -ENOMEM;
203
204 for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++)
205 INIT_HLIST_HEAD(&nilfs->ns_gc_inodes_h[loop]);
206 return 0;
207}
208
209/*
210 * nilfs_destroy_gccache() - free gc_inode hash table
211 * @nilfs - the nilfs
212 */
213void nilfs_destroy_gccache(struct the_nilfs *nilfs)
214{ 177{
215 if (nilfs->ns_gc_inodes_h) { 178 struct nilfs_inode_info *ii = NILFS_I(inode);
216 nilfs_remove_all_gcinode(nilfs); 179 struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
217 kfree(nilfs->ns_gc_inodes_h); 180 int ret;
218 nilfs->ns_gc_inodes_h = NULL;
219 }
220}
221
222static struct inode *alloc_gcinode(struct the_nilfs *nilfs, ino_t ino,
223 __u64 cno)
224{
225 struct inode *inode;
226 struct nilfs_inode_info *ii;
227
228 inode = nilfs_mdt_new_common(nilfs, NULL, ino);
229 if (!inode)
230 return NULL;
231
232 if (nilfs_mdt_init(inode, nilfs, GFP_NOFS, 0) < 0) {
233 nilfs_destroy_inode(inode);
234 return NULL;
235 }
236 inode->i_op = NULL;
237 inode->i_fop = NULL;
238 inode->i_mapping->a_ops = &def_gcinode_aops;
239
240 ii = NILFS_I(inode);
241 ii->i_cno = cno;
242 ii->i_flags = 0;
243 ii->i_state = 1 << NILFS_I_GCINODE;
244 ii->i_bh = NULL;
245 nilfs_bmap_init_gc(ii->i_bmap);
246 181
247 return inode; 182 ret = nilfs_mdt_init(inode, nilfs, GFP_NOFS, 0);
248} 183 if (!ret) {
184 inode->i_mapping->a_ops = &def_gcinode_aops;
249 185
250static unsigned long ihash(ino_t ino, __u64 cno) 186 ii->i_flags = 0;
251{ 187 nilfs_bmap_init_gc(ii->i_bmap);
252 return hash_long((unsigned long)((ino << 2) + cno),
253 NILFS_GCINODE_HASH_BITS);
254}
255 188
256/* 189 /*
257 * nilfs_gc_iget() - find or create gc inode with specified (ino,cno) 190 * Add the inode to GC inode list. Garbage Collection
258 */ 191 * is serialized and no two processes manipulate the
259struct inode *nilfs_gc_iget(struct the_nilfs *nilfs, ino_t ino, __u64 cno) 192 * list simultaneously.
260{ 193 */
261 struct hlist_head *head = nilfs->ns_gc_inodes_h + ihash(ino, cno); 194 igrab(inode);
262 struct hlist_node *node;
263 struct inode *inode;
264
265 hlist_for_each_entry(inode, node, head, i_hash) {
266 if (inode->i_ino == ino && NILFS_I(inode)->i_cno == cno)
267 return inode;
268 }
269
270 inode = alloc_gcinode(nilfs, ino, cno);
271 if (likely(inode)) {
272 hlist_add_head(&inode->i_hash, head);
273 list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes); 195 list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes);
274 } 196 }
275 return inode; 197 return ret;
276}
277
278/*
279 * nilfs_clear_gcinode() - clear and free a gc inode
280 */
281void nilfs_clear_gcinode(struct inode *inode)
282{
283 nilfs_mdt_destroy(inode);
284} 198}
285 199
286/* 200/**
287 * nilfs_remove_all_gcinode() - remove all inodes from the_nilfs 201 * nilfs_remove_all_gcinodes() - remove all unprocessed gc inodes
288 */ 202 */
289void nilfs_remove_all_gcinode(struct the_nilfs *nilfs) 203void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs)
290{ 204{
291 struct hlist_head *head = nilfs->ns_gc_inodes_h; 205 struct list_head *head = &nilfs->ns_gc_inodes;
292 struct hlist_node *node, *n; 206 struct nilfs_inode_info *ii;
293 struct inode *inode;
294 int loop;
295 207
296 for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++, head++) { 208 while (!list_empty(head)) {
297 hlist_for_each_entry_safe(inode, node, n, head, i_hash) { 209 ii = list_first_entry(head, struct nilfs_inode_info, i_dirty);
298 hlist_del_init(&inode->i_hash); 210 list_del_init(&ii->i_dirty);
299 list_del_init(&NILFS_I(inode)->i_dirty); 211 iput(&ii->vfs_inode);
300 nilfs_clear_gcinode(inode); /* might sleep */
301 }
302 } 212 }
303} 213}