10a8165d7SJaegeuk Kim /* 2127e670aSJaegeuk Kim * fs/f2fs/checkpoint.c 3127e670aSJaegeuk Kim * 4127e670aSJaegeuk Kim * Copyright (c) 2012 Samsung Electronics Co., Ltd. 5127e670aSJaegeuk Kim * http://www.samsung.com/ 6127e670aSJaegeuk Kim * 7127e670aSJaegeuk Kim * This program is free software; you can redistribute it and/or modify 8127e670aSJaegeuk Kim * it under the terms of the GNU General Public License version 2 as 9127e670aSJaegeuk Kim * published by the Free Software Foundation. 10127e670aSJaegeuk Kim */ 11127e670aSJaegeuk Kim #include <linux/fs.h> 12127e670aSJaegeuk Kim #include <linux/bio.h> 13127e670aSJaegeuk Kim #include <linux/mpage.h> 14127e670aSJaegeuk Kim #include <linux/writeback.h> 15127e670aSJaegeuk Kim #include <linux/blkdev.h> 16127e670aSJaegeuk Kim #include <linux/f2fs_fs.h> 17127e670aSJaegeuk Kim #include <linux/pagevec.h> 18127e670aSJaegeuk Kim #include <linux/swap.h> 19127e670aSJaegeuk Kim 20127e670aSJaegeuk Kim #include "f2fs.h" 21127e670aSJaegeuk Kim #include "node.h" 22127e670aSJaegeuk Kim #include "segment.h" 232af4bd6cSNamjae Jeon #include <trace/events/f2fs.h> 24127e670aSJaegeuk Kim 256451e041SJaegeuk Kim static struct kmem_cache *ino_entry_slab; 26127e670aSJaegeuk Kim static struct kmem_cache *inode_entry_slab; 27127e670aSJaegeuk Kim 280a8165d7SJaegeuk Kim /* 29127e670aSJaegeuk Kim * We guarantee no failure on the returned page. 30127e670aSJaegeuk Kim */ 31127e670aSJaegeuk Kim struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) 32127e670aSJaegeuk Kim { 339df27d98SGu Zheng struct address_space *mapping = META_MAPPING(sbi); 34127e670aSJaegeuk Kim struct page *page = NULL; 35127e670aSJaegeuk Kim repeat: 36bde44686SJaegeuk Kim page = grab_cache_page(mapping, index); 37127e670aSJaegeuk Kim if (!page) { 38127e670aSJaegeuk Kim cond_resched(); 39127e670aSJaegeuk Kim goto repeat; 40127e670aSJaegeuk Kim } 41bde44686SJaegeuk Kim f2fs_wait_on_page_writeback(page, META); 42127e670aSJaegeuk Kim SetPageUptodate(page); 43127e670aSJaegeuk Kim return page; 44127e670aSJaegeuk Kim } 45127e670aSJaegeuk Kim 460a8165d7SJaegeuk Kim /* 47127e670aSJaegeuk Kim * We guarantee no failure on the returned page. 48127e670aSJaegeuk Kim */ 49127e670aSJaegeuk Kim struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) 50127e670aSJaegeuk Kim { 519df27d98SGu Zheng struct address_space *mapping = META_MAPPING(sbi); 52127e670aSJaegeuk Kim struct page *page; 53127e670aSJaegeuk Kim repeat: 54127e670aSJaegeuk Kim page = grab_cache_page(mapping, index); 55127e670aSJaegeuk Kim if (!page) { 56127e670aSJaegeuk Kim cond_resched(); 57127e670aSJaegeuk Kim goto repeat; 58127e670aSJaegeuk Kim } 59393ff91fSJaegeuk Kim if (PageUptodate(page)) 60393ff91fSJaegeuk Kim goto out; 61127e670aSJaegeuk Kim 6293dfe2acSJaegeuk Kim if (f2fs_submit_page_bio(sbi, page, index, 6393dfe2acSJaegeuk Kim READ_SYNC | REQ_META | REQ_PRIO)) 64393ff91fSJaegeuk Kim goto repeat; 65393ff91fSJaegeuk Kim 66393ff91fSJaegeuk Kim lock_page(page); 676bacf52fSJaegeuk Kim if (unlikely(page->mapping != mapping)) { 68afcb7ca0SJaegeuk Kim f2fs_put_page(page, 1); 69afcb7ca0SJaegeuk Kim goto repeat; 70afcb7ca0SJaegeuk Kim } 71393ff91fSJaegeuk Kim out: 72127e670aSJaegeuk Kim return page; 73127e670aSJaegeuk Kim } 74127e670aSJaegeuk Kim 7566b00c18SChao Yu static inline bool is_valid_blkaddr(struct f2fs_sb_info *sbi, 7666b00c18SChao Yu block_t blkaddr, int type) 77662befdaSChao Yu { 78662befdaSChao Yu switch (type) { 79662befdaSChao Yu case META_NAT: 8066b00c18SChao Yu break; 81662befdaSChao Yu case META_SIT: 8266b00c18SChao Yu if (unlikely(blkaddr >= SIT_BLK_CNT(sbi))) 8366b00c18SChao Yu return false; 8466b00c18SChao Yu break; 8581c1a0f1SChao Yu case META_SSA: 8666b00c18SChao Yu if (unlikely(blkaddr >= MAIN_BLKADDR(sbi) || 8766b00c18SChao Yu blkaddr < SM_I(sbi)->ssa_blkaddr)) 8866b00c18SChao Yu return false; 8966b00c18SChao Yu break; 90662befdaSChao Yu case META_CP: 9166b00c18SChao Yu if (unlikely(blkaddr >= SIT_I(sbi)->sit_base_addr || 9266b00c18SChao Yu blkaddr < __start_cp_addr(sbi))) 9366b00c18SChao Yu return false; 9466b00c18SChao Yu break; 954c521f49SJaegeuk Kim case META_POR: 9666b00c18SChao Yu if (unlikely(blkaddr >= MAX_BLKADDR(sbi) || 9766b00c18SChao Yu blkaddr < MAIN_BLKADDR(sbi))) 9866b00c18SChao Yu return false; 9966b00c18SChao Yu break; 100662befdaSChao Yu default: 101662befdaSChao Yu BUG(); 102662befdaSChao Yu } 10366b00c18SChao Yu 10466b00c18SChao Yu return true; 105662befdaSChao Yu } 106662befdaSChao Yu 107662befdaSChao Yu /* 10881c1a0f1SChao Yu * Readahead CP/NAT/SIT/SSA pages 109662befdaSChao Yu */ 1104c521f49SJaegeuk Kim int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, int type) 111662befdaSChao Yu { 112662befdaSChao Yu block_t prev_blk_addr = 0; 113662befdaSChao Yu struct page *page; 1144c521f49SJaegeuk Kim block_t blkno = start; 115662befdaSChao Yu 116662befdaSChao Yu struct f2fs_io_info fio = { 117662befdaSChao Yu .type = META, 118662befdaSChao Yu .rw = READ_SYNC | REQ_META | REQ_PRIO 119662befdaSChao Yu }; 120662befdaSChao Yu 121662befdaSChao Yu for (; nrpages-- > 0; blkno++) { 122662befdaSChao Yu block_t blk_addr; 123662befdaSChao Yu 12466b00c18SChao Yu if (!is_valid_blkaddr(sbi, blkno, type)) 12566b00c18SChao Yu goto out; 12666b00c18SChao Yu 127662befdaSChao Yu switch (type) { 128662befdaSChao Yu case META_NAT: 12966b00c18SChao Yu if (unlikely(blkno >= 13066b00c18SChao Yu NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid))) 131662befdaSChao Yu blkno = 0; 13266b00c18SChao Yu /* get nat block addr */ 133662befdaSChao Yu blk_addr = current_nat_addr(sbi, 134662befdaSChao Yu blkno * NAT_ENTRY_PER_BLOCK); 135662befdaSChao Yu break; 136662befdaSChao Yu case META_SIT: 137662befdaSChao Yu /* get sit block addr */ 138662befdaSChao Yu blk_addr = current_sit_addr(sbi, 139662befdaSChao Yu blkno * SIT_ENTRY_PER_BLOCK); 140662befdaSChao Yu if (blkno != start && prev_blk_addr + 1 != blk_addr) 141662befdaSChao Yu goto out; 142662befdaSChao Yu prev_blk_addr = blk_addr; 143662befdaSChao Yu break; 14481c1a0f1SChao Yu case META_SSA: 145662befdaSChao Yu case META_CP: 1464c521f49SJaegeuk Kim case META_POR: 147662befdaSChao Yu blk_addr = blkno; 148662befdaSChao Yu break; 149662befdaSChao Yu default: 150662befdaSChao Yu BUG(); 151662befdaSChao Yu } 152662befdaSChao Yu 153662befdaSChao Yu page = grab_cache_page(META_MAPPING(sbi), blk_addr); 154662befdaSChao Yu if (!page) 155662befdaSChao Yu continue; 156662befdaSChao Yu if (PageUptodate(page)) { 157662befdaSChao Yu f2fs_put_page(page, 1); 158662befdaSChao Yu continue; 159662befdaSChao Yu } 160662befdaSChao Yu 161662befdaSChao Yu f2fs_submit_page_mbio(sbi, page, blk_addr, &fio); 162662befdaSChao Yu f2fs_put_page(page, 0); 163662befdaSChao Yu } 164662befdaSChao Yu out: 165662befdaSChao Yu f2fs_submit_merged_bio(sbi, META, READ); 166662befdaSChao Yu return blkno - start; 167662befdaSChao Yu } 168662befdaSChao Yu 169*635aee1fSChao Yu void ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index) 170*635aee1fSChao Yu { 171*635aee1fSChao Yu struct page *page; 172*635aee1fSChao Yu bool readahead = false; 173*635aee1fSChao Yu 174*635aee1fSChao Yu page = find_get_page(META_MAPPING(sbi), index); 175*635aee1fSChao Yu if (!page || (page && !PageUptodate(page))) 176*635aee1fSChao Yu readahead = true; 177*635aee1fSChao Yu f2fs_put_page(page, 0); 178*635aee1fSChao Yu 179*635aee1fSChao Yu if (readahead) 180*635aee1fSChao Yu ra_meta_pages(sbi, index, MAX_BIO_BLOCKS(sbi), META_POR); 181*635aee1fSChao Yu } 182*635aee1fSChao Yu 183127e670aSJaegeuk Kim static int f2fs_write_meta_page(struct page *page, 184127e670aSJaegeuk Kim struct writeback_control *wbc) 185127e670aSJaegeuk Kim { 1864081363fSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_P_SB(page); 187577e3495SJaegeuk Kim 188ecda0de3SChao Yu trace_f2fs_writepage(page, META); 189ecda0de3SChao Yu 190203681f6SJaegeuk Kim if (unlikely(sbi->por_doing)) 191cfb271d4SChao Yu goto redirty_out; 192857dc4e0SJaegeuk Kim if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0)) 193cfb271d4SChao Yu goto redirty_out; 1941e968fdfSJaegeuk Kim if (unlikely(f2fs_cp_error(sbi))) 195cf779cabSJaegeuk Kim goto redirty_out; 196127e670aSJaegeuk Kim 1973cb5ad15SJaegeuk Kim f2fs_wait_on_page_writeback(page, META); 198577e3495SJaegeuk Kim write_meta_page(sbi, page); 199127e670aSJaegeuk Kim dec_page_count(sbi, F2FS_DIRTY_META); 200127e670aSJaegeuk Kim unlock_page(page); 201857dc4e0SJaegeuk Kim 202857dc4e0SJaegeuk Kim if (wbc->for_reclaim) 203857dc4e0SJaegeuk Kim f2fs_submit_merged_bio(sbi, META, WRITE); 204577e3495SJaegeuk Kim return 0; 205cfb271d4SChao Yu 206cfb271d4SChao Yu redirty_out: 20776f60268SJaegeuk Kim redirty_page_for_writepage(wbc, page); 208cfb271d4SChao Yu return AOP_WRITEPAGE_ACTIVATE; 209127e670aSJaegeuk Kim } 210127e670aSJaegeuk Kim 211127e670aSJaegeuk Kim static int f2fs_write_meta_pages(struct address_space *mapping, 212127e670aSJaegeuk Kim struct writeback_control *wbc) 213127e670aSJaegeuk Kim { 2144081363fSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); 21550c8cdb3SJaegeuk Kim long diff, written; 216127e670aSJaegeuk Kim 217e5748434SChao Yu trace_f2fs_writepages(mapping->host, wbc, META); 218e5748434SChao Yu 2195459aa97SJaegeuk Kim /* collect a number of dirty meta pages and write together */ 22050c8cdb3SJaegeuk Kim if (wbc->for_kupdate || 22150c8cdb3SJaegeuk Kim get_pages(sbi, F2FS_DIRTY_META) < nr_pages_to_skip(sbi, META)) 222d3baf95dSJaegeuk Kim goto skip_write; 223127e670aSJaegeuk Kim 224127e670aSJaegeuk Kim /* if mounting is failed, skip writing node pages */ 225127e670aSJaegeuk Kim mutex_lock(&sbi->cp_mutex); 22650c8cdb3SJaegeuk Kim diff = nr_pages_to_write(sbi, META, wbc); 22750c8cdb3SJaegeuk Kim written = sync_meta_pages(sbi, META, wbc->nr_to_write); 228127e670aSJaegeuk Kim mutex_unlock(&sbi->cp_mutex); 22950c8cdb3SJaegeuk Kim wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff); 230127e670aSJaegeuk Kim return 0; 231d3baf95dSJaegeuk Kim 232d3baf95dSJaegeuk Kim skip_write: 233d3baf95dSJaegeuk Kim wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_META); 234d3baf95dSJaegeuk Kim return 0; 235127e670aSJaegeuk Kim } 236127e670aSJaegeuk Kim 237127e670aSJaegeuk Kim long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type, 238127e670aSJaegeuk Kim long nr_to_write) 239127e670aSJaegeuk Kim { 2409df27d98SGu Zheng struct address_space *mapping = META_MAPPING(sbi); 241127e670aSJaegeuk Kim pgoff_t index = 0, end = LONG_MAX; 242127e670aSJaegeuk Kim struct pagevec pvec; 243127e670aSJaegeuk Kim long nwritten = 0; 244127e670aSJaegeuk Kim struct writeback_control wbc = { 245127e670aSJaegeuk Kim .for_reclaim = 0, 246127e670aSJaegeuk Kim }; 247127e670aSJaegeuk Kim 248127e670aSJaegeuk Kim pagevec_init(&pvec, 0); 249127e670aSJaegeuk Kim 250127e670aSJaegeuk Kim while (index <= end) { 251127e670aSJaegeuk Kim int i, nr_pages; 252127e670aSJaegeuk Kim nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, 253127e670aSJaegeuk Kim PAGECACHE_TAG_DIRTY, 254127e670aSJaegeuk Kim min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); 255cfb271d4SChao Yu if (unlikely(nr_pages == 0)) 256127e670aSJaegeuk Kim break; 257127e670aSJaegeuk Kim 258127e670aSJaegeuk Kim for (i = 0; i < nr_pages; i++) { 259127e670aSJaegeuk Kim struct page *page = pvec.pages[i]; 260203681f6SJaegeuk Kim 261127e670aSJaegeuk Kim lock_page(page); 262203681f6SJaegeuk Kim 263203681f6SJaegeuk Kim if (unlikely(page->mapping != mapping)) { 264203681f6SJaegeuk Kim continue_unlock: 265203681f6SJaegeuk Kim unlock_page(page); 266203681f6SJaegeuk Kim continue; 267203681f6SJaegeuk Kim } 268203681f6SJaegeuk Kim if (!PageDirty(page)) { 269203681f6SJaegeuk Kim /* someone wrote it for us */ 270203681f6SJaegeuk Kim goto continue_unlock; 271203681f6SJaegeuk Kim } 272203681f6SJaegeuk Kim 273203681f6SJaegeuk Kim if (!clear_page_dirty_for_io(page)) 274203681f6SJaegeuk Kim goto continue_unlock; 275203681f6SJaegeuk Kim 276577e3495SJaegeuk Kim if (f2fs_write_meta_page(page, &wbc)) { 277577e3495SJaegeuk Kim unlock_page(page); 278577e3495SJaegeuk Kim break; 279577e3495SJaegeuk Kim } 280cfb271d4SChao Yu nwritten++; 281cfb271d4SChao Yu if (unlikely(nwritten >= nr_to_write)) 282127e670aSJaegeuk Kim break; 283127e670aSJaegeuk Kim } 284127e670aSJaegeuk Kim pagevec_release(&pvec); 285127e670aSJaegeuk Kim cond_resched(); 286127e670aSJaegeuk Kim } 287127e670aSJaegeuk Kim 288127e670aSJaegeuk Kim if (nwritten) 289458e6197SJaegeuk Kim f2fs_submit_merged_bio(sbi, type, WRITE); 290127e670aSJaegeuk Kim 291127e670aSJaegeuk Kim return nwritten; 292127e670aSJaegeuk Kim } 293127e670aSJaegeuk Kim 294127e670aSJaegeuk Kim static int f2fs_set_meta_page_dirty(struct page *page) 295127e670aSJaegeuk Kim { 29626c6b887SJaegeuk Kim trace_f2fs_set_page_dirty(page, META); 29726c6b887SJaegeuk Kim 298127e670aSJaegeuk Kim SetPageUptodate(page); 299127e670aSJaegeuk Kim if (!PageDirty(page)) { 300127e670aSJaegeuk Kim __set_page_dirty_nobuffers(page); 3014081363fSJaegeuk Kim inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META); 302127e670aSJaegeuk Kim return 1; 303127e670aSJaegeuk Kim } 304127e670aSJaegeuk Kim return 0; 305127e670aSJaegeuk Kim } 306127e670aSJaegeuk Kim 307127e670aSJaegeuk Kim const struct address_space_operations f2fs_meta_aops = { 308127e670aSJaegeuk Kim .writepage = f2fs_write_meta_page, 309127e670aSJaegeuk Kim .writepages = f2fs_write_meta_pages, 310127e670aSJaegeuk Kim .set_page_dirty = f2fs_set_meta_page_dirty, 311127e670aSJaegeuk Kim }; 312127e670aSJaegeuk Kim 3136451e041SJaegeuk Kim static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) 314953e6cc6SJaegeuk Kim { 31567298804SChao Yu struct inode_management *im = &sbi->im[type]; 31639efac41SJaegeuk Kim struct ino_entry *e; 31739efac41SJaegeuk Kim retry: 318769ec6e5SJaegeuk Kim if (radix_tree_preload(GFP_NOFS)) { 319769ec6e5SJaegeuk Kim cond_resched(); 320769ec6e5SJaegeuk Kim goto retry; 321769ec6e5SJaegeuk Kim } 322769ec6e5SJaegeuk Kim 32367298804SChao Yu spin_lock(&im->ino_lock); 324953e6cc6SJaegeuk Kim 32567298804SChao Yu e = radix_tree_lookup(&im->ino_root, ino); 32639efac41SJaegeuk Kim if (!e) { 32739efac41SJaegeuk Kim e = kmem_cache_alloc(ino_entry_slab, GFP_ATOMIC); 32839efac41SJaegeuk Kim if (!e) { 32967298804SChao Yu spin_unlock(&im->ino_lock); 330769ec6e5SJaegeuk Kim radix_tree_preload_end(); 33139efac41SJaegeuk Kim goto retry; 33239efac41SJaegeuk Kim } 33367298804SChao Yu if (radix_tree_insert(&im->ino_root, ino, e)) { 33467298804SChao Yu spin_unlock(&im->ino_lock); 33539efac41SJaegeuk Kim kmem_cache_free(ino_entry_slab, e); 336769ec6e5SJaegeuk Kim radix_tree_preload_end(); 33739efac41SJaegeuk Kim goto retry; 33839efac41SJaegeuk Kim } 33939efac41SJaegeuk Kim memset(e, 0, sizeof(struct ino_entry)); 34039efac41SJaegeuk Kim e->ino = ino; 34139efac41SJaegeuk Kim 34267298804SChao Yu list_add_tail(&e->list, &im->ino_list); 3438c402946SJaegeuk Kim if (type != ORPHAN_INO) 34467298804SChao Yu im->ino_num++; 34539efac41SJaegeuk Kim } 34667298804SChao Yu spin_unlock(&im->ino_lock); 347769ec6e5SJaegeuk Kim radix_tree_preload_end(); 348953e6cc6SJaegeuk Kim } 349953e6cc6SJaegeuk Kim 3506451e041SJaegeuk Kim static void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) 351953e6cc6SJaegeuk Kim { 35267298804SChao Yu struct inode_management *im = &sbi->im[type]; 3536451e041SJaegeuk Kim struct ino_entry *e; 354953e6cc6SJaegeuk Kim 35567298804SChao Yu spin_lock(&im->ino_lock); 35667298804SChao Yu e = radix_tree_lookup(&im->ino_root, ino); 35739efac41SJaegeuk Kim if (e) { 358953e6cc6SJaegeuk Kim list_del(&e->list); 35967298804SChao Yu radix_tree_delete(&im->ino_root, ino); 36067298804SChao Yu im->ino_num--; 36167298804SChao Yu spin_unlock(&im->ino_lock); 3626451e041SJaegeuk Kim kmem_cache_free(ino_entry_slab, e); 363953e6cc6SJaegeuk Kim return; 364953e6cc6SJaegeuk Kim } 36567298804SChao Yu spin_unlock(&im->ino_lock); 366953e6cc6SJaegeuk Kim } 367953e6cc6SJaegeuk Kim 368fff04f90SJaegeuk Kim void add_dirty_inode(struct f2fs_sb_info *sbi, nid_t ino, int type) 369fff04f90SJaegeuk Kim { 370fff04f90SJaegeuk Kim /* add new dirty ino entry into list */ 371fff04f90SJaegeuk Kim __add_ino_entry(sbi, ino, type); 372fff04f90SJaegeuk Kim } 373fff04f90SJaegeuk Kim 374fff04f90SJaegeuk Kim void remove_dirty_inode(struct f2fs_sb_info *sbi, nid_t ino, int type) 375fff04f90SJaegeuk Kim { 376fff04f90SJaegeuk Kim /* remove dirty ino entry from list */ 377fff04f90SJaegeuk Kim __remove_ino_entry(sbi, ino, type); 378fff04f90SJaegeuk Kim } 379fff04f90SJaegeuk Kim 380fff04f90SJaegeuk Kim /* mode should be APPEND_INO or UPDATE_INO */ 381fff04f90SJaegeuk Kim bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode) 382fff04f90SJaegeuk Kim { 38367298804SChao Yu struct inode_management *im = &sbi->im[mode]; 384fff04f90SJaegeuk Kim struct ino_entry *e; 38567298804SChao Yu 38667298804SChao Yu spin_lock(&im->ino_lock); 38767298804SChao Yu e = radix_tree_lookup(&im->ino_root, ino); 38867298804SChao Yu spin_unlock(&im->ino_lock); 389fff04f90SJaegeuk Kim return e ? true : false; 390fff04f90SJaegeuk Kim } 391fff04f90SJaegeuk Kim 3926f12ac25SJaegeuk Kim void release_dirty_inode(struct f2fs_sb_info *sbi) 393fff04f90SJaegeuk Kim { 394fff04f90SJaegeuk Kim struct ino_entry *e, *tmp; 395fff04f90SJaegeuk Kim int i; 396fff04f90SJaegeuk Kim 397fff04f90SJaegeuk Kim for (i = APPEND_INO; i <= UPDATE_INO; i++) { 39867298804SChao Yu struct inode_management *im = &sbi->im[i]; 39967298804SChao Yu 40067298804SChao Yu spin_lock(&im->ino_lock); 40167298804SChao Yu list_for_each_entry_safe(e, tmp, &im->ino_list, list) { 402fff04f90SJaegeuk Kim list_del(&e->list); 40367298804SChao Yu radix_tree_delete(&im->ino_root, e->ino); 404fff04f90SJaegeuk Kim kmem_cache_free(ino_entry_slab, e); 40567298804SChao Yu im->ino_num--; 406fff04f90SJaegeuk Kim } 40767298804SChao Yu spin_unlock(&im->ino_lock); 408fff04f90SJaegeuk Kim } 409fff04f90SJaegeuk Kim } 410fff04f90SJaegeuk Kim 411cbd56e7dSJaegeuk Kim int acquire_orphan_inode(struct f2fs_sb_info *sbi) 412127e670aSJaegeuk Kim { 41367298804SChao Yu struct inode_management *im = &sbi->im[ORPHAN_INO]; 414127e670aSJaegeuk Kim int err = 0; 415127e670aSJaegeuk Kim 41667298804SChao Yu spin_lock(&im->ino_lock); 41767298804SChao Yu if (unlikely(im->ino_num >= sbi->max_orphans)) 418127e670aSJaegeuk Kim err = -ENOSPC; 419cbd56e7dSJaegeuk Kim else 42067298804SChao Yu im->ino_num++; 42167298804SChao Yu spin_unlock(&im->ino_lock); 4220d47c1adSGu Zheng 423127e670aSJaegeuk Kim return err; 424127e670aSJaegeuk Kim } 425127e670aSJaegeuk Kim 426cbd56e7dSJaegeuk Kim void release_orphan_inode(struct f2fs_sb_info *sbi) 427cbd56e7dSJaegeuk Kim { 42867298804SChao Yu struct inode_management *im = &sbi->im[ORPHAN_INO]; 42967298804SChao Yu 43067298804SChao Yu spin_lock(&im->ino_lock); 43167298804SChao Yu f2fs_bug_on(sbi, im->ino_num == 0); 43267298804SChao Yu im->ino_num--; 43367298804SChao Yu spin_unlock(&im->ino_lock); 434cbd56e7dSJaegeuk Kim } 435cbd56e7dSJaegeuk Kim 436127e670aSJaegeuk Kim void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) 437127e670aSJaegeuk Kim { 43839efac41SJaegeuk Kim /* add new orphan ino entry into list */ 4396451e041SJaegeuk Kim __add_ino_entry(sbi, ino, ORPHAN_INO); 440127e670aSJaegeuk Kim } 441127e670aSJaegeuk Kim 442127e670aSJaegeuk Kim void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) 443127e670aSJaegeuk Kim { 444953e6cc6SJaegeuk Kim /* remove orphan entry from orphan list */ 4456451e041SJaegeuk Kim __remove_ino_entry(sbi, ino, ORPHAN_INO); 446127e670aSJaegeuk Kim } 447127e670aSJaegeuk Kim 448127e670aSJaegeuk Kim static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) 449127e670aSJaegeuk Kim { 450127e670aSJaegeuk Kim struct inode *inode = f2fs_iget(sbi->sb, ino); 4519850cf4aSJaegeuk Kim f2fs_bug_on(sbi, IS_ERR(inode)); 452127e670aSJaegeuk Kim clear_nlink(inode); 453127e670aSJaegeuk Kim 454127e670aSJaegeuk Kim /* truncate all the data during iput */ 455127e670aSJaegeuk Kim iput(inode); 456127e670aSJaegeuk Kim } 457127e670aSJaegeuk Kim 4588f99a946SChao Yu void recover_orphan_inodes(struct f2fs_sb_info *sbi) 459127e670aSJaegeuk Kim { 460127e670aSJaegeuk Kim block_t start_blk, orphan_blkaddr, i, j; 461127e670aSJaegeuk Kim 46225ca923bSJaegeuk Kim if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG)) 4638f99a946SChao Yu return; 464127e670aSJaegeuk Kim 465aabe5136SHaicheng Li sbi->por_doing = true; 4661dbe4152SChangman Lee 4671dbe4152SChangman Lee start_blk = __start_cp_addr(sbi) + 1 + 4681dbe4152SChangman Lee le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); 469127e670aSJaegeuk Kim orphan_blkaddr = __start_sum_addr(sbi) - 1; 470127e670aSJaegeuk Kim 471662befdaSChao Yu ra_meta_pages(sbi, start_blk, orphan_blkaddr, META_CP); 472662befdaSChao Yu 473127e670aSJaegeuk Kim for (i = 0; i < orphan_blkaddr; i++) { 474127e670aSJaegeuk Kim struct page *page = get_meta_page(sbi, start_blk + i); 475127e670aSJaegeuk Kim struct f2fs_orphan_block *orphan_blk; 476127e670aSJaegeuk Kim 477127e670aSJaegeuk Kim orphan_blk = (struct f2fs_orphan_block *)page_address(page); 478127e670aSJaegeuk Kim for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) { 479127e670aSJaegeuk Kim nid_t ino = le32_to_cpu(orphan_blk->ino[j]); 480127e670aSJaegeuk Kim recover_orphan_inode(sbi, ino); 481127e670aSJaegeuk Kim } 482127e670aSJaegeuk Kim f2fs_put_page(page, 1); 483127e670aSJaegeuk Kim } 484127e670aSJaegeuk Kim /* clear Orphan Flag */ 48525ca923bSJaegeuk Kim clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG); 486aabe5136SHaicheng Li sbi->por_doing = false; 4878f99a946SChao Yu return; 488127e670aSJaegeuk Kim } 489127e670aSJaegeuk Kim 490127e670aSJaegeuk Kim static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) 491127e670aSJaegeuk Kim { 492502c6e0bSGu Zheng struct list_head *head; 493127e670aSJaegeuk Kim struct f2fs_orphan_block *orphan_blk = NULL; 494127e670aSJaegeuk Kim unsigned int nentries = 0; 4954531929eSGu Zheng unsigned short index; 4968c402946SJaegeuk Kim unsigned short orphan_blocks; 4974531929eSGu Zheng struct page *page = NULL; 4986451e041SJaegeuk Kim struct ino_entry *orphan = NULL; 49967298804SChao Yu struct inode_management *im = &sbi->im[ORPHAN_INO]; 500127e670aSJaegeuk Kim 50167298804SChao Yu orphan_blocks = GET_ORPHAN_BLOCKS(im->ino_num); 5028c402946SJaegeuk Kim 5034531929eSGu Zheng for (index = 0; index < orphan_blocks; index++) 50463f5384cSGu Zheng grab_meta_page(sbi, start_blk + index); 505127e670aSJaegeuk Kim 5064531929eSGu Zheng index = 1; 50767298804SChao Yu spin_lock(&im->ino_lock); 50867298804SChao Yu head = &im->ino_list; 509127e670aSJaegeuk Kim 510127e670aSJaegeuk Kim /* loop for each orphan inode entry and write them in Jornal block */ 511502c6e0bSGu Zheng list_for_each_entry(orphan, head, list) { 512502c6e0bSGu Zheng if (!page) { 51363f5384cSGu Zheng page = find_get_page(META_MAPPING(sbi), start_blk++); 5149850cf4aSJaegeuk Kim f2fs_bug_on(sbi, !page); 515502c6e0bSGu Zheng orphan_blk = 516502c6e0bSGu Zheng (struct f2fs_orphan_block *)page_address(page); 517502c6e0bSGu Zheng memset(orphan_blk, 0, sizeof(*orphan_blk)); 51863f5384cSGu Zheng f2fs_put_page(page, 0); 519502c6e0bSGu Zheng } 520127e670aSJaegeuk Kim 52136795567SGu Zheng orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino); 522127e670aSJaegeuk Kim 52336795567SGu Zheng if (nentries == F2FS_ORPHANS_PER_BLOCK) { 524127e670aSJaegeuk Kim /* 525127e670aSJaegeuk Kim * an orphan block is full of 1020 entries, 526127e670aSJaegeuk Kim * then we need to flush current orphan blocks 527127e670aSJaegeuk Kim * and bring another one in memory 528127e670aSJaegeuk Kim */ 529127e670aSJaegeuk Kim orphan_blk->blk_addr = cpu_to_le16(index); 530127e670aSJaegeuk Kim orphan_blk->blk_count = cpu_to_le16(orphan_blocks); 531127e670aSJaegeuk Kim orphan_blk->entry_count = cpu_to_le32(nentries); 532127e670aSJaegeuk Kim set_page_dirty(page); 533127e670aSJaegeuk Kim f2fs_put_page(page, 1); 534127e670aSJaegeuk Kim index++; 535127e670aSJaegeuk Kim nentries = 0; 536127e670aSJaegeuk Kim page = NULL; 537127e670aSJaegeuk Kim } 538127e670aSJaegeuk Kim } 539127e670aSJaegeuk Kim 540502c6e0bSGu Zheng if (page) { 541127e670aSJaegeuk Kim orphan_blk->blk_addr = cpu_to_le16(index); 542127e670aSJaegeuk Kim orphan_blk->blk_count = cpu_to_le16(orphan_blocks); 543127e670aSJaegeuk Kim orphan_blk->entry_count = cpu_to_le32(nentries); 544127e670aSJaegeuk Kim set_page_dirty(page); 545127e670aSJaegeuk Kim f2fs_put_page(page, 1); 546502c6e0bSGu Zheng } 547502c6e0bSGu Zheng 54867298804SChao Yu spin_unlock(&im->ino_lock); 549127e670aSJaegeuk Kim } 550127e670aSJaegeuk Kim 551127e670aSJaegeuk Kim static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, 552127e670aSJaegeuk Kim block_t cp_addr, unsigned long long *version) 553127e670aSJaegeuk Kim { 554127e670aSJaegeuk Kim struct page *cp_page_1, *cp_page_2 = NULL; 555127e670aSJaegeuk Kim unsigned long blk_size = sbi->blocksize; 556127e670aSJaegeuk Kim struct f2fs_checkpoint *cp_block; 557127e670aSJaegeuk Kim unsigned long long cur_version = 0, pre_version = 0; 558127e670aSJaegeuk Kim size_t crc_offset; 5597e586fa0SJaegeuk Kim __u32 crc = 0; 560127e670aSJaegeuk Kim 561127e670aSJaegeuk Kim /* Read the 1st cp block in this CP pack */ 562127e670aSJaegeuk Kim cp_page_1 = get_meta_page(sbi, cp_addr); 563127e670aSJaegeuk Kim 564127e670aSJaegeuk Kim /* get the version number */ 565127e670aSJaegeuk Kim cp_block = (struct f2fs_checkpoint *)page_address(cp_page_1); 566127e670aSJaegeuk Kim crc_offset = le32_to_cpu(cp_block->checksum_offset); 567127e670aSJaegeuk Kim if (crc_offset >= blk_size) 568127e670aSJaegeuk Kim goto invalid_cp1; 569127e670aSJaegeuk Kim 5707e586fa0SJaegeuk Kim crc = le32_to_cpu(*((__u32 *)((unsigned char *)cp_block + crc_offset))); 571127e670aSJaegeuk Kim if (!f2fs_crc_valid(crc, cp_block, crc_offset)) 572127e670aSJaegeuk Kim goto invalid_cp1; 573127e670aSJaegeuk Kim 574d71b5564SJaegeuk Kim pre_version = cur_cp_version(cp_block); 575127e670aSJaegeuk Kim 576127e670aSJaegeuk Kim /* Read the 2nd cp block in this CP pack */ 57725ca923bSJaegeuk Kim cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1; 578127e670aSJaegeuk Kim cp_page_2 = get_meta_page(sbi, cp_addr); 579127e670aSJaegeuk Kim 580127e670aSJaegeuk Kim cp_block = (struct f2fs_checkpoint *)page_address(cp_page_2); 581127e670aSJaegeuk Kim crc_offset = le32_to_cpu(cp_block->checksum_offset); 582127e670aSJaegeuk Kim if (crc_offset >= blk_size) 583127e670aSJaegeuk Kim goto invalid_cp2; 584127e670aSJaegeuk Kim 5857e586fa0SJaegeuk Kim crc = le32_to_cpu(*((__u32 *)((unsigned char *)cp_block + crc_offset))); 586127e670aSJaegeuk Kim if (!f2fs_crc_valid(crc, cp_block, crc_offset)) 587127e670aSJaegeuk Kim goto invalid_cp2; 588127e670aSJaegeuk Kim 589d71b5564SJaegeuk Kim cur_version = cur_cp_version(cp_block); 590127e670aSJaegeuk Kim 591127e670aSJaegeuk Kim if (cur_version == pre_version) { 592127e670aSJaegeuk Kim *version = cur_version; 593127e670aSJaegeuk Kim f2fs_put_page(cp_page_2, 1); 594127e670aSJaegeuk Kim return cp_page_1; 595127e670aSJaegeuk Kim } 596127e670aSJaegeuk Kim invalid_cp2: 597127e670aSJaegeuk Kim f2fs_put_page(cp_page_2, 1); 598127e670aSJaegeuk Kim invalid_cp1: 599127e670aSJaegeuk Kim f2fs_put_page(cp_page_1, 1); 600127e670aSJaegeuk Kim return NULL; 601127e670aSJaegeuk Kim } 602127e670aSJaegeuk Kim 603127e670aSJaegeuk Kim int get_valid_checkpoint(struct f2fs_sb_info *sbi) 604127e670aSJaegeuk Kim { 605127e670aSJaegeuk Kim struct f2fs_checkpoint *cp_block; 606127e670aSJaegeuk Kim struct f2fs_super_block *fsb = sbi->raw_super; 607127e670aSJaegeuk Kim struct page *cp1, *cp2, *cur_page; 608127e670aSJaegeuk Kim unsigned long blk_size = sbi->blocksize; 609127e670aSJaegeuk Kim unsigned long long cp1_version = 0, cp2_version = 0; 610127e670aSJaegeuk Kim unsigned long long cp_start_blk_no; 6111dbe4152SChangman Lee unsigned int cp_blks = 1 + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); 6121dbe4152SChangman Lee block_t cp_blk_no; 6131dbe4152SChangman Lee int i; 614127e670aSJaegeuk Kim 6151dbe4152SChangman Lee sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL); 616127e670aSJaegeuk Kim if (!sbi->ckpt) 617127e670aSJaegeuk Kim return -ENOMEM; 618127e670aSJaegeuk Kim /* 619127e670aSJaegeuk Kim * Finding out valid cp block involves read both 620127e670aSJaegeuk Kim * sets( cp pack1 and cp pack 2) 621127e670aSJaegeuk Kim */ 622127e670aSJaegeuk Kim cp_start_blk_no = le32_to_cpu(fsb->cp_blkaddr); 623127e670aSJaegeuk Kim cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version); 624127e670aSJaegeuk Kim 625127e670aSJaegeuk Kim /* The second checkpoint pack should start at the next segment */ 626f9a4e6dfSJaegeuk Kim cp_start_blk_no += ((unsigned long long)1) << 627f9a4e6dfSJaegeuk Kim le32_to_cpu(fsb->log_blocks_per_seg); 628127e670aSJaegeuk Kim cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version); 629127e670aSJaegeuk Kim 630127e670aSJaegeuk Kim if (cp1 && cp2) { 631127e670aSJaegeuk Kim if (ver_after(cp2_version, cp1_version)) 632127e670aSJaegeuk Kim cur_page = cp2; 633127e670aSJaegeuk Kim else 634127e670aSJaegeuk Kim cur_page = cp1; 635127e670aSJaegeuk Kim } else if (cp1) { 636127e670aSJaegeuk Kim cur_page = cp1; 637127e670aSJaegeuk Kim } else if (cp2) { 638127e670aSJaegeuk Kim cur_page = cp2; 639127e670aSJaegeuk Kim } else { 640127e670aSJaegeuk Kim goto fail_no_cp; 641127e670aSJaegeuk Kim } 642127e670aSJaegeuk Kim 643127e670aSJaegeuk Kim cp_block = (struct f2fs_checkpoint *)page_address(cur_page); 644127e670aSJaegeuk Kim memcpy(sbi->ckpt, cp_block, blk_size); 645127e670aSJaegeuk Kim 6461dbe4152SChangman Lee if (cp_blks <= 1) 6471dbe4152SChangman Lee goto done; 6481dbe4152SChangman Lee 6491dbe4152SChangman Lee cp_blk_no = le32_to_cpu(fsb->cp_blkaddr); 6501dbe4152SChangman Lee if (cur_page == cp2) 6511dbe4152SChangman Lee cp_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg); 6521dbe4152SChangman Lee 6531dbe4152SChangman Lee for (i = 1; i < cp_blks; i++) { 6541dbe4152SChangman Lee void *sit_bitmap_ptr; 6551dbe4152SChangman Lee unsigned char *ckpt = (unsigned char *)sbi->ckpt; 6561dbe4152SChangman Lee 6571dbe4152SChangman Lee cur_page = get_meta_page(sbi, cp_blk_no + i); 6581dbe4152SChangman Lee sit_bitmap_ptr = page_address(cur_page); 6591dbe4152SChangman Lee memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size); 6601dbe4152SChangman Lee f2fs_put_page(cur_page, 1); 6611dbe4152SChangman Lee } 6621dbe4152SChangman Lee done: 663127e670aSJaegeuk Kim f2fs_put_page(cp1, 1); 664127e670aSJaegeuk Kim f2fs_put_page(cp2, 1); 665127e670aSJaegeuk Kim return 0; 666127e670aSJaegeuk Kim 667127e670aSJaegeuk Kim fail_no_cp: 668127e670aSJaegeuk Kim kfree(sbi->ckpt); 669127e670aSJaegeuk Kim return -EINVAL; 670127e670aSJaegeuk Kim } 671127e670aSJaegeuk Kim 6725deb8267SJaegeuk Kim static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new) 673127e670aSJaegeuk Kim { 6744081363fSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 6752d7b822aSChao Yu 676ed57c27fSJaegeuk Kim if (is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR)) 6775deb8267SJaegeuk Kim return -EEXIST; 6782d7b822aSChao Yu 679ed57c27fSJaegeuk Kim set_inode_flag(F2FS_I(inode), FI_DIRTY_DIR); 680ed57c27fSJaegeuk Kim F2FS_I(inode)->dirty_dir = new; 681ed57c27fSJaegeuk Kim list_add_tail(&new->list, &sbi->dir_inode_list); 682dcdfff65SJaegeuk Kim stat_inc_dirty_dir(sbi); 6835deb8267SJaegeuk Kim return 0; 6845deb8267SJaegeuk Kim } 6855deb8267SJaegeuk Kim 686a7ffdbe2SJaegeuk Kim void update_dirty_page(struct inode *inode, struct page *page) 6875deb8267SJaegeuk Kim { 6884081363fSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 6895deb8267SJaegeuk Kim struct dir_inode_entry *new; 690cf0ee0f0SChao Yu int ret = 0; 6915deb8267SJaegeuk Kim 692a7ffdbe2SJaegeuk Kim if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode)) 693127e670aSJaegeuk Kim return; 6947bd59381SGu Zheng 695a7ffdbe2SJaegeuk Kim if (!S_ISDIR(inode->i_mode)) { 696a7ffdbe2SJaegeuk Kim inode_inc_dirty_pages(inode); 697a7ffdbe2SJaegeuk Kim goto out; 698a7ffdbe2SJaegeuk Kim } 699a7ffdbe2SJaegeuk Kim 7007bd59381SGu Zheng new = f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS); 701127e670aSJaegeuk Kim new->inode = inode; 702127e670aSJaegeuk Kim INIT_LIST_HEAD(&new->list); 703127e670aSJaegeuk Kim 704127e670aSJaegeuk Kim spin_lock(&sbi->dir_inode_lock); 705cf0ee0f0SChao Yu ret = __add_dirty_inode(inode, new); 706a7ffdbe2SJaegeuk Kim inode_inc_dirty_pages(inode); 7075deb8267SJaegeuk Kim spin_unlock(&sbi->dir_inode_lock); 708cf0ee0f0SChao Yu 709cf0ee0f0SChao Yu if (ret) 710cf0ee0f0SChao Yu kmem_cache_free(inode_entry_slab, new); 711a7ffdbe2SJaegeuk Kim out: 712a7ffdbe2SJaegeuk Kim SetPagePrivate(page); 7135deb8267SJaegeuk Kim } 714127e670aSJaegeuk Kim 7155deb8267SJaegeuk Kim void add_dirty_dir_inode(struct inode *inode) 7165deb8267SJaegeuk Kim { 7174081363fSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 7187bd59381SGu Zheng struct dir_inode_entry *new = 7197bd59381SGu Zheng f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS); 720cf0ee0f0SChao Yu int ret = 0; 7217bd59381SGu Zheng 7225deb8267SJaegeuk Kim new->inode = inode; 7235deb8267SJaegeuk Kim INIT_LIST_HEAD(&new->list); 7245deb8267SJaegeuk Kim 7255deb8267SJaegeuk Kim spin_lock(&sbi->dir_inode_lock); 726cf0ee0f0SChao Yu ret = __add_dirty_inode(inode, new); 727127e670aSJaegeuk Kim spin_unlock(&sbi->dir_inode_lock); 728cf0ee0f0SChao Yu 729cf0ee0f0SChao Yu if (ret) 730cf0ee0f0SChao Yu kmem_cache_free(inode_entry_slab, new); 731127e670aSJaegeuk Kim } 732127e670aSJaegeuk Kim 733127e670aSJaegeuk Kim void remove_dirty_dir_inode(struct inode *inode) 734127e670aSJaegeuk Kim { 7354081363fSJaegeuk Kim struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 7362d7b822aSChao Yu struct dir_inode_entry *entry; 737127e670aSJaegeuk Kim 738127e670aSJaegeuk Kim if (!S_ISDIR(inode->i_mode)) 739127e670aSJaegeuk Kim return; 740127e670aSJaegeuk Kim 741127e670aSJaegeuk Kim spin_lock(&sbi->dir_inode_lock); 742a7ffdbe2SJaegeuk Kim if (get_dirty_pages(inode) || 743ed57c27fSJaegeuk Kim !is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR)) { 7443b10b1fdSJaegeuk Kim spin_unlock(&sbi->dir_inode_lock); 7453b10b1fdSJaegeuk Kim return; 7463b10b1fdSJaegeuk Kim } 747127e670aSJaegeuk Kim 748ed57c27fSJaegeuk Kim entry = F2FS_I(inode)->dirty_dir; 749127e670aSJaegeuk Kim list_del(&entry->list); 750ed57c27fSJaegeuk Kim F2FS_I(inode)->dirty_dir = NULL; 751ed57c27fSJaegeuk Kim clear_inode_flag(F2FS_I(inode), FI_DIRTY_DIR); 752dcdfff65SJaegeuk Kim stat_dec_dirty_dir(sbi); 753cf0ee0f0SChao Yu spin_unlock(&sbi->dir_inode_lock); 754cf0ee0f0SChao Yu kmem_cache_free(inode_entry_slab, entry); 75574d0b917SJaegeuk Kim 75674d0b917SJaegeuk Kim /* Only from the recovery routine */ 757afc3eda2SJaegeuk Kim if (is_inode_flag_set(F2FS_I(inode), FI_DELAY_IPUT)) { 758afc3eda2SJaegeuk Kim clear_inode_flag(F2FS_I(inode), FI_DELAY_IPUT); 75974d0b917SJaegeuk Kim iput(inode); 76074d0b917SJaegeuk Kim } 761afc3eda2SJaegeuk Kim } 76274d0b917SJaegeuk Kim 763127e670aSJaegeuk Kim void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi) 764127e670aSJaegeuk Kim { 765ce3b7d80SGu Zheng struct list_head *head; 766127e670aSJaegeuk Kim struct dir_inode_entry *entry; 767127e670aSJaegeuk Kim struct inode *inode; 768127e670aSJaegeuk Kim retry: 769af41d3eeSJaegeuk Kim if (unlikely(f2fs_cp_error(sbi))) 770af41d3eeSJaegeuk Kim return; 771af41d3eeSJaegeuk Kim 772127e670aSJaegeuk Kim spin_lock(&sbi->dir_inode_lock); 773ce3b7d80SGu Zheng 774ce3b7d80SGu Zheng head = &sbi->dir_inode_list; 775127e670aSJaegeuk Kim if (list_empty(head)) { 776127e670aSJaegeuk Kim spin_unlock(&sbi->dir_inode_lock); 777127e670aSJaegeuk Kim return; 778127e670aSJaegeuk Kim } 779127e670aSJaegeuk Kim entry = list_entry(head->next, struct dir_inode_entry, list); 780127e670aSJaegeuk Kim inode = igrab(entry->inode); 781127e670aSJaegeuk Kim spin_unlock(&sbi->dir_inode_lock); 782127e670aSJaegeuk Kim if (inode) { 78387d6f890SJaegeuk Kim filemap_fdatawrite(inode->i_mapping); 784127e670aSJaegeuk Kim iput(inode); 785127e670aSJaegeuk Kim } else { 786127e670aSJaegeuk Kim /* 787127e670aSJaegeuk Kim * We should submit bio, since it exists several 788127e670aSJaegeuk Kim * wribacking dentry pages in the freeing inode. 789127e670aSJaegeuk Kim */ 790458e6197SJaegeuk Kim f2fs_submit_merged_bio(sbi, DATA, WRITE); 791127e670aSJaegeuk Kim } 792127e670aSJaegeuk Kim goto retry; 793127e670aSJaegeuk Kim } 794127e670aSJaegeuk Kim 7950a8165d7SJaegeuk Kim /* 796127e670aSJaegeuk Kim * Freeze all the FS-operations for checkpoint. 797127e670aSJaegeuk Kim */ 798cf779cabSJaegeuk Kim static int block_operations(struct f2fs_sb_info *sbi) 799127e670aSJaegeuk Kim { 800127e670aSJaegeuk Kim struct writeback_control wbc = { 801127e670aSJaegeuk Kim .sync_mode = WB_SYNC_ALL, 802127e670aSJaegeuk Kim .nr_to_write = LONG_MAX, 803127e670aSJaegeuk Kim .for_reclaim = 0, 804127e670aSJaegeuk Kim }; 805c718379bSJaegeuk Kim struct blk_plug plug; 806cf779cabSJaegeuk Kim int err = 0; 807c718379bSJaegeuk Kim 808c718379bSJaegeuk Kim blk_start_plug(&plug); 809c718379bSJaegeuk Kim 81039936837SJaegeuk Kim retry_flush_dents: 811e479556bSGu Zheng f2fs_lock_all(sbi); 812127e670aSJaegeuk Kim /* write all the dirty dentry pages */ 813127e670aSJaegeuk Kim if (get_pages(sbi, F2FS_DIRTY_DENTS)) { 814e479556bSGu Zheng f2fs_unlock_all(sbi); 81539936837SJaegeuk Kim sync_dirty_dir_inodes(sbi); 816cf779cabSJaegeuk Kim if (unlikely(f2fs_cp_error(sbi))) { 817cf779cabSJaegeuk Kim err = -EIO; 818cf779cabSJaegeuk Kim goto out; 819cf779cabSJaegeuk Kim } 82039936837SJaegeuk Kim goto retry_flush_dents; 821127e670aSJaegeuk Kim } 822127e670aSJaegeuk Kim 823127e670aSJaegeuk Kim /* 824e1c42045Sarter97 * POR: we should ensure that there are no dirty node pages 825127e670aSJaegeuk Kim * until finishing nat/sit flush. 826127e670aSJaegeuk Kim */ 82739936837SJaegeuk Kim retry_flush_nodes: 828b3582c68SChao Yu down_write(&sbi->node_write); 829127e670aSJaegeuk Kim 830127e670aSJaegeuk Kim if (get_pages(sbi, F2FS_DIRTY_NODES)) { 831b3582c68SChao Yu up_write(&sbi->node_write); 83239936837SJaegeuk Kim sync_node_pages(sbi, 0, &wbc); 833cf779cabSJaegeuk Kim if (unlikely(f2fs_cp_error(sbi))) { 834cf779cabSJaegeuk Kim f2fs_unlock_all(sbi); 835cf779cabSJaegeuk Kim err = -EIO; 836cf779cabSJaegeuk Kim goto out; 837cf779cabSJaegeuk Kim } 83839936837SJaegeuk Kim goto retry_flush_nodes; 839127e670aSJaegeuk Kim } 840cf779cabSJaegeuk Kim out: 841c718379bSJaegeuk Kim blk_finish_plug(&plug); 842cf779cabSJaegeuk Kim return err; 843127e670aSJaegeuk Kim } 844127e670aSJaegeuk Kim 845127e670aSJaegeuk Kim static void unblock_operations(struct f2fs_sb_info *sbi) 846127e670aSJaegeuk Kim { 847b3582c68SChao Yu up_write(&sbi->node_write); 848e479556bSGu Zheng f2fs_unlock_all(sbi); 849127e670aSJaegeuk Kim } 850127e670aSJaegeuk Kim 851fb51b5efSChangman Lee static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi) 852fb51b5efSChangman Lee { 853fb51b5efSChangman Lee DEFINE_WAIT(wait); 854fb51b5efSChangman Lee 855fb51b5efSChangman Lee for (;;) { 856fb51b5efSChangman Lee prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE); 857fb51b5efSChangman Lee 858fb51b5efSChangman Lee if (!get_pages(sbi, F2FS_WRITEBACK)) 859fb51b5efSChangman Lee break; 860fb51b5efSChangman Lee 861fb51b5efSChangman Lee io_schedule(); 862fb51b5efSChangman Lee } 863fb51b5efSChangman Lee finish_wait(&sbi->cp_wait, &wait); 864fb51b5efSChangman Lee } 865fb51b5efSChangman Lee 86675ab4cb8SJaegeuk Kim static void do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) 867127e670aSJaegeuk Kim { 868127e670aSJaegeuk Kim struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 869cf2271e7SJaegeuk Kim struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); 87077041823SHuang Ying struct f2fs_nm_info *nm_i = NM_I(sbi); 87167298804SChao Yu unsigned long orphan_num = sbi->im[ORPHAN_INO].ino_num; 87277041823SHuang Ying nid_t last_nid = nm_i->next_scan_nid; 873127e670aSJaegeuk Kim block_t start_blk; 874127e670aSJaegeuk Kim struct page *cp_page; 875127e670aSJaegeuk Kim unsigned int data_sum_blocks, orphan_blocks; 8767e586fa0SJaegeuk Kim __u32 crc32 = 0; 877127e670aSJaegeuk Kim void *kaddr; 878127e670aSJaegeuk Kim int i; 8791dbe4152SChangman Lee int cp_payload_blks = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); 880127e670aSJaegeuk Kim 8811e87a78dSJaegeuk Kim /* 8821e87a78dSJaegeuk Kim * This avoids to conduct wrong roll-forward operations and uses 8831e87a78dSJaegeuk Kim * metapages, so should be called prior to sync_meta_pages below. 8841e87a78dSJaegeuk Kim */ 885cf2271e7SJaegeuk Kim discard_next_dnode(sbi, NEXT_FREE_BLKADDR(sbi, curseg)); 886127e670aSJaegeuk Kim 887127e670aSJaegeuk Kim /* Flush all the NAT/SIT pages */ 888cf779cabSJaegeuk Kim while (get_pages(sbi, F2FS_DIRTY_META)) { 889127e670aSJaegeuk Kim sync_meta_pages(sbi, META, LONG_MAX); 890cf779cabSJaegeuk Kim if (unlikely(f2fs_cp_error(sbi))) 891cf779cabSJaegeuk Kim return; 892cf779cabSJaegeuk Kim } 893127e670aSJaegeuk Kim 894127e670aSJaegeuk Kim next_free_nid(sbi, &last_nid); 895127e670aSJaegeuk Kim 896127e670aSJaegeuk Kim /* 897127e670aSJaegeuk Kim * modify checkpoint 898127e670aSJaegeuk Kim * version number is already updated 899127e670aSJaegeuk Kim */ 900127e670aSJaegeuk Kim ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi)); 901127e670aSJaegeuk Kim ckpt->valid_block_count = cpu_to_le64(valid_user_blocks(sbi)); 902127e670aSJaegeuk Kim ckpt->free_segment_count = cpu_to_le32(free_segments(sbi)); 903b5b82205SChao Yu for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { 904127e670aSJaegeuk Kim ckpt->cur_node_segno[i] = 905127e670aSJaegeuk Kim cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_NODE)); 906127e670aSJaegeuk Kim ckpt->cur_node_blkoff[i] = 907127e670aSJaegeuk Kim cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_NODE)); 908127e670aSJaegeuk Kim ckpt->alloc_type[i + CURSEG_HOT_NODE] = 909127e670aSJaegeuk Kim curseg_alloc_type(sbi, i + CURSEG_HOT_NODE); 910127e670aSJaegeuk Kim } 911b5b82205SChao Yu for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) { 912127e670aSJaegeuk Kim ckpt->cur_data_segno[i] = 913127e670aSJaegeuk Kim cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_DATA)); 914127e670aSJaegeuk Kim ckpt->cur_data_blkoff[i] = 915127e670aSJaegeuk Kim cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_DATA)); 916127e670aSJaegeuk Kim ckpt->alloc_type[i + CURSEG_HOT_DATA] = 917127e670aSJaegeuk Kim curseg_alloc_type(sbi, i + CURSEG_HOT_DATA); 918127e670aSJaegeuk Kim } 919127e670aSJaegeuk Kim 920127e670aSJaegeuk Kim ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi)); 921127e670aSJaegeuk Kim ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi)); 922127e670aSJaegeuk Kim ckpt->next_free_nid = cpu_to_le32(last_nid); 923127e670aSJaegeuk Kim 924127e670aSJaegeuk Kim /* 2 cp + n data seg summary + orphan inode blocks */ 925127e670aSJaegeuk Kim data_sum_blocks = npages_for_summary_flush(sbi); 926b5b82205SChao Yu if (data_sum_blocks < NR_CURSEG_DATA_TYPE) 92725ca923bSJaegeuk Kim set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG); 928127e670aSJaegeuk Kim else 92925ca923bSJaegeuk Kim clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG); 930127e670aSJaegeuk Kim 93167298804SChao Yu orphan_blocks = GET_ORPHAN_BLOCKS(orphan_num); 9321dbe4152SChangman Lee ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks + 9331dbe4152SChangman Lee orphan_blocks); 934127e670aSJaegeuk Kim 93575ab4cb8SJaegeuk Kim if (cpc->reason == CP_UMOUNT) { 93625ca923bSJaegeuk Kim set_ckpt_flags(ckpt, CP_UMOUNT_FLAG); 937b5b82205SChao Yu ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS+ 9381dbe4152SChangman Lee cp_payload_blks + data_sum_blocks + 9391dbe4152SChangman Lee orphan_blocks + NR_CURSEG_NODE_TYPE); 940127e670aSJaegeuk Kim } else { 94125ca923bSJaegeuk Kim clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG); 942b5b82205SChao Yu ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS + 9431dbe4152SChangman Lee cp_payload_blks + data_sum_blocks + 9441dbe4152SChangman Lee orphan_blocks); 945127e670aSJaegeuk Kim } 946127e670aSJaegeuk Kim 94767298804SChao Yu if (orphan_num) 94825ca923bSJaegeuk Kim set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG); 949127e670aSJaegeuk Kim else 95025ca923bSJaegeuk Kim clear_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG); 951127e670aSJaegeuk Kim 9522ae4c673SJaegeuk Kim if (sbi->need_fsck) 9532ae4c673SJaegeuk Kim set_ckpt_flags(ckpt, CP_FSCK_FLAG); 9542ae4c673SJaegeuk Kim 955127e670aSJaegeuk Kim /* update SIT/NAT bitmap */ 956127e670aSJaegeuk Kim get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP)); 957127e670aSJaegeuk Kim get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP)); 958127e670aSJaegeuk Kim 959127e670aSJaegeuk Kim crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset)); 9607e586fa0SJaegeuk Kim *((__le32 *)((unsigned char *)ckpt + 9617e586fa0SJaegeuk Kim le32_to_cpu(ckpt->checksum_offset))) 962127e670aSJaegeuk Kim = cpu_to_le32(crc32); 963127e670aSJaegeuk Kim 964127e670aSJaegeuk Kim start_blk = __start_cp_addr(sbi); 965127e670aSJaegeuk Kim 966127e670aSJaegeuk Kim /* write out checkpoint buffer at block 0 */ 967127e670aSJaegeuk Kim cp_page = grab_meta_page(sbi, start_blk++); 968127e670aSJaegeuk Kim kaddr = page_address(cp_page); 969127e670aSJaegeuk Kim memcpy(kaddr, ckpt, (1 << sbi->log_blocksize)); 970127e670aSJaegeuk Kim set_page_dirty(cp_page); 971127e670aSJaegeuk Kim f2fs_put_page(cp_page, 1); 972127e670aSJaegeuk Kim 9731dbe4152SChangman Lee for (i = 1; i < 1 + cp_payload_blks; i++) { 9741dbe4152SChangman Lee cp_page = grab_meta_page(sbi, start_blk++); 9751dbe4152SChangman Lee kaddr = page_address(cp_page); 9761dbe4152SChangman Lee memcpy(kaddr, (char *)ckpt + i * F2FS_BLKSIZE, 9771dbe4152SChangman Lee (1 << sbi->log_blocksize)); 9781dbe4152SChangman Lee set_page_dirty(cp_page); 9791dbe4152SChangman Lee f2fs_put_page(cp_page, 1); 9801dbe4152SChangman Lee } 9811dbe4152SChangman Lee 98267298804SChao Yu if (orphan_num) { 983127e670aSJaegeuk Kim write_orphan_inodes(sbi, start_blk); 984127e670aSJaegeuk Kim start_blk += orphan_blocks; 985127e670aSJaegeuk Kim } 986127e670aSJaegeuk Kim 987127e670aSJaegeuk Kim write_data_summaries(sbi, start_blk); 988127e670aSJaegeuk Kim start_blk += data_sum_blocks; 98975ab4cb8SJaegeuk Kim if (cpc->reason == CP_UMOUNT) { 990127e670aSJaegeuk Kim write_node_summaries(sbi, start_blk); 991127e670aSJaegeuk Kim start_blk += NR_CURSEG_NODE_TYPE; 992127e670aSJaegeuk Kim } 993127e670aSJaegeuk Kim 994127e670aSJaegeuk Kim /* writeout checkpoint block */ 995127e670aSJaegeuk Kim cp_page = grab_meta_page(sbi, start_blk); 996127e670aSJaegeuk Kim kaddr = page_address(cp_page); 997127e670aSJaegeuk Kim memcpy(kaddr, ckpt, (1 << sbi->log_blocksize)); 998127e670aSJaegeuk Kim set_page_dirty(cp_page); 999127e670aSJaegeuk Kim f2fs_put_page(cp_page, 1); 1000127e670aSJaegeuk Kim 1001127e670aSJaegeuk Kim /* wait for previous submitted node/meta pages writeback */ 1002fb51b5efSChangman Lee wait_on_all_pages_writeback(sbi); 1003127e670aSJaegeuk Kim 1004cf779cabSJaegeuk Kim if (unlikely(f2fs_cp_error(sbi))) 1005cf779cabSJaegeuk Kim return; 1006cf779cabSJaegeuk Kim 10074ef51a8fSJaegeuk Kim filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LONG_MAX); 10089df27d98SGu Zheng filemap_fdatawait_range(META_MAPPING(sbi), 0, LONG_MAX); 1009127e670aSJaegeuk Kim 1010127e670aSJaegeuk Kim /* update user_block_counts */ 1011127e670aSJaegeuk Kim sbi->last_valid_block_count = sbi->total_valid_block_count; 1012127e670aSJaegeuk Kim sbi->alloc_valid_block_count = 0; 1013127e670aSJaegeuk Kim 1014127e670aSJaegeuk Kim /* Here, we only have one bio having CP pack */ 1015127e670aSJaegeuk Kim sync_meta_pages(sbi, META_FLUSH, LONG_MAX); 1016127e670aSJaegeuk Kim 10176a8f8ca5SJaegeuk Kim /* wait for previous submitted meta pages writeback */ 10186a8f8ca5SJaegeuk Kim wait_on_all_pages_writeback(sbi); 10196a8f8ca5SJaegeuk Kim 1020fff04f90SJaegeuk Kim release_dirty_inode(sbi); 1021cf779cabSJaegeuk Kim 1022cf779cabSJaegeuk Kim if (unlikely(f2fs_cp_error(sbi))) 1023cf779cabSJaegeuk Kim return; 1024cf779cabSJaegeuk Kim 1025cf779cabSJaegeuk Kim clear_prefree_segments(sbi); 1026127e670aSJaegeuk Kim F2FS_RESET_SB_DIRT(sbi); 1027127e670aSJaegeuk Kim } 1028127e670aSJaegeuk Kim 10290a8165d7SJaegeuk Kim /* 1030e1c42045Sarter97 * We guarantee that this checkpoint procedure will not fail. 1031127e670aSJaegeuk Kim */ 103275ab4cb8SJaegeuk Kim void write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) 1033127e670aSJaegeuk Kim { 1034127e670aSJaegeuk Kim struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 1035127e670aSJaegeuk Kim unsigned long long ckpt_ver; 1036127e670aSJaegeuk Kim 103775ab4cb8SJaegeuk Kim trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "start block_ops"); 10382af4bd6cSNamjae Jeon 1039127e670aSJaegeuk Kim mutex_lock(&sbi->cp_mutex); 10408501017eSJaegeuk Kim 10414b2fecc8SJaegeuk Kim if (!sbi->s_dirty && cpc->reason != CP_DISCARD) 10428501017eSJaegeuk Kim goto out; 1043cf779cabSJaegeuk Kim if (unlikely(f2fs_cp_error(sbi))) 1044cf779cabSJaegeuk Kim goto out; 1045cf779cabSJaegeuk Kim if (block_operations(sbi)) 1046cf779cabSJaegeuk Kim goto out; 1047127e670aSJaegeuk Kim 104875ab4cb8SJaegeuk Kim trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops"); 10492af4bd6cSNamjae Jeon 1050458e6197SJaegeuk Kim f2fs_submit_merged_bio(sbi, DATA, WRITE); 1051458e6197SJaegeuk Kim f2fs_submit_merged_bio(sbi, NODE, WRITE); 1052458e6197SJaegeuk Kim f2fs_submit_merged_bio(sbi, META, WRITE); 1053127e670aSJaegeuk Kim 1054127e670aSJaegeuk Kim /* 1055127e670aSJaegeuk Kim * update checkpoint pack index 1056127e670aSJaegeuk Kim * Increase the version number so that 1057127e670aSJaegeuk Kim * SIT entries and seg summaries are written at correct place 1058127e670aSJaegeuk Kim */ 1059d71b5564SJaegeuk Kim ckpt_ver = cur_cp_version(ckpt); 1060127e670aSJaegeuk Kim ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver); 1061127e670aSJaegeuk Kim 1062127e670aSJaegeuk Kim /* write cached NAT/SIT entries to NAT/SIT area */ 1063127e670aSJaegeuk Kim flush_nat_entries(sbi); 10644b2fecc8SJaegeuk Kim flush_sit_entries(sbi, cpc); 1065127e670aSJaegeuk Kim 1066127e670aSJaegeuk Kim /* unlock all the fs_lock[] in do_checkpoint() */ 106775ab4cb8SJaegeuk Kim do_checkpoint(sbi, cpc); 1068127e670aSJaegeuk Kim 1069127e670aSJaegeuk Kim unblock_operations(sbi); 1070942e0be6SChangman Lee stat_inc_cp_count(sbi->stat_info); 10718501017eSJaegeuk Kim out: 10728501017eSJaegeuk Kim mutex_unlock(&sbi->cp_mutex); 107375ab4cb8SJaegeuk Kim trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint"); 1074127e670aSJaegeuk Kim } 1075127e670aSJaegeuk Kim 10766451e041SJaegeuk Kim void init_ino_entry_info(struct f2fs_sb_info *sbi) 1077127e670aSJaegeuk Kim { 10786451e041SJaegeuk Kim int i; 10796451e041SJaegeuk Kim 10806451e041SJaegeuk Kim for (i = 0; i < MAX_INO_ENTRY; i++) { 108167298804SChao Yu struct inode_management *im = &sbi->im[i]; 108267298804SChao Yu 108367298804SChao Yu INIT_RADIX_TREE(&im->ino_root, GFP_ATOMIC); 108467298804SChao Yu spin_lock_init(&im->ino_lock); 108567298804SChao Yu INIT_LIST_HEAD(&im->ino_list); 108667298804SChao Yu im->ino_num = 0; 10876451e041SJaegeuk Kim } 10886451e041SJaegeuk Kim 10890d47c1adSGu Zheng /* 10900d47c1adSGu Zheng * considering 512 blocks in a segment 8 blocks are needed for cp 10910d47c1adSGu Zheng * and log segment summaries. Remaining blocks are used to keep 10920d47c1adSGu Zheng * orphan entries with the limitation one reserved segment 10930d47c1adSGu Zheng * for cp pack we can have max 1020*504 orphan entries 10940d47c1adSGu Zheng */ 1095b5b82205SChao Yu sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS - 1096b5b82205SChao Yu NR_CURSEG_TYPE) * F2FS_ORPHANS_PER_BLOCK; 1097127e670aSJaegeuk Kim } 1098127e670aSJaegeuk Kim 10996e6093a8SNamjae Jeon int __init create_checkpoint_caches(void) 1100127e670aSJaegeuk Kim { 11016451e041SJaegeuk Kim ino_entry_slab = f2fs_kmem_cache_create("f2fs_ino_entry", 11026451e041SJaegeuk Kim sizeof(struct ino_entry)); 11036451e041SJaegeuk Kim if (!ino_entry_slab) 1104127e670aSJaegeuk Kim return -ENOMEM; 1105127e670aSJaegeuk Kim inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry", 1106e8512d2eSGu Zheng sizeof(struct dir_inode_entry)); 11076bacf52fSJaegeuk Kim if (!inode_entry_slab) { 11086451e041SJaegeuk Kim kmem_cache_destroy(ino_entry_slab); 1109127e670aSJaegeuk Kim return -ENOMEM; 1110127e670aSJaegeuk Kim } 1111127e670aSJaegeuk Kim return 0; 1112127e670aSJaegeuk Kim } 1113127e670aSJaegeuk Kim 1114127e670aSJaegeuk Kim void destroy_checkpoint_caches(void) 1115127e670aSJaegeuk Kim { 11166451e041SJaegeuk Kim kmem_cache_destroy(ino_entry_slab); 1117127e670aSJaegeuk Kim kmem_cache_destroy(inode_entry_slab); 1118127e670aSJaegeuk Kim } 1119