]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/f2fs/segment.c
f2fs: add an option to avoid unnecessary BUG_ONs
[mirror_ubuntu-artful-kernel.git] / fs / f2fs / segment.c
index 09af9c7b0f52673fff92f00be5a37a6030b72668..c7161defff901f6b0670a3a8615f0dc31888a150 100644 (file)
@@ -36,6 +36,14 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi)
        }
 }
 
+void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
+{
+       /* check the # of cached NAT entries and prefree segments */
+       if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK) ||
+                               excess_prefree_segs(sbi))
+               f2fs_sync_fs(sbi->sb, true);
+}
+
 static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
                enum dirty_type dirty_type)
 {
@@ -50,20 +58,10 @@ static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
 
        if (dirty_type == DIRTY) {
                struct seg_entry *sentry = get_seg_entry(sbi, segno);
-               enum dirty_type t = DIRTY_HOT_DATA;
+               enum dirty_type t = sentry->type;
 
-               dirty_type = sentry->type;
-
-               if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
-                       dirty_i->nr_dirty[dirty_type]++;
-
-               /* Only one bitmap should be set */
-               for (; t <= DIRTY_COLD_NODE; t++) {
-                       if (t == dirty_type)
-                               continue;
-                       if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t]))
-                               dirty_i->nr_dirty[t]--;
-               }
+               if (!test_and_set_bit(segno, dirty_i->dirty_segmap[t]))
+                       dirty_i->nr_dirty[t]++;
        }
 }
 
@@ -76,12 +74,11 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
                dirty_i->nr_dirty[dirty_type]--;
 
        if (dirty_type == DIRTY) {
-               enum dirty_type t = DIRTY_HOT_DATA;
+               struct seg_entry *sentry = get_seg_entry(sbi, segno);
+               enum dirty_type t = sentry->type;
 
-               /* clear all the bitmaps */
-               for (; t <= DIRTY_COLD_NODE; t++)
-                       if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t]))
-                               dirty_i->nr_dirty[t]--;
+               if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t]))
+                       dirty_i->nr_dirty[t]--;
 
                if (get_valid_blocks(sbi, segno, sbi->segs_per_sec) == 0)
                        clear_bit(GET_SECNO(sbi, segno),
@@ -195,7 +192,7 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
        new_vblocks = se->valid_blocks + del;
        offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & (sbi->blocks_per_seg - 1);
 
-       BUG_ON((new_vblocks >> (sizeof(unsigned short) << 3) ||
+       f2fs_bug_on((new_vblocks >> (sizeof(unsigned short) << 3) ||
                                (new_vblocks > sbi->blocks_per_seg)));
 
        se->valid_blocks = new_vblocks;
@@ -235,7 +232,7 @@ void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
        unsigned int segno = GET_SEGNO(sbi, addr);
        struct sit_info *sit_i = SIT_I(sbi);
 
-       BUG_ON(addr == NULL_ADDR);
+       f2fs_bug_on(addr == NULL_ADDR);
        if (addr == NEW_ADDR)
                return;
 
@@ -350,7 +347,7 @@ find_other_zone:
                if (dir == ALLOC_RIGHT) {
                        secno = find_next_zero_bit(free_i->free_secmap,
                                                        TOTAL_SECS(sbi), 0);
-                       BUG_ON(secno >= TOTAL_SECS(sbi));
+                       f2fs_bug_on(secno >= TOTAL_SECS(sbi));
                } else {
                        go_left = 1;
                        left_start = hint - 1;
@@ -366,7 +363,7 @@ find_other_zone:
                }
                left_start = find_next_zero_bit(free_i->free_secmap,
                                                        TOTAL_SECS(sbi), 0);
-               BUG_ON(left_start >= TOTAL_SECS(sbi));
+               f2fs_bug_on(left_start >= TOTAL_SECS(sbi));
                break;
        }
        secno = left_start;
@@ -405,7 +402,7 @@ skip_left:
        }
 got_it:
        /* set it as dirty segment in free segmap */
-       BUG_ON(test_bit(segno, free_i->free_segmap));
+       f2fs_bug_on(test_bit(segno, free_i->free_segmap));
        __set_inuse(sbi, segno);
        *newseg = segno;
        write_unlock(&free_i->segmap_lock);
@@ -550,9 +547,8 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi,
                change_curseg(sbi, type, true);
        else
                new_curseg(sbi, type, false);
-#ifdef CONFIG_F2FS_STAT_FS
-       sbi->segment_count[curseg->alloc_type]++;
-#endif
+
+       stat_inc_seg_type(sbi, curseg);
 }
 
 void allocate_new_segments(struct f2fs_sb_info *sbi)
@@ -597,6 +593,10 @@ static void f2fs_end_io_write(struct bio *bio, int err)
 
        if (p->is_sync)
                complete(p->wait);
+
+       if (!get_pages(p->sbi, F2FS_WRITEBACK) && p->sbi->cp_task)
+               wake_up_process(p->sbi->cp_task);
+
        kfree(p);
        bio_put(bio);
 }
@@ -657,6 +657,7 @@ static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page,
                                block_t blk_addr, enum page_type type)
 {
        struct block_device *bdev = sbi->sb->s_bdev;
+       int bio_blocks;
 
        verify_block_addr(sbi, blk_addr);
 
@@ -676,7 +677,8 @@ retry:
                        goto retry;
                }
 
-               sbi->bio[type] = f2fs_bio_alloc(bdev, max_hw_blocks(sbi));
+               bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
+               sbi->bio[type] = f2fs_bio_alloc(bdev, bio_blocks);
                sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
                sbi->bio[type]->bi_private = priv;
                /*
@@ -771,7 +773,7 @@ static int __get_segment_type(struct page *page, enum page_type p_type)
                return __get_segment_type_4(page, p_type);
        }
        /* NR_CURSEG_TYPE(6) logs by default */
-       BUG_ON(sbi->active_logs != NR_CURSEG_TYPE);
+       f2fs_bug_on(sbi->active_logs != NR_CURSEG_TYPE);
        return __get_segment_type_6(page, p_type);
 }
 
@@ -801,9 +803,8 @@ static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
 
        mutex_lock(&sit_i->sentry_lock);
        __refresh_next_blkoff(sbi, curseg);
-#ifdef CONFIG_F2FS_STAT_FS
-       sbi->block_count[curseg->alloc_type]++;
-#endif
+
+       stat_inc_block_count(sbi, curseg);
 
        /*
         * SIT information should be updated before segment allocation,
@@ -849,7 +850,7 @@ void write_data_page(struct inode *inode, struct page *page,
        struct f2fs_summary sum;
        struct node_info ni;
 
-       BUG_ON(old_blkaddr == NULL_ADDR);
+       f2fs_bug_on(old_blkaddr == NULL_ADDR);
        get_node_info(sbi, dn->nid, &ni);
        set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
 
@@ -1122,8 +1123,6 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
                                                SUM_JOURNAL_SIZE);
        written_size += SUM_JOURNAL_SIZE;
 
-       set_page_dirty(page);
-
        /* Step 3: write summary entries */
        for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
                unsigned short blkoff;
@@ -1142,18 +1141,20 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
                        summary = (struct f2fs_summary *)(kaddr + written_size);
                        *summary = seg_i->sum_blk->entries[j];
                        written_size += SUMMARY_SIZE;
-                       set_page_dirty(page);
 
                        if (written_size + SUMMARY_SIZE <= PAGE_CACHE_SIZE -
                                                        SUM_FOOTER_SIZE)
                                continue;
 
+                       set_page_dirty(page);
                        f2fs_put_page(page, 1);
                        page = NULL;
                }
        }
-       if (page)
+       if (page) {
+               set_page_dirty(page);
                f2fs_put_page(page, 1);
+       }
 }
 
 static void write_normal_summaries(struct f2fs_sb_info *sbi,
@@ -1239,7 +1240,7 @@ static struct page *get_next_sit_page(struct f2fs_sb_info *sbi,
        /* get current sit block page without lock */
        src_page = get_meta_page(sbi, src_off);
        dst_page = grab_meta_page(sbi, dst_off);
-       BUG_ON(PageDirty(src_page));
+       f2fs_bug_on(PageDirty(src_page));
 
        src_addr = page_address(src_page);
        dst_addr = page_address(dst_page);
@@ -1271,9 +1272,9 @@ static bool flush_sits_in_journal(struct f2fs_sb_info *sbi)
                        __mark_sit_entry_dirty(sbi, segno);
                }
                update_sits_in_cursum(sum, -sits_in_cursum(sum));
-               return 1;
+               return true;
        }
-       return 0;
+       return false;
 }
 
 /*
@@ -1637,6 +1638,7 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
        sm_info->ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
        sm_info->main_segments = le32_to_cpu(raw_super->segment_count_main);
        sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
+       sm_info->rec_prefree_segments = DEF_RECLAIM_PREFREE_SEGMENTS;
 
        err = build_sit_info(sbi);
        if (err)