Skip to content

Commit c2ffb1e

Browse files
adam900710kdave
authored andcommitted
btrfs: prepare compression folio alloc/free for bs > ps cases
This includes the following preparation for bs > ps cases: - Always alloc/free the folio directly if bs > ps This adds a new @fs_info parameter for btrfs_alloc_compr_folio(), thus affecting all compression algorithms. For btrfs_free_compr_folio() it needs no parameter for now, as we can use the folio size to skip the caching part. For now the change is just to passing a @fs_info into the function, all the folio size assumption is still based on page size. - Properly zero the last folio in compress_file_range() Since the compressed folios can be larger than a page, we need to properly zero the whole folio. - Use correct folio size for btrfs_add_compressed_bio_folios() Instead of page size, use the correct folio size. - Use correct folio size/shift for btrfs_compress_filemap_get_folio() As we are not only using simple page sized folios anymore. - Use correct folio size for btrfs_decompress() There is an ASSERT() making sure the decompressed range is no larger than a page, which will be triggered for bs > ps cases. - Skip readahead for compressed pages Similar to subpage cases. - Make btrfs_alloc_folio_array() to accept a new @order parameter - Add a helper to calculate the minimal folio size All those changes should not affect the existing bs <= ps handling. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 7b26da4 commit c2ffb1e

9 files changed

Lines changed: 78 additions & 44 deletions

File tree

fs/btrfs/compression.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,14 @@ static unsigned long btrfs_compr_pool_scan(struct shrinker *sh, struct shrink_co
223223
/*
224224
* Common wrappers for page allocation from compression wrappers
225225
*/
226-
struct folio *btrfs_alloc_compr_folio(void)
226+
struct folio *btrfs_alloc_compr_folio(struct btrfs_fs_info *fs_info)
227227
{
228228
struct folio *folio = NULL;
229229

230+
/* For bs > ps cases, no cached folio pool for now. */
231+
if (fs_info->block_min_order)
232+
goto alloc;
233+
230234
spin_lock(&compr_pool.lock);
231235
if (compr_pool.count > 0) {
232236
folio = list_first_entry(&compr_pool.list, struct folio, lru);
@@ -238,13 +242,18 @@ struct folio *btrfs_alloc_compr_folio(void)
238242
if (folio)
239243
return folio;
240244

241-
return folio_alloc(GFP_NOFS, 0);
245+
alloc:
246+
return folio_alloc(GFP_NOFS, fs_info->block_min_order);
242247
}
243248

244249
void btrfs_free_compr_folio(struct folio *folio)
245250
{
246251
bool do_free = false;
247252

253+
/* The folio is from bs > ps fs, no cached pool for now. */
254+
if (folio_order(folio))
255+
goto free;
256+
248257
spin_lock(&compr_pool.lock);
249258
if (compr_pool.count > compr_pool.thresh) {
250259
do_free = true;
@@ -257,6 +266,7 @@ void btrfs_free_compr_folio(struct folio *folio)
257266
if (!do_free)
258267
return;
259268

269+
free:
260270
ASSERT(folio_ref_count(folio) == 1);
261271
folio_put(folio);
262272
}
@@ -344,16 +354,19 @@ static void end_bbio_compressed_write(struct btrfs_bio *bbio)
344354

345355
static void btrfs_add_compressed_bio_folios(struct compressed_bio *cb)
346356
{
357+
struct btrfs_fs_info *fs_info = cb->bbio.fs_info;
347358
struct bio *bio = &cb->bbio.bio;
348359
u32 offset = 0;
349360

350361
while (offset < cb->compressed_len) {
362+
struct folio *folio;
351363
int ret;
352-
u32 len = min_t(u32, cb->compressed_len - offset, PAGE_SIZE);
364+
u32 len = min_t(u32, cb->compressed_len - offset,
365+
btrfs_min_folio_size(fs_info));
353366

367+
folio = cb->compressed_folios[offset >> (PAGE_SHIFT + fs_info->block_min_order)];
354368
/* Maximum compressed extent is smaller than bio size limit. */
355-
ret = bio_add_folio(bio, cb->compressed_folios[offset >> PAGE_SHIFT],
356-
len, 0);
369+
ret = bio_add_folio(bio, folio, len, 0);
357370
ASSERT(ret);
358371
offset += len;
359372
}
@@ -443,6 +456,10 @@ static noinline int add_ra_bio_pages(struct inode *inode,
443456
if (fs_info->sectorsize < PAGE_SIZE)
444457
return 0;
445458

459+
/* For bs > ps cases, we don't support readahead for compressed folios for now. */
460+
if (fs_info->block_min_order)
461+
return 0;
462+
446463
end_index = (i_size_read(inode) - 1) >> PAGE_SHIFT;
447464

448465
while (cur < compressed_end) {
@@ -606,14 +623,15 @@ void btrfs_submit_compressed_read(struct btrfs_bio *bbio)
606623

607624
btrfs_free_extent_map(em);
608625

609-
cb->nr_folios = DIV_ROUND_UP(compressed_len, PAGE_SIZE);
626+
cb->nr_folios = DIV_ROUND_UP(compressed_len, btrfs_min_folio_size(fs_info));
610627
cb->compressed_folios = kcalloc(cb->nr_folios, sizeof(struct folio *), GFP_NOFS);
611628
if (!cb->compressed_folios) {
612629
status = BLK_STS_RESOURCE;
613630
goto out_free_bio;
614631
}
615632

616-
ret = btrfs_alloc_folio_array(cb->nr_folios, cb->compressed_folios);
633+
ret = btrfs_alloc_folio_array(cb->nr_folios, fs_info->block_min_order,
634+
cb->compressed_folios);
617635
if (ret) {
618636
status = BLK_STS_RESOURCE;
619637
goto out_free_compressed_pages;
@@ -1033,12 +1051,12 @@ int btrfs_compress_filemap_get_folio(struct address_space *mapping, u64 start,
10331051
* - compression algo are 0-3
10341052
* - the level are bits 4-7
10351053
*
1036-
* @out_pages is an in/out parameter, holds maximum number of pages to allocate
1037-
* and returns number of actually allocated pages
1054+
* @out_folios is an in/out parameter, holds maximum number of folios to allocate
1055+
* and returns number of actually allocated folios
10381056
*
10391057
* @total_in is used to return the number of bytes actually read. It
10401058
* may be smaller than the input length if we had to exit early because we
1041-
* ran out of room in the pages array or because we cross the
1059+
* ran out of room in the folios array or because we cross the
10421060
* max_out threshold.
10431061
*
10441062
* @total_out is an in/out parameter, must be set to the input length and will
@@ -1093,11 +1111,11 @@ int btrfs_decompress(int type, const u8 *data_in, struct folio *dest_folio,
10931111
int ret;
10941112

10951113
/*
1096-
* The full destination page range should not exceed the page size.
1114+
* The full destination folio range should not exceed the folio size.
10971115
* And the @destlen should not exceed sectorsize, as this is only called for
10981116
* inline file extents, which should not exceed sectorsize.
10991117
*/
1100-
ASSERT(dest_pgoff + destlen <= PAGE_SIZE && destlen <= sectorsize);
1118+
ASSERT(dest_pgoff + destlen <= folio_size(dest_folio) && destlen <= sectorsize);
11011119

11021120
workspace = get_workspace(fs_info, type, 0);
11031121
ret = compression_decompress(type, workspace, data_in, dest_folio,

fs/btrfs/compression.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ void btrfs_submit_compressed_read(struct btrfs_bio *bbio);
112112

113113
int btrfs_compress_str2level(unsigned int type, const char *str, int *level_ret);
114114

115-
struct folio *btrfs_alloc_compr_folio(void);
115+
struct folio *btrfs_alloc_compr_folio(struct btrfs_fs_info *fs_info);
116116
void btrfs_free_compr_folio(struct folio *folio);
117117

118118
struct workspace_manager {

fs/btrfs/extent_io.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,19 +626,21 @@ static void end_bbio_data_read(struct btrfs_bio *bbio)
626626
* Populate every free slot in a provided array with folios using GFP_NOFS.
627627
*
628628
* @nr_folios: number of folios to allocate
629+
* @order: the order of the folios to be allocated
629630
* @folio_array: the array to fill with folios; any existing non-NULL entries in
630631
* the array will be skipped
631632
*
632633
* Return: 0 if all folios were able to be allocated;
633634
* -ENOMEM otherwise, the partially allocated folios would be freed and
634635
* the array slots zeroed
635636
*/
636-
int btrfs_alloc_folio_array(unsigned int nr_folios, struct folio **folio_array)
637+
int btrfs_alloc_folio_array(unsigned int nr_folios, unsigned int order,
638+
struct folio **folio_array)
637639
{
638640
for (int i = 0; i < nr_folios; i++) {
639641
if (folio_array[i])
640642
continue;
641-
folio_array[i] = folio_alloc(GFP_NOFS, 0);
643+
folio_array[i] = folio_alloc(GFP_NOFS, order);
642644
if (!folio_array[i])
643645
goto error;
644646
}
@@ -647,6 +649,7 @@ int btrfs_alloc_folio_array(unsigned int nr_folios, struct folio **folio_array)
647649
for (int i = 0; i < nr_folios; i++) {
648650
if (folio_array[i])
649651
folio_put(folio_array[i]);
652+
folio_array[i] = NULL;
650653
}
651654
return -ENOMEM;
652655
}

fs/btrfs/extent_io.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans,
366366

367367
int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array,
368368
bool nofail);
369-
int btrfs_alloc_folio_array(unsigned int nr_folios, struct folio **folio_array);
369+
int btrfs_alloc_folio_array(unsigned int nr_folios, unsigned int order,
370+
struct folio **folio_array);
370371

371372
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
372373
bool find_lock_delalloc_range(struct inode *inode,

fs/btrfs/fs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,12 @@ static inline gfp_t btrfs_alloc_write_mask(struct address_space *mapping)
923923
return mapping_gfp_constraint(mapping, ~__GFP_FS);
924924
}
925925

926+
/* Return the minimal folio size of the fs. */
927+
static inline unsigned int btrfs_min_folio_size(struct btrfs_fs_info *fs_info)
928+
{
929+
return 1U << (PAGE_SHIFT + fs_info->block_min_order);
930+
}
931+
926932
static inline u64 btrfs_get_fs_generation(const struct btrfs_fs_info *fs_info)
927933
{
928934
return READ_ONCE(fs_info->generation);

fs/btrfs/inode.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,8 @@ static void compress_file_range(struct btrfs_work *work)
854854
struct btrfs_inode *inode = async_chunk->inode;
855855
struct btrfs_fs_info *fs_info = inode->root->fs_info;
856856
struct address_space *mapping = inode->vfs_inode.i_mapping;
857+
const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
858+
const u32 min_folio_size = btrfs_min_folio_size(fs_info);
857859
u64 blocksize = fs_info->sectorsize;
858860
u64 start = async_chunk->start;
859861
u64 end = async_chunk->end;
@@ -864,7 +866,7 @@ static void compress_file_range(struct btrfs_work *work)
864866
unsigned long nr_folios;
865867
unsigned long total_compressed = 0;
866868
unsigned long total_in = 0;
867-
unsigned int poff;
869+
unsigned int loff;
868870
int i;
869871
int compress_type = fs_info->compress_type;
870872
int compress_level = fs_info->compress_level;
@@ -902,8 +904,8 @@ static void compress_file_range(struct btrfs_work *work)
902904
actual_end = min_t(u64, i_size, end + 1);
903905
again:
904906
folios = NULL;
905-
nr_folios = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
906-
nr_folios = min_t(unsigned long, nr_folios, BTRFS_MAX_COMPRESSED_PAGES);
907+
nr_folios = (end >> min_folio_shift) - (start >> min_folio_shift) + 1;
908+
nr_folios = min_t(unsigned long, nr_folios, BTRFS_MAX_COMPRESSED >> min_folio_shift);
907909

908910
/*
909911
* we don't want to send crud past the end of i_size through
@@ -965,12 +967,12 @@ static void compress_file_range(struct btrfs_work *work)
965967
goto mark_incompressible;
966968

967969
/*
968-
* Zero the tail end of the last page, as we might be sending it down
970+
* Zero the tail end of the last folio, as we might be sending it down
969971
* to disk.
970972
*/
971-
poff = offset_in_page(total_compressed);
972-
if (poff)
973-
folio_zero_range(folios[nr_folios - 1], poff, PAGE_SIZE - poff);
973+
loff = (total_compressed & (min_folio_size - 1));
974+
if (loff)
975+
folio_zero_range(folios[nr_folios - 1], loff, min_folio_size - loff);
974976

975977
/*
976978
* Try to create an inline extent.

fs/btrfs/lzo.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,14 @@ static inline size_t read_compress_length(const char *buf)
132132
*
133133
* Will allocate new pages when needed.
134134
*/
135-
static int copy_compressed_data_to_page(char *compressed_data,
135+
static int copy_compressed_data_to_page(struct btrfs_fs_info *fs_info,
136+
char *compressed_data,
136137
size_t compressed_size,
137138
struct folio **out_folios,
138139
unsigned long max_nr_folio,
139-
u32 *cur_out,
140-
const u32 sectorsize)
140+
u32 *cur_out)
141141
{
142+
const u32 sectorsize = fs_info->sectorsize;
142143
u32 sector_bytes_left;
143144
u32 orig_out;
144145
struct folio *cur_folio;
@@ -156,7 +157,7 @@ static int copy_compressed_data_to_page(char *compressed_data,
156157
cur_folio = out_folios[*cur_out / PAGE_SIZE];
157158
/* Allocate a new page */
158159
if (!cur_folio) {
159-
cur_folio = btrfs_alloc_compr_folio();
160+
cur_folio = btrfs_alloc_compr_folio(fs_info);
160161
if (!cur_folio)
161162
return -ENOMEM;
162163
out_folios[*cur_out / PAGE_SIZE] = cur_folio;
@@ -182,7 +183,7 @@ static int copy_compressed_data_to_page(char *compressed_data,
182183
cur_folio = out_folios[*cur_out / PAGE_SIZE];
183184
/* Allocate a new page */
184185
if (!cur_folio) {
185-
cur_folio = btrfs_alloc_compr_folio();
186+
cur_folio = btrfs_alloc_compr_folio(fs_info);
186187
if (!cur_folio)
187188
return -ENOMEM;
188189
out_folios[*cur_out / PAGE_SIZE] = cur_folio;
@@ -217,8 +218,9 @@ int lzo_compress_folios(struct list_head *ws, struct btrfs_inode *inode,
217218
u64 start, struct folio **folios, unsigned long *out_folios,
218219
unsigned long *total_in, unsigned long *total_out)
219220
{
221+
struct btrfs_fs_info *fs_info = inode->root->fs_info;
220222
struct workspace *workspace = list_entry(ws, struct workspace, list);
221-
const u32 sectorsize = inode->root->fs_info->sectorsize;
223+
const u32 sectorsize = fs_info->sectorsize;
222224
struct address_space *mapping = inode->vfs_inode.i_mapping;
223225
struct folio *folio_in = NULL;
224226
char *sizes_ptr;
@@ -268,9 +270,9 @@ int lzo_compress_folios(struct list_head *ws, struct btrfs_inode *inode,
268270
goto out;
269271
}
270272

271-
ret = copy_compressed_data_to_page(workspace->cbuf, out_len,
273+
ret = copy_compressed_data_to_page(fs_info, workspace->cbuf, out_len,
272274
folios, max_nr_folio,
273-
&cur_out, sectorsize);
275+
&cur_out);
274276
if (ret < 0)
275277
goto out;
276278

fs/btrfs/zlib.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ int zlib_compress_folios(struct list_head *ws, struct btrfs_inode *inode,
136136
u64 start, struct folio **folios, unsigned long *out_folios,
137137
unsigned long *total_in, unsigned long *total_out)
138138
{
139+
struct btrfs_fs_info *fs_info = inode->root->fs_info;
139140
struct workspace *workspace = list_entry(ws, struct workspace, list);
140141
struct address_space *mapping = inode->vfs_inode.i_mapping;
141142
int ret;
@@ -147,7 +148,7 @@ int zlib_compress_folios(struct list_head *ws, struct btrfs_inode *inode,
147148
unsigned long len = *total_out;
148149
unsigned long nr_dest_folios = *out_folios;
149150
const unsigned long max_out = nr_dest_folios * PAGE_SIZE;
150-
const u32 blocksize = inode->root->fs_info->sectorsize;
151+
const u32 blocksize = fs_info->sectorsize;
151152
const u64 orig_end = start + len;
152153

153154
*out_folios = 0;
@@ -156,7 +157,7 @@ int zlib_compress_folios(struct list_head *ws, struct btrfs_inode *inode,
156157

157158
ret = zlib_deflateInit(&workspace->strm, workspace->level);
158159
if (unlikely(ret != Z_OK)) {
159-
btrfs_err(inode->root->fs_info,
160+
btrfs_err(fs_info,
160161
"zlib compression init failed, error %d root %llu inode %llu offset %llu",
161162
ret, btrfs_root_id(inode->root), btrfs_ino(inode), start);
162163
ret = -EIO;
@@ -166,7 +167,7 @@ int zlib_compress_folios(struct list_head *ws, struct btrfs_inode *inode,
166167
workspace->strm.total_in = 0;
167168
workspace->strm.total_out = 0;
168169

169-
out_folio = btrfs_alloc_compr_folio();
170+
out_folio = btrfs_alloc_compr_folio(fs_info);
170171
if (out_folio == NULL) {
171172
ret = -ENOMEM;
172173
goto out;
@@ -224,7 +225,7 @@ int zlib_compress_folios(struct list_head *ws, struct btrfs_inode *inode,
224225

225226
ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH);
226227
if (unlikely(ret != Z_OK)) {
227-
btrfs_warn(inode->root->fs_info,
228+
btrfs_warn(fs_info,
228229
"zlib compression failed, error %d root %llu inode %llu offset %llu",
229230
ret, btrfs_root_id(inode->root), btrfs_ino(inode),
230231
start);
@@ -249,7 +250,7 @@ int zlib_compress_folios(struct list_head *ws, struct btrfs_inode *inode,
249250
ret = -E2BIG;
250251
goto out;
251252
}
252-
out_folio = btrfs_alloc_compr_folio();
253+
out_folio = btrfs_alloc_compr_folio(fs_info);
253254
if (out_folio == NULL) {
254255
ret = -ENOMEM;
255256
goto out;
@@ -285,7 +286,7 @@ int zlib_compress_folios(struct list_head *ws, struct btrfs_inode *inode,
285286
ret = -E2BIG;
286287
goto out;
287288
}
288-
out_folio = btrfs_alloc_compr_folio();
289+
out_folio = btrfs_alloc_compr_folio(fs_info);
289290
if (out_folio == NULL) {
290291
ret = -ENOMEM;
291292
goto out;

0 commit comments

Comments
 (0)