summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2026-09-10 11:35:53 +0930
committerDavid Sterba <dsterba@suse.com>2026-09-16 15:29:26 +0200
commite894e7cf00f7cf62252645bb907d5172cca8fede (patch)
treefe41e1f8948b239fa7a59c9d3460a345344c5848
parent9dc38f249a02e99124058caf6d4926fa0e0032fe (diff)
downloadlinux-next-e894e7cf00f7cf62252645bb907d5172cca8fede.tar.gz
linux-next-e894e7cf00f7cf62252645bb907d5172cca8fede.zip
btrfs: simplify heuristic_collect_sample() to handle large folios better
Currently heuristic_collect_sample() is purely page size based, and it has a lot of extra handling just inside the page. However we already have large folio support, there is no need to look up the same folio repeatedly. Simplify the handling by: - Use @cur as the iterator instead of page index - Handle the sample copying on a per-folio basis Although kmap_local_folio() requires an offset to handle HIGHMEM page mapping, we have rejected large folios for HIGHMEM systems completely. So we can safely handle all sample copying inside the folio in one go. - Remove unnecessary unaligned range handling All the range passed in should be block aligned, thus there is no need to handle cases where sample crosses the block boundary. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/compression.c40
1 files changed, 16 insertions, 24 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 7c1c018dbd6f..ad90e14032db 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -1489,10 +1489,8 @@ static void heuristic_collect_sample(struct inode *inode, u64 start, u64 end,
struct heuristic_ws *ws)
{
const u32 blocksize = BTRFS_I(inode)->root->fs_info->sectorsize;
- struct folio *folio;
- u64 index, index_end;
- u32 i, curr_sample_pos;
- u8 *in_data;
+ u64 cur = start;
+ u32 curr_sample_pos = 0;
ASSERT(IS_ALIGNED(start, blocksize) && IS_ALIGNED(end + 1, blocksize));
@@ -1508,33 +1506,27 @@ static void heuristic_collect_sample(struct inode *inode, u64 start, u64 end,
if (end + 1 - start > BTRFS_MAX_UNCOMPRESSED)
end = start + BTRFS_MAX_UNCOMPRESSED - 1;
- index = start >> PAGE_SHIFT;
- index_end = end >> PAGE_SHIFT;
+ while (cur < end) {
+ struct folio *folio;
+ void *in_data;
+ u64 next_pos;
- curr_sample_pos = 0;
- while (index <= index_end) {
- folio = filemap_get_folio(inode->i_mapping, index);
+ folio = filemap_get_folio(inode->i_mapping, cur >> PAGE_SHIFT);
+ /* All folios inside the range should exist and be locked. */
ASSERT(!IS_ERR(folio));
- in_data = kmap_local_folio(folio,
- offset_in_folio(folio, index << PAGE_SHIFT));
- /* Handle case where the start is not aligned to PAGE_SIZE */
- i = start % PAGE_SIZE;
- while (i < PAGE_SIZE - SAMPLING_READ_SIZE) {
- /* Don't sample any garbage from the last page */
- if (start > end + 1 - SAMPLING_READ_SIZE)
- break;
- memcpy(&ws->sample[curr_sample_pos], &in_data[i],
- SAMPLING_READ_SIZE);
- i += SAMPLING_INTERVAL;
- start += SAMPLING_INTERVAL;
+ next_pos = min_t(u64, end + 1, folio_next_pos(folio));
+ in_data = kmap_local_folio(folio, 0);
+
+ for (; cur < next_pos; cur += SAMPLING_INTERVAL) {
+ memcpy(&ws->sample[curr_sample_pos],
+ in_data + offset_in_folio(folio, cur),
+ SAMPLING_READ_SIZE);
curr_sample_pos += SAMPLING_READ_SIZE;
}
kunmap_local(in_data);
folio_put(folio);
-
- index++;
+ cur = next_pos;
}
-
ws->sample_size = curr_sample_pos;
}