diff options
Diffstat (limited to 'fs/f2fs/segment.c')
-rw-r--r-- | fs/f2fs/segment.c | 122 |
1 files changed, 83 insertions, 39 deletions
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 923cb76fdc46..42607a679923 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -178,17 +178,47 @@ void register_inmem_page(struct inode *inode, struct page *page) | |||
178 | { | 178 | { |
179 | struct f2fs_inode_info *fi = F2FS_I(inode); | 179 | struct f2fs_inode_info *fi = F2FS_I(inode); |
180 | struct inmem_pages *new; | 180 | struct inmem_pages *new; |
181 | int err; | ||
182 | |||
183 | SetPagePrivate(page); | ||
181 | 184 | ||
182 | new = f2fs_kmem_cache_alloc(inmem_entry_slab, GFP_NOFS); | 185 | new = f2fs_kmem_cache_alloc(inmem_entry_slab, GFP_NOFS); |
183 | 186 | ||
184 | /* add atomic page indices to the list */ | 187 | /* add atomic page indices to the list */ |
185 | new->page = page; | 188 | new->page = page; |
186 | INIT_LIST_HEAD(&new->list); | 189 | INIT_LIST_HEAD(&new->list); |
187 | 190 | retry: | |
188 | /* increase reference count with clean state */ | 191 | /* increase reference count with clean state */ |
189 | mutex_lock(&fi->inmem_lock); | 192 | mutex_lock(&fi->inmem_lock); |
193 | err = radix_tree_insert(&fi->inmem_root, page->index, new); | ||
194 | if (err == -EEXIST) { | ||
195 | mutex_unlock(&fi->inmem_lock); | ||
196 | kmem_cache_free(inmem_entry_slab, new); | ||
197 | return; | ||
198 | } else if (err) { | ||
199 | mutex_unlock(&fi->inmem_lock); | ||
200 | goto retry; | ||
201 | } | ||
190 | get_page(page); | 202 | get_page(page); |
191 | list_add_tail(&new->list, &fi->inmem_pages); | 203 | list_add_tail(&new->list, &fi->inmem_pages); |
204 | inc_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES); | ||
205 | mutex_unlock(&fi->inmem_lock); | ||
206 | } | ||
207 | |||
208 | void invalidate_inmem_page(struct inode *inode, struct page *page) | ||
209 | { | ||
210 | struct f2fs_inode_info *fi = F2FS_I(inode); | ||
211 | struct inmem_pages *cur; | ||
212 | |||
213 | mutex_lock(&fi->inmem_lock); | ||
214 | cur = radix_tree_lookup(&fi->inmem_root, page->index); | ||
215 | if (cur) { | ||
216 | radix_tree_delete(&fi->inmem_root, cur->page->index); | ||
217 | f2fs_put_page(cur->page, 0); | ||
218 | list_del(&cur->list); | ||
219 | kmem_cache_free(inmem_entry_slab, cur); | ||
220 | dec_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES); | ||
221 | } | ||
192 | mutex_unlock(&fi->inmem_lock); | 222 | mutex_unlock(&fi->inmem_lock); |
193 | } | 223 | } |
194 | 224 | ||
@@ -203,7 +233,16 @@ void commit_inmem_pages(struct inode *inode, bool abort) | |||
203 | .rw = WRITE_SYNC, | 233 | .rw = WRITE_SYNC, |
204 | }; | 234 | }; |
205 | 235 | ||
206 | f2fs_balance_fs(sbi); | 236 | /* |
237 | * The abort is true only when f2fs_evict_inode is called. | ||
238 | * Basically, the f2fs_evict_inode doesn't produce any data writes, so | ||
239 | * that we don't need to call f2fs_balance_fs. | ||
240 | * Otherwise, f2fs_gc in f2fs_balance_fs can wait forever until this | ||
241 | * inode becomes free by iget_locked in f2fs_iget. | ||
242 | */ | ||
243 | if (!abort) | ||
244 | f2fs_balance_fs(sbi); | ||
245 | |||
207 | f2fs_lock_op(sbi); | 246 | f2fs_lock_op(sbi); |
208 | 247 | ||
209 | mutex_lock(&fi->inmem_lock); | 248 | mutex_lock(&fi->inmem_lock); |
@@ -216,9 +255,11 @@ void commit_inmem_pages(struct inode *inode, bool abort) | |||
216 | do_write_data_page(cur->page, &fio); | 255 | do_write_data_page(cur->page, &fio); |
217 | submit_bio = true; | 256 | submit_bio = true; |
218 | } | 257 | } |
258 | radix_tree_delete(&fi->inmem_root, cur->page->index); | ||
219 | f2fs_put_page(cur->page, 1); | 259 | f2fs_put_page(cur->page, 1); |
220 | list_del(&cur->list); | 260 | list_del(&cur->list); |
221 | kmem_cache_free(inmem_entry_slab, cur); | 261 | kmem_cache_free(inmem_entry_slab, cur); |
262 | dec_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES); | ||
222 | } | 263 | } |
223 | if (submit_bio) | 264 | if (submit_bio) |
224 | f2fs_submit_merged_bio(sbi, DATA, WRITE); | 265 | f2fs_submit_merged_bio(sbi, DATA, WRITE); |
@@ -248,7 +289,8 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi) | |||
248 | { | 289 | { |
249 | /* check the # of cached NAT entries and prefree segments */ | 290 | /* check the # of cached NAT entries and prefree segments */ |
250 | if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK) || | 291 | if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK) || |
251 | excess_prefree_segs(sbi)) | 292 | excess_prefree_segs(sbi) || |
293 | available_free_memory(sbi, INO_ENTRIES)) | ||
252 | f2fs_sync_fs(sbi->sb, true); | 294 | f2fs_sync_fs(sbi->sb, true); |
253 | } | 295 | } |
254 | 296 | ||
@@ -441,10 +483,33 @@ void discard_next_dnode(struct f2fs_sb_info *sbi, block_t blkaddr) | |||
441 | } | 483 | } |
442 | } | 484 | } |
443 | 485 | ||
444 | static void add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc) | 486 | static void __add_discard_entry(struct f2fs_sb_info *sbi, |
487 | struct cp_control *cpc, unsigned int start, unsigned int end) | ||
445 | { | 488 | { |
446 | struct list_head *head = &SM_I(sbi)->discard_list; | 489 | struct list_head *head = &SM_I(sbi)->discard_list; |
447 | struct discard_entry *new; | 490 | struct discard_entry *new, *last; |
491 | |||
492 | if (!list_empty(head)) { | ||
493 | last = list_last_entry(head, struct discard_entry, list); | ||
494 | if (START_BLOCK(sbi, cpc->trim_start) + start == | ||
495 | last->blkaddr + last->len) { | ||
496 | last->len += end - start; | ||
497 | goto done; | ||
498 | } | ||
499 | } | ||
500 | |||
501 | new = f2fs_kmem_cache_alloc(discard_entry_slab, GFP_NOFS); | ||
502 | INIT_LIST_HEAD(&new->list); | ||
503 | new->blkaddr = START_BLOCK(sbi, cpc->trim_start) + start; | ||
504 | new->len = end - start; | ||
505 | list_add_tail(&new->list, head); | ||
506 | done: | ||
507 | SM_I(sbi)->nr_discards += end - start; | ||
508 | cpc->trimmed += end - start; | ||
509 | } | ||
510 | |||
511 | static void add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc) | ||
512 | { | ||
448 | int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long); | 513 | int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long); |
449 | int max_blocks = sbi->blocks_per_seg; | 514 | int max_blocks = sbi->blocks_per_seg; |
450 | struct seg_entry *se = get_seg_entry(sbi, cpc->trim_start); | 515 | struct seg_entry *se = get_seg_entry(sbi, cpc->trim_start); |
@@ -473,13 +538,7 @@ static void add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
473 | } | 538 | } |
474 | mutex_unlock(&dirty_i->seglist_lock); | 539 | mutex_unlock(&dirty_i->seglist_lock); |
475 | 540 | ||
476 | new = f2fs_kmem_cache_alloc(discard_entry_slab, GFP_NOFS); | 541 | __add_discard_entry(sbi, cpc, 0, sbi->blocks_per_seg); |
477 | INIT_LIST_HEAD(&new->list); | ||
478 | new->blkaddr = START_BLOCK(sbi, cpc->trim_start); | ||
479 | new->len = sbi->blocks_per_seg; | ||
480 | list_add_tail(&new->list, head); | ||
481 | SM_I(sbi)->nr_discards += sbi->blocks_per_seg; | ||
482 | cpc->trimmed += sbi->blocks_per_seg; | ||
483 | return; | 542 | return; |
484 | } | 543 | } |
485 | 544 | ||
@@ -489,7 +548,7 @@ static void add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
489 | 548 | ||
490 | /* SIT_VBLOCK_MAP_SIZE should be multiple of sizeof(unsigned long) */ | 549 | /* SIT_VBLOCK_MAP_SIZE should be multiple of sizeof(unsigned long) */ |
491 | for (i = 0; i < entries; i++) | 550 | for (i = 0; i < entries; i++) |
492 | dmap[i] = (cur_map[i] ^ ckpt_map[i]) & ckpt_map[i]; | 551 | dmap[i] = ~(cur_map[i] | ckpt_map[i]); |
493 | 552 | ||
494 | while (force || SM_I(sbi)->nr_discards <= SM_I(sbi)->max_discards) { | 553 | while (force || SM_I(sbi)->nr_discards <= SM_I(sbi)->max_discards) { |
495 | start = __find_rev_next_bit(dmap, max_blocks, end + 1); | 554 | start = __find_rev_next_bit(dmap, max_blocks, end + 1); |
@@ -501,14 +560,7 @@ static void add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
501 | if (end - start < cpc->trim_minlen) | 560 | if (end - start < cpc->trim_minlen) |
502 | continue; | 561 | continue; |
503 | 562 | ||
504 | new = f2fs_kmem_cache_alloc(discard_entry_slab, GFP_NOFS); | 563 | __add_discard_entry(sbi, cpc, start, end); |
505 | INIT_LIST_HEAD(&new->list); | ||
506 | new->blkaddr = START_BLOCK(sbi, cpc->trim_start) + start; | ||
507 | new->len = end - start; | ||
508 | cpc->trimmed += end - start; | ||
509 | |||
510 | list_add_tail(&new->list, head); | ||
511 | SM_I(sbi)->nr_discards += end - start; | ||
512 | } | 564 | } |
513 | } | 565 | } |
514 | 566 | ||
@@ -620,10 +672,10 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) | |||
620 | 672 | ||
621 | /* Update valid block bitmap */ | 673 | /* Update valid block bitmap */ |
622 | if (del > 0) { | 674 | if (del > 0) { |
623 | if (f2fs_set_bit(offset, se->cur_valid_map)) | 675 | if (f2fs_test_and_set_bit(offset, se->cur_valid_map)) |
624 | f2fs_bug_on(sbi, 1); | 676 | f2fs_bug_on(sbi, 1); |
625 | } else { | 677 | } else { |
626 | if (!f2fs_clear_bit(offset, se->cur_valid_map)) | 678 | if (!f2fs_test_and_clear_bit(offset, se->cur_valid_map)) |
627 | f2fs_bug_on(sbi, 1); | 679 | f2fs_bug_on(sbi, 1); |
628 | } | 680 | } |
629 | if (!f2fs_test_bit(offset, se->ckpt_valid_map)) | 681 | if (!f2fs_test_bit(offset, se->ckpt_valid_map)) |
@@ -1004,6 +1056,7 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) | |||
1004 | range->len < sbi->blocksize) | 1056 | range->len < sbi->blocksize) |
1005 | return -EINVAL; | 1057 | return -EINVAL; |
1006 | 1058 | ||
1059 | cpc.trimmed = 0; | ||
1007 | if (end <= MAIN_BLKADDR(sbi)) | 1060 | if (end <= MAIN_BLKADDR(sbi)) |
1008 | goto out; | 1061 | goto out; |
1009 | 1062 | ||
@@ -1015,10 +1068,11 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) | |||
1015 | cpc.trim_start = start_segno; | 1068 | cpc.trim_start = start_segno; |
1016 | cpc.trim_end = end_segno; | 1069 | cpc.trim_end = end_segno; |
1017 | cpc.trim_minlen = range->minlen >> sbi->log_blocksize; | 1070 | cpc.trim_minlen = range->minlen >> sbi->log_blocksize; |
1018 | cpc.trimmed = 0; | ||
1019 | 1071 | ||
1020 | /* do checkpoint to issue discard commands safely */ | 1072 | /* do checkpoint to issue discard commands safely */ |
1073 | mutex_lock(&sbi->gc_mutex); | ||
1021 | write_checkpoint(sbi, &cpc); | 1074 | write_checkpoint(sbi, &cpc); |
1075 | mutex_unlock(&sbi->gc_mutex); | ||
1022 | out: | 1076 | out: |
1023 | range->len = cpc.trimmed << sbi->log_blocksize; | 1077 | range->len = cpc.trimmed << sbi->log_blocksize; |
1024 | return 0; | 1078 | return 0; |
@@ -1050,8 +1104,8 @@ static int __get_segment_type_4(struct page *page, enum page_type p_type) | |||
1050 | else | 1104 | else |
1051 | return CURSEG_COLD_DATA; | 1105 | return CURSEG_COLD_DATA; |
1052 | } else { | 1106 | } else { |
1053 | if (IS_DNODE(page) && !is_cold_node(page)) | 1107 | if (IS_DNODE(page) && is_cold_node(page)) |
1054 | return CURSEG_HOT_NODE; | 1108 | return CURSEG_WARM_NODE; |
1055 | else | 1109 | else |
1056 | return CURSEG_COLD_NODE; | 1110 | return CURSEG_COLD_NODE; |
1057 | } | 1111 | } |
@@ -1524,17 +1578,7 @@ int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type, | |||
1524 | static struct page *get_current_sit_page(struct f2fs_sb_info *sbi, | 1578 | static struct page *get_current_sit_page(struct f2fs_sb_info *sbi, |
1525 | unsigned int segno) | 1579 | unsigned int segno) |
1526 | { | 1580 | { |
1527 | struct sit_info *sit_i = SIT_I(sbi); | 1581 | return get_meta_page(sbi, current_sit_addr(sbi, segno)); |
1528 | unsigned int offset = SIT_BLOCK_OFFSET(segno); | ||
1529 | block_t blk_addr = sit_i->sit_base_addr + offset; | ||
1530 | |||
1531 | check_seg_range(sbi, segno); | ||
1532 | |||
1533 | /* calculate sit block address */ | ||
1534 | if (f2fs_test_bit(offset, sit_i->sit_bitmap)) | ||
1535 | blk_addr += sit_i->sit_blocks; | ||
1536 | |||
1537 | return get_meta_page(sbi, blk_addr); | ||
1538 | } | 1582 | } |
1539 | 1583 | ||
1540 | static struct page *get_next_sit_page(struct f2fs_sb_info *sbi, | 1584 | static struct page *get_next_sit_page(struct f2fs_sb_info *sbi, |
@@ -1687,7 +1731,7 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
1687 | * #2, flush sit entries to sit page. | 1731 | * #2, flush sit entries to sit page. |
1688 | */ | 1732 | */ |
1689 | list_for_each_entry_safe(ses, tmp, head, set_list) { | 1733 | list_for_each_entry_safe(ses, tmp, head, set_list) { |
1690 | struct page *page; | 1734 | struct page *page = NULL; |
1691 | struct f2fs_sit_block *raw_sit = NULL; | 1735 | struct f2fs_sit_block *raw_sit = NULL; |
1692 | unsigned int start_segno = ses->start_segno; | 1736 | unsigned int start_segno = ses->start_segno; |
1693 | unsigned int end = min(start_segno + SIT_ENTRY_PER_BLOCK, | 1737 | unsigned int end = min(start_segno + SIT_ENTRY_PER_BLOCK, |
@@ -2200,7 +2244,7 @@ int __init create_segment_manager_caches(void) | |||
2200 | goto fail; | 2244 | goto fail; |
2201 | 2245 | ||
2202 | sit_entry_set_slab = f2fs_kmem_cache_create("sit_entry_set", | 2246 | sit_entry_set_slab = f2fs_kmem_cache_create("sit_entry_set", |
2203 | sizeof(struct nat_entry_set)); | 2247 | sizeof(struct sit_entry_set)); |
2204 | if (!sit_entry_set_slab) | 2248 | if (!sit_entry_set_slab) |
2205 | goto destory_discard_entry; | 2249 | goto destory_discard_entry; |
2206 | 2250 | ||