| .. | .. |
|---|
| 14 | 14 | #define DEF_GC_THREAD_MIN_SLEEP_TIME 30000 /* milliseconds */ |
|---|
| 15 | 15 | #define DEF_GC_THREAD_MAX_SLEEP_TIME 60000 |
|---|
| 16 | 16 | #define DEF_GC_THREAD_NOGC_SLEEP_TIME 300000 /* wait 5 min */ |
|---|
| 17 | + |
|---|
| 18 | +/* choose candidates from sections which has age of more than 7 days */ |
|---|
| 19 | +#define DEF_GC_THREAD_AGE_THRESHOLD (60 * 60 * 24 * 7) |
|---|
| 20 | +#define DEF_GC_THREAD_CANDIDATE_RATIO 20 /* select 20% oldest sections as candidates */ |
|---|
| 21 | +#define DEF_GC_THREAD_MAX_CANDIDATE_COUNT 10 /* select at most 10 sections as candidates */ |
|---|
| 22 | +#define DEF_GC_THREAD_AGE_WEIGHT 60 /* age weight */ |
|---|
| 23 | +#define DEFAULT_ACCURACY_CLASS 10000 /* accuracy class */ |
|---|
| 24 | + |
|---|
| 17 | 25 | #define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */ |
|---|
| 18 | 26 | #define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */ |
|---|
| 19 | 27 | |
|---|
| .. | .. |
|---|
| 34 | 42 | |
|---|
| 35 | 43 | /* for changing gc mode */ |
|---|
| 36 | 44 | unsigned int gc_wake; |
|---|
| 45 | + |
|---|
| 46 | + /* for GC_MERGE mount option */ |
|---|
| 47 | + wait_queue_head_t fggc_wq; /* |
|---|
| 48 | + * caller of f2fs_balance_fs() |
|---|
| 49 | + * will wait on this wait queue. |
|---|
| 50 | + */ |
|---|
| 37 | 51 | }; |
|---|
| 38 | 52 | |
|---|
| 39 | 53 | struct gc_inode_list { |
|---|
| .. | .. |
|---|
| 41 | 55 | struct radix_tree_root iroot; |
|---|
| 42 | 56 | }; |
|---|
| 43 | 57 | |
|---|
| 58 | +struct victim_info { |
|---|
| 59 | + unsigned long long mtime; /* mtime of section */ |
|---|
| 60 | + unsigned int segno; /* section No. */ |
|---|
| 61 | +}; |
|---|
| 62 | + |
|---|
| 63 | +struct victim_entry { |
|---|
| 64 | + struct rb_node rb_node; /* rb node located in rb-tree */ |
|---|
| 65 | + union { |
|---|
| 66 | + struct { |
|---|
| 67 | + unsigned long long mtime; /* mtime of section */ |
|---|
| 68 | + unsigned int segno; /* segment No. */ |
|---|
| 69 | + }; |
|---|
| 70 | + struct victim_info vi; /* victim info */ |
|---|
| 71 | + }; |
|---|
| 72 | + struct list_head list; |
|---|
| 73 | +}; |
|---|
| 74 | + |
|---|
| 44 | 75 | /* |
|---|
| 45 | 76 | * inline functions |
|---|
| 46 | 77 | */ |
|---|
| 78 | + |
|---|
| 79 | +/* |
|---|
| 80 | + * On a Zoned device zone-capacity can be less than zone-size and if |
|---|
| 81 | + * zone-capacity is not aligned to f2fs segment size(2MB), then the segment |
|---|
| 82 | + * starting just before zone-capacity has some blocks spanning across the |
|---|
| 83 | + * zone-capacity, these blocks are not usable. |
|---|
| 84 | + * Such spanning segments can be in free list so calculate the sum of usable |
|---|
| 85 | + * blocks in currently free segments including normal and spanning segments. |
|---|
| 86 | + */ |
|---|
| 87 | +static inline block_t free_segs_blk_count_zoned(struct f2fs_sb_info *sbi) |
|---|
| 88 | +{ |
|---|
| 89 | + block_t free_seg_blks = 0; |
|---|
| 90 | + struct free_segmap_info *free_i = FREE_I(sbi); |
|---|
| 91 | + int j; |
|---|
| 92 | + |
|---|
| 93 | + spin_lock(&free_i->segmap_lock); |
|---|
| 94 | + for (j = 0; j < MAIN_SEGS(sbi); j++) |
|---|
| 95 | + if (!test_bit(j, free_i->free_segmap)) |
|---|
| 96 | + free_seg_blks += f2fs_usable_blks_in_seg(sbi, j); |
|---|
| 97 | + spin_unlock(&free_i->segmap_lock); |
|---|
| 98 | + |
|---|
| 99 | + return free_seg_blks; |
|---|
| 100 | +} |
|---|
| 101 | + |
|---|
| 102 | +static inline block_t free_segs_blk_count(struct f2fs_sb_info *sbi) |
|---|
| 103 | +{ |
|---|
| 104 | + if (f2fs_sb_has_blkzoned(sbi)) |
|---|
| 105 | + return free_segs_blk_count_zoned(sbi); |
|---|
| 106 | + |
|---|
| 107 | + return free_segments(sbi) << sbi->log_blocks_per_seg; |
|---|
| 108 | +} |
|---|
| 109 | + |
|---|
| 47 | 110 | static inline block_t free_user_blocks(struct f2fs_sb_info *sbi) |
|---|
| 48 | 111 | { |
|---|
| 49 | | - if (free_segments(sbi) < overprovision_segments(sbi)) |
|---|
| 112 | + block_t free_blks, ovp_blks; |
|---|
| 113 | + |
|---|
| 114 | + free_blks = free_segs_blk_count(sbi); |
|---|
| 115 | + ovp_blks = overprovision_segments(sbi) << sbi->log_blocks_per_seg; |
|---|
| 116 | + |
|---|
| 117 | + if (free_blks < ovp_blks) |
|---|
| 50 | 118 | return 0; |
|---|
| 51 | | - else |
|---|
| 52 | | - return (free_segments(sbi) - overprovision_segments(sbi)) |
|---|
| 53 | | - << sbi->log_blocks_per_seg; |
|---|
| 119 | + |
|---|
| 120 | + return free_blks - ovp_blks; |
|---|
| 54 | 121 | } |
|---|
| 55 | 122 | |
|---|
| 56 | 123 | static inline block_t limit_invalid_user_blocks(struct f2fs_sb_info *sbi) |
|---|