Skip to content

Commit 578def7

Browse files
committed
Btrfs: don't wait for unrelated IO to finish before relocation
Before the relocation process of a block group starts, it sets the block group to readonly mode, then flushes all delalloc writes and then finally it waits for all ordered extents to complete. This last step includes waiting for ordered extents destinated at extents allocated in other block groups, making us waste unecessary time. So improve this by waiting only for ordered extents that fall into the block group's range. Signed-off-by: Filipe Manana <[email protected]> Reviewed-by: Josef Bacik <[email protected]> Reviewed-by: Liu Bo <[email protected]>
1 parent 3f9749f commit 578def7

File tree

8 files changed

+38
-19
lines changed

8 files changed

+38
-19
lines changed

fs/btrfs/dev-replace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
403403
if (ret)
404404
btrfs_err(root->fs_info, "kobj add dev failed %d\n", ret);
405405

406-
btrfs_wait_ordered_roots(root->fs_info, -1);
406+
btrfs_wait_ordered_roots(root->fs_info, -1, 0, (u64)-1);
407407

408408
/* force writing the updated state information to disk */
409409
trans = btrfs_start_transaction(root, 0);
@@ -495,7 +495,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
495495
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
496496
return ret;
497497
}
498-
btrfs_wait_ordered_roots(root->fs_info, -1);
498+
btrfs_wait_ordered_roots(root->fs_info, -1, 0, (u64)-1);
499499

500500
trans = btrfs_start_transaction(root, 0);
501501
if (IS_ERR(trans)) {

fs/btrfs/extent-tree.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4141,7 +4141,7 @@ int btrfs_alloc_data_chunk_ondemand(struct inode *inode, u64 bytes)
41414141

41424142
if (need_commit > 0) {
41434143
btrfs_start_delalloc_roots(fs_info, 0, -1);
4144-
btrfs_wait_ordered_roots(fs_info, -1);
4144+
btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1);
41454145
}
41464146

41474147
trans = btrfs_join_transaction(root);
@@ -4583,7 +4583,8 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root,
45834583
*/
45844584
btrfs_start_delalloc_roots(root->fs_info, 0, nr_items);
45854585
if (!current->journal_info)
4586-
btrfs_wait_ordered_roots(root->fs_info, nr_items);
4586+
btrfs_wait_ordered_roots(root->fs_info, nr_items,
4587+
0, (u64)-1);
45874588
}
45884589
}
45894590

@@ -4632,7 +4633,8 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
46324633
if (trans)
46334634
return;
46344635
if (wait_ordered)
4635-
btrfs_wait_ordered_roots(root->fs_info, items);
4636+
btrfs_wait_ordered_roots(root->fs_info, items,
4637+
0, (u64)-1);
46364638
return;
46374639
}
46384640

@@ -4671,7 +4673,8 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
46714673

46724674
loops++;
46734675
if (wait_ordered && !trans) {
4674-
btrfs_wait_ordered_roots(root->fs_info, items);
4676+
btrfs_wait_ordered_roots(root->fs_info, items,
4677+
0, (u64)-1);
46754678
} else {
46764679
time_left = schedule_timeout_killable(1);
46774680
if (time_left)

fs/btrfs/ioctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
681681
if (ret)
682682
goto dec_and_free;
683683

684-
btrfs_wait_ordered_extents(root, -1);
684+
btrfs_wait_ordered_extents(root, -1, 0, (u64)-1);
685685

686686
btrfs_init_block_rsv(&pending_snapshot->block_rsv,
687687
BTRFS_BLOCK_RSV_TEMP);

fs/btrfs/ordered-data.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -661,21 +661,30 @@ static void btrfs_run_ordered_extent_work(struct btrfs_work *work)
661661
* wait for all the ordered extents in a root. This is done when balancing
662662
* space between drives.
663663
*/
664-
int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
664+
int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr,
665+
const u64 range_start, const u64 range_len)
665666
{
666-
struct list_head splice, works;
667+
LIST_HEAD(splice);
668+
LIST_HEAD(skipped);
669+
LIST_HEAD(works);
667670
struct btrfs_ordered_extent *ordered, *next;
668671
int count = 0;
669-
670-
INIT_LIST_HEAD(&splice);
671-
INIT_LIST_HEAD(&works);
672+
const u64 range_end = range_start + range_len;
672673

673674
mutex_lock(&root->ordered_extent_mutex);
674675
spin_lock(&root->ordered_extent_lock);
675676
list_splice_init(&root->ordered_extents, &splice);
676677
while (!list_empty(&splice) && nr) {
677678
ordered = list_first_entry(&splice, struct btrfs_ordered_extent,
678679
root_extent_list);
680+
681+
if (range_end <= ordered->start ||
682+
ordered->start + ordered->disk_len <= range_start) {
683+
list_move_tail(&ordered->root_extent_list, &skipped);
684+
cond_resched_lock(&root->ordered_extent_lock);
685+
continue;
686+
}
687+
679688
list_move_tail(&ordered->root_extent_list,
680689
&root->ordered_extents);
681690
atomic_inc(&ordered->refs);
@@ -694,6 +703,7 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
694703
nr--;
695704
count++;
696705
}
706+
list_splice_tail(&skipped, &root->ordered_extents);
697707
list_splice_tail(&splice, &root->ordered_extents);
698708
spin_unlock(&root->ordered_extent_lock);
699709

@@ -708,7 +718,8 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
708718
return count;
709719
}
710720

711-
void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr)
721+
void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
722+
const u64 range_start, const u64 range_len)
712723
{
713724
struct btrfs_root *root;
714725
struct list_head splice;
@@ -728,7 +739,8 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr)
728739
&fs_info->ordered_roots);
729740
spin_unlock(&fs_info->ordered_root_lock);
730741

731-
done = btrfs_wait_ordered_extents(root, nr);
742+
done = btrfs_wait_ordered_extents(root, nr,
743+
range_start, range_len);
732744
btrfs_put_fs_root(root);
733745

734746
spin_lock(&fs_info->ordered_root_lock);

fs/btrfs/ordered-data.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,10 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
197197
struct btrfs_ordered_extent *ordered);
198198
int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
199199
u32 *sum, int len);
200-
int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr);
201-
void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr);
200+
int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr,
201+
const u64 range_start, const u64 range_len);
202+
void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
203+
const u64 range_start, const u64 range_len);
202204
void btrfs_get_logged_extents(struct inode *inode,
203205
struct list_head *logged_list,
204206
const loff_t start,

fs/btrfs/relocation.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4259,7 +4259,9 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
42594259
err = ret;
42604260
goto out;
42614261
}
4262-
btrfs_wait_ordered_roots(fs_info, -1);
4262+
btrfs_wait_ordered_roots(fs_info, -1,
4263+
rc->block_group->key.objectid,
4264+
rc->block_group->key.offset);
42634265

42644266
while (1) {
42654267
mutex_lock(&fs_info->cleaner_mutex);

fs/btrfs/super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,7 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
11601160
return 0;
11611161
}
11621162

1163-
btrfs_wait_ordered_roots(fs_info, -1);
1163+
btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1);
11641164

11651165
trans = btrfs_attach_transaction_barrier(root);
11661166
if (IS_ERR(trans)) {

fs/btrfs/transaction.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1821,7 +1821,7 @@ static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
18211821
static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info)
18221822
{
18231823
if (btrfs_test_opt(fs_info->tree_root, FLUSHONCOMMIT))
1824-
btrfs_wait_ordered_roots(fs_info, -1);
1824+
btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1);
18251825
}
18261826

18271827
static inline void

0 commit comments

Comments
 (0)