static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
                          int type, struct victim_sel_policy *p)
{
    struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);

    if (p->alloc_mode == SSR) {
        p->gc_mode = GC_GREEDY;
        p->dirty_segmap = dirty_i->dirty_segmap[type];
        p->ofs_unit = 1;
    } else {
        p->gc_mode = select_gc_type(gc_type);
        p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
        p->ofs_unit = sbi->segs_per_sec;
    }
    p->offset = sbi->last_victim[p->gc_mode];
}
static unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
{
    struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
    unsigned int hint = 0;
    unsigned int secno;

    /*
     * If the gc_type is FG_GC, we can select victim segments
     * selected by background GC before.
     * Those segments guarantee they have small valid blocks.
     */
next:
    secno = find_next_bit(dirty_i->victim_secmap, TOTAL_SECS(sbi), hint++);
    if (secno < TOTAL_SECS(sbi)) {
        if (sec_usage_check(sbi, secno))
            goto next;
        clear_bit(secno, dirty_i->victim_secmap);
        return secno * sbi->segs_per_sec;
    }
    return NULL_SEGNO;
}
static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
			int type, struct victim_sel_policy *p)
{
	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);

	if (p->alloc_mode == SSR) {
		p->gc_mode = GC_GREEDY;
		p->dirty_segmap = dirty_i->dirty_segmap[type];
		p->max_search = dirty_i->nr_dirty[type];
		p->ofs_unit = 1;
	} else {
		p->gc_mode = select_gc_type(sbi->gc_thread, gc_type);
		p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
		p->max_search = dirty_i->nr_dirty[DIRTY];
		p->ofs_unit = sbi->segs_per_sec;
	}

	if (p->max_search > MAX_VICTIM_SEARCH)
		p->max_search = MAX_VICTIM_SEARCH;

	p->offset = sbi->last_victim[p->gc_mode];
}
/*
 * This function is called from two paths.
 * One is garbage collection and the other is SSR segment selection.
 * When it is called during GC, it just gets a victim segment
 * and it does not remove it from dirty seglist.
 * When it is called from SSR segment selection, it finds a segment
 * which has minimum valid blocks and removes it from dirty seglist.
 */
static int get_victim_by_default(struct f2fs_sb_info *sbi,
                                 unsigned int *result, int gc_type, int type, char alloc_mode)
{
    struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
    struct victim_sel_policy p;
    unsigned int secno, max_cost;
    int nsearched = 0;

    p.alloc_mode = alloc_mode;
    select_policy(sbi, gc_type, type, &p);

    p.min_segno = NULL_SEGNO;
    p.min_cost = max_cost = get_max_cost(sbi, &p);

    mutex_lock(&dirty_i->seglist_lock);

    if (p.alloc_mode == LFS && gc_type == FG_GC) {
        p.min_segno = check_bg_victims(sbi);
        if (p.min_segno != NULL_SEGNO)
            goto got_it;
    }

    while (1) {
        unsigned long cost;
        unsigned int segno;

        segno = find_next_bit(p.dirty_segmap,
                              TOTAL_SEGS(sbi), p.offset);
        if (segno >= TOTAL_SEGS(sbi)) {
            if (sbi->last_victim[p.gc_mode]) {
                sbi->last_victim[p.gc_mode] = 0;
                p.offset = 0;
                continue;
            }
            break;
        }
        p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit;
        secno = GET_SECNO(sbi, segno);

        if (sec_usage_check(sbi, secno))
            continue;
        if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
            continue;

        cost = get_gc_cost(sbi, segno, &p);

        if (p.min_cost > cost) {
            p.min_segno = segno;
            p.min_cost = cost;
        }

        if (cost == max_cost)
            continue;

        if (nsearched++ >= MAX_VICTIM_SEARCH) {
            sbi->last_victim[p.gc_mode] = segno;
            break;
        }
    }
    if (p.min_segno != NULL_SEGNO) {
got_it:
        if (p.alloc_mode == LFS) {
            secno = GET_SECNO(sbi, p.min_segno);
            if (gc_type == FG_GC)
                sbi->cur_victim_sec = secno;
            else
                set_bit(secno, dirty_i->victim_secmap);
        }
        *result = (p.min_segno / p.ofs_unit) * p.ofs_unit;

        trace_f2fs_get_victim(sbi->sb, type, gc_type, &p,
                              sbi->cur_victim_sec,
                              prefree_segments(sbi), free_segments(sbi));
    }
    mutex_unlock(&dirty_i->seglist_lock);

    return (p.min_segno == NULL_SEGNO) ? 0 : 1;
}