@@ -752,6 +752,14 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
752
752
goto free_cache ;
753
753
}
754
754
755
+ /*
756
+ * Sync discard ensures that the free space cache is always
757
+ * trimmed. So when reading this in, the state should reflect
758
+ * that.
759
+ */
760
+ if (btrfs_test_opt (fs_info , DISCARD_SYNC ))
761
+ e -> trim_state = BTRFS_TRIM_STATE_TRIMMED ;
762
+
755
763
if (!e -> bytes ) {
756
764
kmem_cache_free (btrfs_free_space_cachep , e );
757
765
goto free_cache ;
@@ -2161,6 +2169,22 @@ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl,
2161
2169
return ret ;
2162
2170
}
2163
2171
2172
+ /*
2173
+ * Free space merging rules:
2174
+ * 1) Merge trimmed areas together
2175
+ * 2) Let untrimmed areas coalesce with trimmed areas
2176
+ * 3) Always pull neighboring regions from bitmaps
2177
+ *
2178
+ * The above rules are for when we merge free space based on btrfs_trim_state.
2179
+ * Rules 2 and 3 are subtle because they are suboptimal, but are done for the
2180
+ * same reason: to promote larger extent regions which makes life easier for
2181
+ * find_free_extent(). Rule 2 enables coalescing based on the common path
2182
+ * being returning free space from btrfs_finish_extent_commit(). So when free
2183
+ * space is trimmed, it will prevent aggregating trimmed new region and
2184
+ * untrimmed regions in the rb_tree. Rule 3 is purely to obtain larger extents
2185
+ * and provide find_free_extent() with the largest extents possible hoping for
2186
+ * the reuse path.
2187
+ */
2164
2188
static bool try_merge_free_space (struct btrfs_free_space_ctl * ctl ,
2165
2189
struct btrfs_free_space * info , bool update_stat )
2166
2190
{
@@ -2169,6 +2193,7 @@ static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl,
2169
2193
bool merged = false;
2170
2194
u64 offset = info -> offset ;
2171
2195
u64 bytes = info -> bytes ;
2196
+ const bool is_trimmed = btrfs_free_space_trimmed (info );
2172
2197
2173
2198
/*
2174
2199
* first we want to see if there is free space adjacent to the range we
@@ -2182,7 +2207,9 @@ static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl,
2182
2207
else
2183
2208
left_info = tree_search_offset (ctl , offset - 1 , 0 , 0 );
2184
2209
2185
- if (right_info && !right_info -> bitmap ) {
2210
+ /* See try_merge_free_space() comment. */
2211
+ if (right_info && !right_info -> bitmap &&
2212
+ (!is_trimmed || btrfs_free_space_trimmed (right_info ))) {
2186
2213
if (update_stat )
2187
2214
unlink_free_space (ctl , right_info );
2188
2215
else
@@ -2192,8 +2219,10 @@ static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl,
2192
2219
merged = true;
2193
2220
}
2194
2221
2222
+ /* See try_merge_free_space() comment. */
2195
2223
if (left_info && !left_info -> bitmap &&
2196
- left_info -> offset + left_info -> bytes == offset ) {
2224
+ left_info -> offset + left_info -> bytes == offset &&
2225
+ (!is_trimmed || btrfs_free_space_trimmed (left_info ))) {
2197
2226
if (update_stat )
2198
2227
unlink_free_space (ctl , left_info );
2199
2228
else
@@ -2229,6 +2258,10 @@ static bool steal_from_bitmap_to_end(struct btrfs_free_space_ctl *ctl,
2229
2258
bytes = (j - i ) * ctl -> unit ;
2230
2259
info -> bytes += bytes ;
2231
2260
2261
+ /* See try_merge_free_space() comment. */
2262
+ if (!btrfs_free_space_trimmed (bitmap ))
2263
+ info -> trim_state = BTRFS_TRIM_STATE_UNTRIMMED ;
2264
+
2232
2265
if (update_stat )
2233
2266
bitmap_clear_bits (ctl , bitmap , end , bytes );
2234
2267
else
@@ -2282,6 +2315,10 @@ static bool steal_from_bitmap_to_front(struct btrfs_free_space_ctl *ctl,
2282
2315
info -> offset -= bytes ;
2283
2316
info -> bytes += bytes ;
2284
2317
2318
+ /* See try_merge_free_space() comment. */
2319
+ if (!btrfs_free_space_trimmed (bitmap ))
2320
+ info -> trim_state = BTRFS_TRIM_STATE_UNTRIMMED ;
2321
+
2285
2322
if (update_stat )
2286
2323
bitmap_clear_bits (ctl , bitmap , info -> offset , bytes );
2287
2324
else
@@ -2331,7 +2368,8 @@ static void steal_from_bitmap(struct btrfs_free_space_ctl *ctl,
2331
2368
2332
2369
int __btrfs_add_free_space (struct btrfs_fs_info * fs_info ,
2333
2370
struct btrfs_free_space_ctl * ctl ,
2334
- u64 offset , u64 bytes )
2371
+ u64 offset , u64 bytes ,
2372
+ enum btrfs_trim_state trim_state )
2335
2373
{
2336
2374
struct btrfs_free_space * info ;
2337
2375
int ret = 0 ;
@@ -2342,6 +2380,7 @@ int __btrfs_add_free_space(struct btrfs_fs_info *fs_info,
2342
2380
2343
2381
info -> offset = offset ;
2344
2382
info -> bytes = bytes ;
2383
+ info -> trim_state = trim_state ;
2345
2384
RB_CLEAR_NODE (& info -> offset_index );
2346
2385
2347
2386
spin_lock (& ctl -> tree_lock );
@@ -2387,9 +2426,14 @@ int __btrfs_add_free_space(struct btrfs_fs_info *fs_info,
2387
2426
int btrfs_add_free_space (struct btrfs_block_group * block_group ,
2388
2427
u64 bytenr , u64 size )
2389
2428
{
2429
+ enum btrfs_trim_state trim_state = BTRFS_TRIM_STATE_UNTRIMMED ;
2430
+
2431
+ if (btrfs_test_opt (block_group -> fs_info , DISCARD_SYNC ))
2432
+ trim_state = BTRFS_TRIM_STATE_TRIMMED ;
2433
+
2390
2434
return __btrfs_add_free_space (block_group -> fs_info ,
2391
2435
block_group -> free_space_ctl ,
2392
- bytenr , size );
2436
+ bytenr , size , trim_state );
2393
2437
}
2394
2438
2395
2439
int btrfs_remove_free_space (struct btrfs_block_group * block_group ,
@@ -2464,8 +2508,10 @@ int btrfs_remove_free_space(struct btrfs_block_group *block_group,
2464
2508
}
2465
2509
spin_unlock (& ctl -> tree_lock );
2466
2510
2467
- ret = btrfs_add_free_space (block_group , offset + bytes ,
2468
- old_end - (offset + bytes ));
2511
+ ret = __btrfs_add_free_space (block_group -> fs_info , ctl ,
2512
+ offset + bytes ,
2513
+ old_end - (offset + bytes ),
2514
+ info -> trim_state );
2469
2515
WARN_ON (ret );
2470
2516
goto out ;
2471
2517
}
@@ -2634,6 +2680,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group *block_group,
2634
2680
u64 ret = 0 ;
2635
2681
u64 align_gap = 0 ;
2636
2682
u64 align_gap_len = 0 ;
2683
+ enum btrfs_trim_state align_gap_trim_state = BTRFS_TRIM_STATE_UNTRIMMED ;
2637
2684
2638
2685
spin_lock (& ctl -> tree_lock );
2639
2686
entry = find_free_space (ctl , & offset , & bytes_search ,
@@ -2650,6 +2697,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group *block_group,
2650
2697
unlink_free_space (ctl , entry );
2651
2698
align_gap_len = offset - entry -> offset ;
2652
2699
align_gap = entry -> offset ;
2700
+ align_gap_trim_state = entry -> trim_state ;
2653
2701
2654
2702
entry -> offset = offset + bytes ;
2655
2703
WARN_ON (entry -> bytes < bytes + align_gap_len );
@@ -2665,7 +2713,8 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group *block_group,
2665
2713
2666
2714
if (align_gap_len )
2667
2715
__btrfs_add_free_space (block_group -> fs_info , ctl ,
2668
- align_gap , align_gap_len );
2716
+ align_gap , align_gap_len ,
2717
+ align_gap_trim_state );
2669
2718
return ret ;
2670
2719
}
2671
2720
0 commit comments