]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/f2fs/segment.c
Merge branch 'epoll-busypoll'
[mirror_ubuntu-artful-kernel.git] / fs / f2fs / segment.c
index 028db55375a45fe05300b04a3f0e4c5fbbe080bf..29ef7088c5582a480b6a1f7965fbbcca4f07e24e 100644 (file)
@@ -352,8 +352,10 @@ int commit_inmem_pages(struct inode *inode)
 void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
 {
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-       if (time_to_inject(sbi, FAULT_CHECKPOINT))
+       if (time_to_inject(sbi, FAULT_CHECKPOINT)) {
+               f2fs_show_injection_info(FAULT_CHECKPOINT);
                f2fs_stop_checkpoint(sbi, false);
+       }
 #endif
 
        if (!need)
@@ -386,7 +388,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
        if (!available_free_memory(sbi, FREE_NIDS))
                try_to_free_nids(sbi, MAX_FREE_NIDS);
        else
-               build_free_nids(sbi, false);
+               build_free_nids(sbi, false, false);
 
        if (!is_idle(sbi))
                return;
@@ -676,8 +678,12 @@ void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
        struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
        struct list_head *wait_list = &(dcc->discard_cmd_list);
        struct discard_cmd *dc, *tmp;
+       struct blk_plug plug;
 
        mutex_lock(&dcc->cmd_lock);
+
+       blk_start_plug(&plug);
+
        list_for_each_entry_safe(dc, tmp, wait_list, list) {
 
                if (blkaddr == NULL_ADDR) {
@@ -686,9 +692,6 @@ void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
                                submit_bio(dc->bio);
                                atomic_inc(&dcc->submit_discard);
                        }
-                       wait_for_completion_io(&dc->wait);
-
-                       __remove_discard_cmd(sbi, dc);
                        continue;
                }
 
@@ -699,6 +702,15 @@ void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
                                __remove_discard_cmd(sbi, dc);
                }
        }
+       blk_finish_plug(&plug);
+
+       /* this comes from f2fs_put_super */
+       if (blkaddr == NULL_ADDR) {
+               list_for_each_entry_safe(dc, tmp, wait_list, list) {
+                       wait_for_completion_io(&dc->wait);
+                       __remove_discard_cmd(sbi, dc);
+               }
+       }
        mutex_unlock(&dcc->cmd_lock);
 }
 
@@ -783,24 +795,13 @@ static int __f2fs_issue_discard_async(struct f2fs_sb_info *sbi,
 static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,
                struct block_device *bdev, block_t blkstart, block_t blklen)
 {
-       sector_t nr_sects = SECTOR_FROM_BLOCK(blklen);
-       sector_t sector;
+       sector_t sector, nr_sects;
        int devi = 0;
 
        if (sbi->s_ndevs) {
                devi = f2fs_target_device_index(sbi, blkstart);
                blkstart -= FDEV(devi).start_blk;
        }
-       sector = SECTOR_FROM_BLOCK(blkstart);
-
-       if (sector & (bdev_zone_sectors(bdev) - 1) ||
-           nr_sects != bdev_zone_sectors(bdev)) {
-               f2fs_msg(sbi->sb, KERN_INFO,
-                       "(%d) %s: Unaligned discard attempted (block %x + %x)",
-                       devi, sbi->s_ndevs ? FDEV(devi).path: "",
-                       blkstart, blklen);
-               return -EIO;
-       }
 
        /*
         * We need to know the type of the zone: for conventional zones,
@@ -815,6 +816,17 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,
                return __f2fs_issue_discard_async(sbi, bdev, blkstart, blklen);
        case BLK_ZONE_TYPE_SEQWRITE_REQ:
        case BLK_ZONE_TYPE_SEQWRITE_PREF:
+               sector = SECTOR_FROM_BLOCK(blkstart);
+               nr_sects = SECTOR_FROM_BLOCK(blklen);
+
+               if (sector & (bdev_zone_sectors(bdev) - 1) ||
+                               nr_sects != bdev_zone_sectors(bdev)) {
+                       f2fs_msg(sbi->sb, KERN_INFO,
+                               "(%d) %s: Unaligned discard attempted (block %x + %x)",
+                               devi, sbi->s_ndevs ? FDEV(devi).path: "",
+                               blkstart, blklen);
+                       return -EIO;
+               }
                trace_f2fs_issue_reset_zone(bdev, blkstart);
                return blkdev_reset_zones(bdev, sector,
                                          nr_sects, GFP_NOFS);
@@ -1024,6 +1036,8 @@ next:
                start = start_segno + sbi->segs_per_sec;
                if (start < end)
                        goto next;
+               else
+                       end = start - 1;
        }
        mutex_unlock(&dirty_i->seglist_lock);
 
@@ -1149,6 +1163,12 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
                if (f2fs_discard_en(sbi) &&
                        !f2fs_test_and_set_bit(offset, se->discard_map))
                        sbi->discard_blks--;
+
+               /* don't overwrite by SSR to keep node chain */
+               if (se->type == CURSEG_WARM_NODE) {
+                       if (!f2fs_test_and_set_bit(offset, se->ckpt_valid_map))
+                               se->ckpt_valid_blocks++;
+               }
        } else {
                if (!f2fs_test_and_clear_bit(offset, se->cur_valid_map)) {
 #ifdef CONFIG_F2FS_CHECK_FS
@@ -1529,7 +1549,8 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type)
 {
        struct curseg_info *curseg = CURSEG_I(sbi, type);
        const struct victim_selection *v_ops = DIRTY_I(sbi)->v_ops;
-       int i, n;
+       int i, cnt;
+       bool reversed = false;
 
        /* need_SSR() already forces to do this */
        if (v_ops->get_victim(sbi, &(curseg)->next_segno, BG_GC, type, SSR))
@@ -1537,14 +1558,24 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type)
 
        /* For node segments, let's do SSR more intensively */
        if (IS_NODESEG(type)) {
-               i = CURSEG_HOT_NODE;
-               n = CURSEG_COLD_NODE;
+               if (type >= CURSEG_WARM_NODE) {
+                       reversed = true;
+                       i = CURSEG_COLD_NODE;
+               } else {
+                       i = CURSEG_HOT_NODE;
+               }
+               cnt = NR_CURSEG_NODE_TYPE;
        } else {
-               i = CURSEG_HOT_DATA;
-               n = CURSEG_COLD_DATA;
+               if (type >= CURSEG_WARM_DATA) {
+                       reversed = true;
+                       i = CURSEG_COLD_DATA;
+               } else {
+                       i = CURSEG_HOT_DATA;
+               }
+               cnt = NR_CURSEG_DATA_TYPE;
        }
 
-       for (; i <= n; i++) {
+       for (; cnt-- > 0; reversed ? i-- : i++) {
                if (i == type)
                        continue;
                if (v_ops->get_victim(sbi, &(curseg)->next_segno,