Skip to content

Commit 1d2fbb7

Browse files
adam900710kdave
authored andcommitted
btrfs: allow compression even if the range is not page aligned
Previously for btrfs with sector size smaller than page size (subpage), we only allow compression if the range is fully page aligned. This is to work around the asynchronous submission of compressed range, which delayed the page unlock and writeback into a workqueue, furthermore asynchronous submission can lock multiple sector range across page boundary. Such asynchronous submission makes it very hard to co-operate with other regular writes. With the recent changes to the subpage folio unlock path, now asynchronous submission of compressed pages can co-operate with regular submission, so enable sector perfect compression if it's an experimental build. The ETA for moving this feature out of experimental is 6.15, and I hope all remaining corner cases can be exposed before that. Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent c96d0e3 commit 1d2fbb7

File tree

1 file changed

+7
-34
lines changed

1 file changed

+7
-34
lines changed

fs/btrfs/inode.c

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -832,32 +832,16 @@ static inline int inode_need_compress(struct btrfs_inode *inode, u64 start,
832832
return 0;
833833
}
834834
/*
835-
* Special check for subpage.
835+
* Only enable sector perfect compression for experimental builds.
836836
*
837-
* We lock the full page then run each delalloc range in the page, thus
838-
* for the following case, we will hit some subpage specific corner case:
837+
* This is a big feature change for subpage cases, and can hit
838+
* different corner cases, so only limit this feature for
839+
* experimental build for now.
839840
*
840-
* 0 32K 64K
841-
* | |///////| |///////|
842-
* \- A \- B
843-
*
844-
* In above case, both range A and range B will try to unlock the full
845-
* page [0, 64K), causing the one finished later will have page
846-
* unlocked already, triggering various page lock requirement BUG_ON()s.
847-
*
848-
* So here we add an artificial limit that subpage compression can only
849-
* if the range is fully page aligned.
850-
*
851-
* In theory we only need to ensure the first page is fully covered, but
852-
* the tailing partial page will be locked until the full compression
853-
* finishes, delaying the write of other range.
854-
*
855-
* TODO: Make btrfs_run_delalloc_range() to lock all delalloc range
856-
* first to prevent any submitted async extent to unlock the full page.
857-
* By this, we can ensure for subpage case that only the last async_cow
858-
* will unlock the full page.
841+
* ETA for moving this out of experimental builds is 6.15.
859842
*/
860-
if (fs_info->sectorsize < PAGE_SIZE) {
843+
if (fs_info->sectorsize < PAGE_SIZE &&
844+
!IS_ENABLED(CONFIG_BTRFS_EXPERIMENTAL)) {
861845
if (!PAGE_ALIGNED(start) ||
862846
!PAGE_ALIGNED(end + 1))
863847
return 0;
@@ -1002,17 +986,6 @@ static void compress_file_range(struct btrfs_work *work)
1002986
(start > 0 || end + 1 < inode->disk_i_size))
1003987
goto cleanup_and_bail_uncompressed;
1004988

1005-
/*
1006-
* For subpage case, we require full page alignment for the sector
1007-
* aligned range.
1008-
* Thus we must also check against @actual_end, not just @end.
1009-
*/
1010-
if (blocksize < PAGE_SIZE) {
1011-
if (!PAGE_ALIGNED(start) ||
1012-
!PAGE_ALIGNED(round_up(actual_end, blocksize)))
1013-
goto cleanup_and_bail_uncompressed;
1014-
}
1015-
1016989
total_compressed = min_t(unsigned long, total_compressed,
1017990
BTRFS_MAX_UNCOMPRESSED);
1018991
total_in = 0;

0 commit comments

Comments
 (0)