|
@@ -245,6 +245,18 @@ static inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi,
|
|
|
return get_cb_cost(sbi, segno);
|
|
|
}
|
|
|
|
|
|
+static unsigned int count_bits(const unsigned long *addr,
|
|
|
+ unsigned int offset, unsigned int len)
|
|
|
+{
|
|
|
+ unsigned int end = offset + len, sum = 0;
|
|
|
+
|
|
|
+ while (offset < end) {
|
|
|
+ if (test_bit(offset++, addr))
|
|
|
+ ++sum;
|
|
|
+ }
|
|
|
+ return sum;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* This function is called from two paths.
|
|
|
* One is garbage collection and the other is SSR segment selection.
|
|
@@ -260,7 +272,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
|
|
|
struct victim_sel_policy p;
|
|
|
unsigned int secno, max_cost;
|
|
|
unsigned int last_segment = MAIN_SEGS(sbi);
|
|
|
- int nsearched = 0;
|
|
|
+ unsigned int nsearched = 0;
|
|
|
|
|
|
mutex_lock(&dirty_i->seglist_lock);
|
|
|
|
|
@@ -295,26 +307,31 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
|
|
|
}
|
|
|
|
|
|
p.offset = segno + p.ofs_unit;
|
|
|
- if (p.ofs_unit > 1)
|
|
|
+ if (p.ofs_unit > 1) {
|
|
|
p.offset -= segno % p.ofs_unit;
|
|
|
+ nsearched += count_bits(p.dirty_segmap,
|
|
|
+ p.offset - p.ofs_unit,
|
|
|
+ p.ofs_unit);
|
|
|
+ } else {
|
|
|
+ nsearched++;
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
secno = GET_SECNO(sbi, segno);
|
|
|
|
|
|
if (sec_usage_check(sbi, secno))
|
|
|
- continue;
|
|
|
+ goto next;
|
|
|
if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
|
|
|
- continue;
|
|
|
+ goto next;
|
|
|
|
|
|
cost = get_gc_cost(sbi, segno, &p);
|
|
|
|
|
|
if (p.min_cost > cost) {
|
|
|
p.min_segno = segno;
|
|
|
p.min_cost = cost;
|
|
|
- } else if (unlikely(cost == max_cost)) {
|
|
|
- continue;
|
|
|
}
|
|
|
-
|
|
|
- if (nsearched++ >= p.max_search) {
|
|
|
+next:
|
|
|
+ if (nsearched >= p.max_search) {
|
|
|
sbi->last_victim[p.gc_mode] = segno;
|
|
|
break;
|
|
|
}
|