Skip to content

Commit

Permalink
btrfs: update writeback index when starting defrag
Browse files Browse the repository at this point in the history
When starting a defrag, we should update the writeback index of the
inode's mapping in case it currently has a value beyond the start of the
range we are defragging. This can help performance and often result in
getting less extents after writeback - for e.g., if the current value
of the writeback index sits somewhere in the middle of a range that
gets dirty by the defrag, then after writeback we can get two smaller
extents instead of a single, larger extent.

We used to have this before the refactoring in 5.16, but it was removed
without any reason to do so. Originally it was added in kernel 3.1, by
commit 2a0f7f5 ("Btrfs: fix recursive auto-defrag"), in order to
fix a loop with autodefrag resulting in dirtying and writing pages over
and over, but some testing on current code did not show that happening,
at least with the test described in that commit.

So add back the behaviour, as at the very least it is a nice to have
optimization.

Fixes: 7b50803 ("btrfs: defrag: use defrag_one_cluster() to implement btrfs_defrag_file()")
CC: [email protected] # 5.16
Signed-off-by: Filipe Manana <[email protected]>
Signed-off-by: David Sterba <[email protected]>
  • Loading branch information
fdmanana authored and kdave committed Jan 24, 2022
1 parent 3c9d31c commit 27cdfde
Showing 1 changed file with 9 additions and 0 deletions.
9 changes: 9 additions & 0 deletions fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1537,6 +1537,7 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra,
int compress_type = BTRFS_COMPRESS_ZLIB;
int ret = 0;
u32 extent_thresh = range->extent_thresh;
pgoff_t start_index;

if (isize == 0)
return 0;
Expand Down Expand Up @@ -1578,6 +1579,14 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra,
file_ra_state_init(ra, inode->i_mapping);
}

/*
* Make writeback start from the beginning of the range, so that the
* defrag range can be written sequentially.
*/
start_index = cur >> PAGE_SHIFT;
if (start_index < inode->i_mapping->writeback_index)
inode->i_mapping->writeback_index = start_index;

while (cur < last_byte) {
const unsigned long prev_sectors_defragged = sectors_defragged;
u64 cluster_end;
Expand Down

0 comments on commit 27cdfde

Please sign in to comment.