Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+64 -142
+25 -115
fs/nilfs2/gcinode.c
··· 28 28 * gcinodes), and this file provides lookup function of the dummy 29 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 31 * Buffers and pages held by the dummy inodes will be released each 39 32 * time after they are copied to a new log. Dirty blocks made on the 40 33 * current generation and the blocks to be moved by GC never overlap ··· 173 180 return 0; 174 181 } 175 182 176 - /* 177 - * nilfs_init_gccache() - allocate and initialize gc_inode hash table 178 - * @nilfs - the_nilfs 179 - * 180 - * Return Value: On success, 0. 181 - * On error, a negative error code is returned. 182 - */ 183 - int nilfs_init_gccache(struct the_nilfs *nilfs) 183 + int nilfs_init_gcinode(struct inode *inode) 184 184 { 185 - int loop; 185 + struct nilfs_inode_info *ii = NILFS_I(inode); 186 + struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; 187 + int ret; 186 188 187 - BUG_ON(nilfs->ns_gc_inodes_h); 189 + ret = nilfs_mdt_init(inode, nilfs, GFP_NOFS, 0); 190 + if (!ret) { 191 + inode->i_mapping->a_ops = &def_gcinode_aops; 188 192 189 - INIT_LIST_HEAD(&nilfs->ns_gc_inodes); 193 + ii->i_flags = 0; 194 + nilfs_bmap_init_gc(ii->i_bmap); 190 195 191 - nilfs->ns_gc_inodes_h = 192 - kmalloc(sizeof(struct hlist_head) * NILFS_GCINODE_HASH_SIZE, 193 - GFP_NOFS); 194 - if (nilfs->ns_gc_inodes_h == NULL) 195 - return -ENOMEM; 196 - 197 - for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++) 198 - INIT_HLIST_HEAD(&nilfs->ns_gc_inodes_h[loop]); 199 - return 0; 200 - } 201 - 202 - /* 203 - * nilfs_destroy_gccache() - free gc_inode hash table 204 - * @nilfs - the nilfs 205 - */ 206 - void nilfs_destroy_gccache(struct the_nilfs *nilfs) 207 - { 208 - if (nilfs->ns_gc_inodes_h) { 209 - nilfs_remove_all_gcinode(nilfs); 210 - kfree(nilfs->ns_gc_inodes_h); 211 - nilfs->ns_gc_inodes_h = NULL; 212 - } 213 - } 214 - 215 - static struct inode *alloc_gcinode(struct the_nilfs *nilfs, ino_t ino, 216 - __u64 cno) 217 - { 218 - struct inode *inode; 219 - struct nilfs_inode_info *ii; 220 - 221 - inode = nilfs_mdt_new_common(nilfs, NULL, ino); 222 - if (!inode) 223 - return NULL; 224 - 225 - if (nilfs_mdt_init(inode, nilfs, GFP_NOFS, 0) < 0) { 226 - nilfs_destroy_inode(inode); 227 - return NULL; 228 - } 229 - inode->i_op = NULL; 230 - inode->i_fop = NULL; 231 - inode->i_mapping->a_ops = &def_gcinode_aops; 232 - 233 - ii = NILFS_I(inode); 234 - ii->i_cno = cno; 235 - ii->i_flags = 0; 236 - ii->i_state = 1 << NILFS_I_GCINODE; 237 - ii->i_bh = NULL; 238 - nilfs_bmap_init_gc(ii->i_bmap); 239 - 240 - return inode; 241 - } 242 - 243 - static unsigned long ihash(ino_t ino, __u64 cno) 244 - { 245 - return hash_long((unsigned long)((ino << 2) + cno), 246 - NILFS_GCINODE_HASH_BITS); 247 - } 248 - 249 - /* 250 - * nilfs_gc_iget() - find or create gc inode with specified (ino,cno) 251 - */ 252 - struct inode *nilfs_gc_iget(struct the_nilfs *nilfs, ino_t ino, __u64 cno) 253 - { 254 - struct hlist_head *head = nilfs->ns_gc_inodes_h + ihash(ino, cno); 255 - struct hlist_node *node; 256 - struct inode *inode; 257 - 258 - hlist_for_each_entry(inode, node, head, i_hash) { 259 - if (inode->i_ino == ino && NILFS_I(inode)->i_cno == cno) 260 - return inode; 261 - } 262 - 263 - inode = alloc_gcinode(nilfs, ino, cno); 264 - if (likely(inode)) { 265 - hlist_add_head(&inode->i_hash, head); 196 + /* 197 + * Add the inode to GC inode list. Garbage Collection 198 + * is serialized and no two processes manipulate the 199 + * list simultaneously. 200 + */ 201 + igrab(inode); 266 202 list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes); 267 203 } 268 - return inode; 204 + return ret; 269 205 } 270 206 271 - /* 272 - * nilfs_clear_gcinode() - clear and free a gc inode 207 + /** 208 + * nilfs_remove_all_gcinodes() - remove all unprocessed gc inodes 273 209 */ 274 - void nilfs_clear_gcinode(struct inode *inode) 210 + void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs) 275 211 { 276 - nilfs_mdt_destroy(inode); 277 - } 212 + struct list_head *head = &nilfs->ns_gc_inodes; 213 + struct nilfs_inode_info *ii; 278 214 279 - /* 280 - * nilfs_remove_all_gcinode() - remove all inodes from the_nilfs 281 - */ 282 - void nilfs_remove_all_gcinode(struct the_nilfs *nilfs) 283 - { 284 - struct hlist_head *head = nilfs->ns_gc_inodes_h; 285 - struct hlist_node *node, *n; 286 - struct inode *inode; 287 - int loop; 288 - 289 - for (loop = 0; loop < NILFS_GCINODE_HASH_SIZE; loop++, head++) { 290 - hlist_for_each_entry_safe(inode, node, n, head, i_hash) { 291 - hlist_del_init(&inode->i_hash); 292 - list_del_init(&NILFS_I(inode)->i_dirty); 293 - nilfs_clear_gcinode(inode); /* might sleep */ 294 - } 215 + while (!list_empty(head)) { 216 + ii = list_first_entry(head, struct nilfs_inode_info, i_dirty); 217 + list_del_init(&ii->i_dirty); 218 + iput(&ii->vfs_inode); 295 219 } 296 220 }
+22
fs/nilfs2/inode.c
··· 527 527 return inode; 528 528 } 529 529 530 + struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino, 531 + __u64 cno) 532 + { 533 + struct nilfs_iget_args args = { .ino = ino, .cno = cno, .for_gc = 1 }; 534 + struct inode *inode; 535 + int err; 536 + 537 + inode = iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args); 538 + if (unlikely(!inode)) 539 + return ERR_PTR(-ENOMEM); 540 + if (!(inode->i_state & I_NEW)) 541 + return inode; 542 + 543 + err = nilfs_init_gcinode(inode); 544 + if (unlikely(err)) { 545 + iget_failed(inode); 546 + return ERR_PTR(err); 547 + } 548 + unlock_new_inode(inode); 549 + return inode; 550 + } 551 + 530 552 void nilfs_write_inode_common(struct inode *inode, 531 553 struct nilfs_inode *raw_inode, int has_bmap) 532 554 {
+10 -7
fs/nilfs2/ioctl.c
··· 333 333 return 0; 334 334 } 335 335 336 - static int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs, 336 + static int nilfs_ioctl_move_blocks(struct super_block *sb, 337 337 struct nilfs_argv *argv, void *buf) 338 338 { 339 339 size_t nmembs = argv->v_nmembs; ··· 348 348 for (i = 0, vdesc = buf; i < nmembs; ) { 349 349 ino = vdesc->vd_ino; 350 350 cno = vdesc->vd_cno; 351 - inode = nilfs_gc_iget(nilfs, ino, cno); 351 + inode = nilfs_iget_for_gc(sb, ino, cno); 352 352 if (unlikely(inode == NULL)) { 353 353 ret = -ENOMEM; 354 354 goto failed; ··· 356 356 do { 357 357 ret = nilfs_ioctl_move_inode_block(inode, vdesc, 358 358 &buffers); 359 - if (unlikely(ret < 0)) 359 + if (unlikely(ret < 0)) { 360 + iput(inode); 360 361 goto failed; 362 + } 361 363 vdesc++; 362 364 } while (++i < nmembs && 363 365 vdesc->vd_ino == ino && vdesc->vd_cno == cno); 366 + 367 + iput(inode); /* The inode still remains in GC inode list */ 364 368 } 365 369 366 370 list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { ··· 570 566 } 571 567 572 568 /* 573 - * nilfs_ioctl_move_blocks() will call nilfs_gc_iget(), 569 + * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(), 574 570 * which will operates an inode list without blocking. 575 571 * To protect the list from concurrent operations, 576 572 * nilfs_ioctl_move_blocks should be atomic operation. ··· 580 576 goto out_free; 581 577 } 582 578 583 - ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], kbufs[0]); 579 + ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); 584 580 if (ret < 0) 585 581 printk(KERN_ERR "NILFS: GC failed during preparation: " 586 582 "cannot read source blocks: err=%d\n", ret); 587 583 else 588 584 ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); 589 585 590 - if (ret < 0) 591 - nilfs_remove_all_gcinode(nilfs); 586 + nilfs_remove_all_gcinodes(nilfs); 592 587 clear_nilfs_gc_running(nilfs); 593 588 594 589 out_free:
+4 -5
fs/nilfs2/nilfs.h
··· 248 248 extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *); 249 249 extern void nilfs_write_inode_common(struct inode *, struct nilfs_inode *, int); 250 250 extern struct inode *nilfs_iget(struct super_block *, unsigned long); 251 + extern struct inode *nilfs_iget_for_gc(struct super_block *sb, 252 + unsigned long ino, __u64 cno); 251 253 extern void nilfs_update_inode(struct inode *, struct buffer_head *); 252 254 extern void nilfs_truncate(struct inode *); 253 255 extern void nilfs_evict_inode(struct inode *); ··· 294 292 int nilfs_gccache_submit_read_node(struct inode *, sector_t, __u64, 295 293 struct buffer_head **); 296 294 int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *); 297 - int nilfs_init_gccache(struct the_nilfs *); 298 - void nilfs_destroy_gccache(struct the_nilfs *); 299 - void nilfs_clear_gcinode(struct inode *); 300 - struct inode *nilfs_gc_iget(struct the_nilfs *, ino_t, __u64); 301 - void nilfs_remove_all_gcinode(struct the_nilfs *); 295 + int nilfs_init_gcinode(struct inode *inode); 296 + void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs); 302 297 303 298 /* gcdat.c */ 304 299 int nilfs_init_gcdat_inode(struct the_nilfs *);
+1 -2
fs/nilfs2/segment.c
··· 2451 2451 list_for_each_entry_safe(ii, n, head, i_dirty) { 2452 2452 if (!test_bit(NILFS_I_UPDATED, &ii->i_state)) 2453 2453 continue; 2454 - hlist_del_init(&ii->vfs_inode.i_hash); 2455 2454 list_del_init(&ii->i_dirty); 2456 - nilfs_clear_gcinode(&ii->vfs_inode); 2455 + iput(&ii->vfs_inode); 2457 2456 } 2458 2457 } 2459 2458
+1 -7
fs/nilfs2/the_nilfs.c
··· 87 87 init_rwsem(&nilfs->ns_writer_sem); 88 88 INIT_LIST_HEAD(&nilfs->ns_list); 89 89 INIT_LIST_HEAD(&nilfs->ns_supers); 90 + INIT_LIST_HEAD(&nilfs->ns_gc_inodes); 90 91 spin_lock_init(&nilfs->ns_last_segment_lock); 91 - nilfs->ns_gc_inodes_h = NULL; 92 92 init_rwsem(&nilfs->ns_segctor_sem); 93 93 94 94 return nilfs; ··· 164 164 nilfs_mdt_destroy(nilfs->ns_gc_dat); 165 165 } 166 166 if (nilfs_init(nilfs)) { 167 - nilfs_destroy_gccache(nilfs); 168 167 brelse(nilfs->ns_sbh[0]); 169 168 brelse(nilfs->ns_sbh[1]); 170 169 } ··· 732 733 nilfs->ns_bdi = bdi ? : &default_backing_dev_info; 733 734 734 735 err = nilfs_store_log_cursor(nilfs, sbp); 735 - if (err) 736 - goto failed_sbh; 737 - 738 - /* Initialize gcinode cache */ 739 - err = nilfs_init_gccache(nilfs); 740 736 if (err) 741 737 goto failed_sbh; 742 738
+1 -6
fs/nilfs2/the_nilfs.h
··· 81 81 * @ns_sufile: segusage file inode 82 82 * @ns_gc_dat: shadow inode of the DAT file inode for GC 83 83 * @ns_gc_inodes: dummy inodes to keep live blocks 84 - * @ns_gc_inodes_h: hash list to keep dummy inode holding live blocks 85 84 * @ns_blocksize_bits: bit length of block size 86 85 * @ns_blocksize: block size 87 86 * @ns_nsegments: number of segments in filesystem ··· 164 165 struct inode *ns_sufile; 165 166 struct inode *ns_gc_dat; 166 167 167 - /* GC inode list and hash table head */ 168 + /* GC inode list */ 168 169 struct list_head ns_gc_inodes; 169 - struct hlist_head *ns_gc_inodes_h; 170 170 171 171 /* Disk layout information (static) */ 172 172 unsigned int ns_blocksize_bits; ··· 179 181 int ns_first_ino; 180 182 u32 ns_crc_seed; 181 183 }; 182 - 183 - #define NILFS_GCINODE_HASH_BITS 8 184 - #define NILFS_GCINODE_HASH_SIZE (1<<NILFS_GCINODE_HASH_BITS) 185 184 186 185 #define THE_NILFS_FNS(bit, name) \ 187 186 static inline void set_nilfs_##name(struct the_nilfs *nilfs) \