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

nilfs2: get rid of GCDAT inode

This applies prepared rollback function and redirect function of
metadata file to DAT file, and eliminates GCDAT inode.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>

+41 -171
+1 -1
fs/nilfs2/Makefile
··· 2 2 nilfs2-y := inode.o file.o dir.o super.o namei.o page.o mdt.o \ 3 3 btnode.o bmap.o btree.o direct.o dat.o recovery.o \ 4 4 the_nilfs.o segbuf.o segment.o cpfile.o sufile.o \ 5 - ifile.o alloc.o gcinode.o ioctl.o gcdat.o 5 + ifile.o alloc.o gcinode.o ioctl.o
-16
fs/nilfs2/bmap.c
··· 533 533 nilfs_btree_init_gc(bmap); 534 534 } 535 535 536 - void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) 537 - { 538 - memcpy(gcbmap, bmap, sizeof(*bmap)); 539 - init_rwsem(&gcbmap->b_sem); 540 - lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); 541 - gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode; 542 - } 543 - 544 - void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) 545 - { 546 - memcpy(bmap, gcbmap, sizeof(*bmap)); 547 - init_rwsem(&bmap->b_sem); 548 - lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); 549 - bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; 550 - } 551 - 552 536 void nilfs_bmap_save(const struct nilfs_bmap *bmap, 553 537 struct nilfs_bmap_store *store) 554 538 {
-2
fs/nilfs2/bmap.h
··· 159 159 int nilfs_bmap_mark(struct nilfs_bmap *, __u64, int); 160 160 161 161 void nilfs_bmap_init_gc(struct nilfs_bmap *); 162 - void nilfs_bmap_init_gcdat(struct nilfs_bmap *, struct nilfs_bmap *); 163 - void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *); 164 162 165 163 void nilfs_bmap_save(const struct nilfs_bmap *, struct nilfs_bmap_store *); 166 164 void nilfs_bmap_restore(struct nilfs_bmap *, const struct nilfs_bmap_store *);
+29 -1
fs/nilfs2/dat.c
··· 36 36 struct nilfs_dat_info { 37 37 struct nilfs_mdt_info mi; 38 38 struct nilfs_palloc_cache palloc_cache; 39 + struct nilfs_shadow_map shadow; 39 40 }; 40 41 41 42 static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat) ··· 328 327 ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh); 329 328 if (ret < 0) 330 329 return ret; 330 + 331 + /* 332 + * The given disk block number (blocknr) is not yet written to 333 + * the device at this point. 334 + * 335 + * To prevent nilfs_dat_translate() from returning the 336 + * uncommited block number, this makes a copy of the entry 337 + * buffer and redirects nilfs_dat_translate() to the copy. 338 + */ 339 + if (!buffer_nilfs_redirected(entry_bh)) { 340 + ret = nilfs_mdt_freeze_buffer(dat, entry_bh); 341 + if (ret) { 342 + brelse(entry_bh); 343 + return ret; 344 + } 345 + } 346 + 331 347 kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); 332 348 entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); 333 349 if (unlikely(entry->de_blocknr == cpu_to_le64(0))) { ··· 389 371 */ 390 372 int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp) 391 373 { 392 - struct buffer_head *entry_bh; 374 + struct buffer_head *entry_bh, *bh; 393 375 struct nilfs_dat_entry *entry; 394 376 sector_t blocknr; 395 377 void *kaddr; ··· 398 380 ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh); 399 381 if (ret < 0) 400 382 return ret; 383 + 384 + if (!nilfs_doing_gc() && buffer_nilfs_redirected(entry_bh)) { 385 + bh = nilfs_mdt_get_frozen_buffer(dat, entry_bh); 386 + if (bh) { 387 + WARN_ON(!buffer_uptodate(bh)); 388 + brelse(entry_bh); 389 + entry_bh = bh; 390 + } 391 + } 401 392 402 393 kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); 403 394 entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr); ··· 495 468 di = NILFS_DAT_I(dat); 496 469 lockdep_set_class(&di->mi.mi_sem, &dat_lock_key); 497 470 nilfs_palloc_setup_cache(dat, &di->palloc_cache); 471 + nilfs_mdt_setup_shadow_map(dat, &di->shadow); 498 472 } 499 473 return dat; 500 474 }
-87
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_palloc_clear_cache(dat); 65 - nilfs_palloc_clear_cache(gcdat); 66 - nilfs_clear_dirty_pages(mapping); 67 - nilfs_copy_back_pages(mapping, gmapping); 68 - /* note: mdt dirty flags should be cleared by segctor. */ 69 - 70 - nilfs_clear_dirty_pages(&dii->i_btnode_cache); 71 - nilfs_copy_back_pages(&dii->i_btnode_cache, &gii->i_btnode_cache); 72 - 73 - up_write(&NILFS_MDT(dat)->mi_sem); 74 - } 75 - 76 - void nilfs_clear_gcdat_inode(struct the_nilfs *nilfs) 77 - { 78 - struct inode *gcdat = nilfs->ns_gc_dat; 79 - struct nilfs_inode_info *gii = NILFS_I(gcdat); 80 - 81 - gcdat->i_state = I_FREEING | I_CLEAR; 82 - gii->i_flags = 0; 83 - 84 - nilfs_palloc_clear_cache(gcdat); 85 - truncate_inode_pages(gcdat->i_mapping, 0); 86 - truncate_inode_pages(&gii->i_btnode_cache, 0); 87 - }
-9
fs/nilfs2/mdt.c
··· 414 414 sb = inode->i_sb; 415 415 nilfs = NILFS_MDT(inode)->mi_nilfs; 416 416 417 - if (page->mapping->assoc_mapping) 418 - return 0; /* Do not request flush for shadow page cache */ 419 417 if (!sb) { 420 418 down_read(&nilfs->ns_writer_sem); 421 419 writer = nilfs->ns_writer; ··· 562 564 mi->mi_entry_size = entry_size; 563 565 mi->mi_entries_per_block = (1 << inode->i_blkbits) / entry_size; 564 566 mi->mi_first_entry_offset = DIV_ROUND_UP(header_size, entry_size); 565 - } 566 - 567 - void nilfs_mdt_set_shadow(struct inode *orig, struct inode *shadow) 568 - { 569 - shadow->i_mapping->assoc_mapping = orig->i_mapping; 570 - NILFS_I(shadow)->i_btnode_cache.assoc_mapping = 571 - &NILFS_I(orig)->i_btnode_cache; 572 567 } 573 568 574 569 static const struct address_space_operations shadow_map_aops = {
-1
fs/nilfs2/mdt.h
··· 93 93 ino_t); 94 94 void nilfs_mdt_destroy(struct inode *); 95 95 void nilfs_mdt_set_entry_size(struct inode *, unsigned, unsigned); 96 - void nilfs_mdt_set_shadow(struct inode *, struct inode *); 97 96 98 97 int nilfs_mdt_setup_shadow_map(struct inode *inode, 99 98 struct nilfs_shadow_map *shadow);
+1 -7
fs/nilfs2/nilfs.h
··· 101 101 NILFS_I_INODE_DIRTY, /* write_inode is requested */ 102 102 NILFS_I_BMAP, /* has bmap and btnode_cache */ 103 103 NILFS_I_GCINODE, /* inode for GC, on memory only */ 104 - NILFS_I_GCDAT, /* shadow DAT, on memory only */ 105 104 }; 106 105 107 106 /* ··· 192 193 193 194 static inline struct inode *nilfs_dat_inode(const struct the_nilfs *nilfs) 194 195 { 195 - return nilfs_doing_gc() ? nilfs->ns_gc_dat : nilfs->ns_dat; 196 + return nilfs->ns_dat; 196 197 } 197 198 198 199 /* ··· 292 293 int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *); 293 294 int nilfs_init_gcinode(struct inode *inode); 294 295 void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs); 295 - 296 - /* gcdat.c */ 297 - int nilfs_init_gcdat_inode(struct the_nilfs *); 298 - void nilfs_commit_gcdat_inode(struct the_nilfs *); 299 - void nilfs_clear_gcdat_inode(struct the_nilfs *); 300 296 301 297 /* 302 298 * Inodes and files operations
+2 -26
fs/nilfs2/page.c
··· 79 79 { 80 80 int blkbits = inode->i_blkbits; 81 81 pgoff_t index = blkoff >> (PAGE_CACHE_SHIFT - blkbits); 82 - struct page *page, *opage; 83 - struct buffer_head *bh, *obh; 82 + struct page *page; 83 + struct buffer_head *bh; 84 84 85 85 page = grab_cache_page(mapping, index); 86 86 if (unlikely(!page)) ··· 91 91 unlock_page(page); 92 92 page_cache_release(page); 93 93 return NULL; 94 - } 95 - if (!buffer_uptodate(bh) && mapping->assoc_mapping != NULL) { 96 - /* 97 - * Shadow page cache uses assoc_mapping to point its original 98 - * page cache. The following code tries the original cache 99 - * if the given cache is a shadow and it didn't hit. 100 - */ 101 - opage = find_lock_page(mapping->assoc_mapping, index); 102 - if (!opage) 103 - return bh; 104 - 105 - obh = __nilfs_get_page_block(opage, blkoff, index, blkbits, 106 - b_state); 107 - if (buffer_uptodate(obh)) { 108 - nilfs_copy_buffer(bh, obh); 109 - if (buffer_dirty(obh)) { 110 - nilfs_mark_buffer_dirty(bh); 111 - if (!buffer_nilfs_node(bh) && NILFS_MDT(inode)) 112 - nilfs_mdt_mark_dirty(inode); 113 - } 114 - } 115 - brelse(obh); 116 - unlock_page(opage); 117 - page_cache_release(opage); 118 94 } 119 95 return bh; 120 96 }
+7 -7
fs/nilfs2/segment.c
··· 1945 1945 1946 1946 nilfs_drop_collected_inodes(&sci->sc_dirty_files); 1947 1947 1948 - if (nilfs_doing_gc()) { 1948 + if (nilfs_doing_gc()) 1949 1949 nilfs_drop_collected_inodes(&sci->sc_gc_inodes); 1950 - if (update_sr) 1951 - nilfs_commit_gcdat_inode(nilfs); 1952 - } else 1950 + else 1953 1951 nilfs->ns_nongc_ctime = sci->sc_seg_ctime; 1954 1952 1955 1953 sci->sc_nblk_inc += sci->sc_nblk_this_inc; ··· 2470 2472 2471 2473 nilfs_transaction_lock(sbi, &ti, 1); 2472 2474 2473 - err = nilfs_init_gcdat_inode(nilfs); 2475 + err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat); 2474 2476 if (unlikely(err)) 2475 2477 goto out_unlock; 2476 2478 2477 2479 err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs); 2478 - if (unlikely(err)) 2480 + if (unlikely(err)) { 2481 + nilfs_mdt_restore_from_shadow_map(nilfs->ns_dat); 2479 2482 goto out_unlock; 2483 + } 2480 2484 2481 2485 sci->sc_freesegs = kbufs[4]; 2482 2486 sci->sc_nfreesegs = argv[4].v_nmembs; ··· 2510 2510 out_unlock: 2511 2511 sci->sc_freesegs = NULL; 2512 2512 sci->sc_nfreesegs = 0; 2513 - nilfs_clear_gcdat_inode(nilfs); 2513 + nilfs_mdt_clear_shadow_map(nilfs->ns_dat); 2514 2514 nilfs_transaction_unlock(sbi); 2515 2515 return err; 2516 2516 }
+1 -12
fs/nilfs2/the_nilfs.c
··· 96 96 nilfs_mdt_destroy(nilfs->ns_sufile); 97 97 nilfs_mdt_destroy(nilfs->ns_cpfile); 98 98 nilfs_mdt_destroy(nilfs->ns_dat); 99 - nilfs_mdt_destroy(nilfs->ns_gc_dat); 100 99 } 101 100 if (nilfs_init(nilfs)) { 102 101 brelse(nilfs->ns_sbh[0]); ··· 130 131 if (unlikely(!nilfs->ns_dat)) 131 132 goto failed; 132 133 133 - nilfs->ns_gc_dat = nilfs_dat_new(nilfs, dat_entry_size); 134 - if (unlikely(!nilfs->ns_gc_dat)) 135 - goto failed_dat; 136 - 137 134 nilfs->ns_cpfile = nilfs_cpfile_new(nilfs, checkpoint_size); 138 135 if (unlikely(!nilfs->ns_cpfile)) 139 - goto failed_gc_dat; 136 + goto failed_dat; 140 137 141 138 nilfs->ns_sufile = nilfs_sufile_new(nilfs, segment_usage_size); 142 139 if (unlikely(!nilfs->ns_sufile)) 143 140 goto failed_cpfile; 144 - 145 - nilfs_mdt_set_shadow(nilfs->ns_dat, nilfs->ns_gc_dat); 146 141 147 142 err = nilfs_dat_read(nilfs->ns_dat, (void *)bh_sr->b_data + 148 143 NILFS_SR_DAT_OFFSET(inode_size)); ··· 165 172 166 173 failed_cpfile: 167 174 nilfs_mdt_destroy(nilfs->ns_cpfile); 168 - 169 - failed_gc_dat: 170 - nilfs_mdt_destroy(nilfs->ns_gc_dat); 171 175 172 176 failed_dat: 173 177 nilfs_mdt_destroy(nilfs->ns_dat); ··· 361 371 nilfs_mdt_destroy(nilfs->ns_cpfile); 362 372 nilfs_mdt_destroy(nilfs->ns_sufile); 363 373 nilfs_mdt_destroy(nilfs->ns_dat); 364 - nilfs_mdt_destroy(nilfs->ns_gc_dat); 365 374 366 375 failed: 367 376 nilfs_clear_recovery_info(&ri);
-2
fs/nilfs2/the_nilfs.h
··· 74 74 * @ns_dat: DAT file inode 75 75 * @ns_cpfile: checkpoint file inode 76 76 * @ns_sufile: segusage file inode 77 - * @ns_gc_dat: shadow inode of the DAT file inode for GC 78 77 * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root) 79 78 * @ns_cptree_lock: lock protecting @ns_cptree 80 79 * @ns_gc_inodes: dummy inodes to keep live blocks ··· 148 149 struct inode *ns_dat; 149 150 struct inode *ns_cpfile; 150 151 struct inode *ns_sufile; 151 - struct inode *ns_gc_dat; 152 152 153 153 /* Checkpoint tree */ 154 154 struct rb_root ns_cptree;