Skip to content

Commit fd1e75d

Browse files
adam900710kdave
authored andcommitted
btrfs: make compression path to be subpage compatible
Currently btrfs compression path is not really subpage compatible, every thing is still done in page unit. That's fine for regular sector size and subpage routine. As even for subpage routine compression is only enabled if the whole range is page aligned, so reading the page cache in page unit is totally fine. However in preparation for the future subpage perfect compression support, we need to change the compression routine to properly handle a subpage range. This patch would prepare both zlib and zstd to only read the subpage range for compression. Lzo is already doing subpage aware read, as lzo's on-disk format is already sectorsize dependent. Signed-off-by: Qu Wenruo <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 9ca0e58 commit fd1e75d

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

fs/btrfs/compression.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ static inline unsigned int btrfs_compress_level(unsigned int type_level)
8282
return ((type_level & 0xF0) >> 4);
8383
}
8484

85+
/* @range_end must be exclusive. */
86+
static inline u32 btrfs_calc_input_length(u64 range_end, u64 cur)
87+
{
88+
u64 page_end = round_down(cur, PAGE_SIZE) + PAGE_SIZE;
89+
90+
return min(range_end, page_end) - cur;
91+
}
92+
8593
int __init btrfs_init_compress(void);
8694
void __cold btrfs_exit_compress(void);
8795

fs/btrfs/zlib.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <linux/refcount.h>
2121
#include "btrfs_inode.h"
2222
#include "compression.h"
23+
#include "fs.h"
24+
#include "subpage.h"
2325

2426
/* workspace buffer size for s390 zlib hardware support */
2527
#define ZLIB_DFLTCC_BUF_SIZE (4 * PAGE_SIZE)
@@ -108,6 +110,7 @@ int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
108110
unsigned long len = *total_out;
109111
unsigned long nr_dest_folios = *out_folios;
110112
const unsigned long max_out = nr_dest_folios * PAGE_SIZE;
113+
const u64 orig_end = start + len;
111114

112115
*out_folios = 0;
113116
*total_out = 0;
@@ -153,6 +156,10 @@ int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
153156
if (in_buf_folios > 1) {
154157
int i;
155158

159+
/* S390 hardware acceleration path, not subpage. */
160+
ASSERT(!btrfs_is_subpage(
161+
inode_to_fs_info(mapping->host),
162+
mapping));
156163
for (i = 0; i < in_buf_folios; i++) {
157164
if (data_in) {
158165
kunmap_local(data_in);
@@ -167,9 +174,14 @@ int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
167174
copy_page(workspace->buf + i * PAGE_SIZE,
168175
data_in);
169176
start += PAGE_SIZE;
177+
workspace->strm.avail_in =
178+
(in_buf_folios << PAGE_SHIFT);
170179
}
171180
workspace->strm.next_in = workspace->buf;
172181
} else {
182+
unsigned int pg_off;
183+
unsigned int cur_len;
184+
173185
if (data_in) {
174186
kunmap_local(data_in);
175187
folio_put(in_folio);
@@ -179,12 +191,13 @@ int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
179191
start, &in_folio);
180192
if (ret < 0)
181193
goto out;
182-
data_in = kmap_local_folio(in_folio, 0);
194+
pg_off = offset_in_page(start);
195+
cur_len = btrfs_calc_input_length(orig_end, start);
196+
data_in = kmap_local_folio(in_folio, pg_off);
183197
start += PAGE_SIZE;
184198
workspace->strm.next_in = data_in;
199+
workspace->strm.avail_in = cur_len;
185200
}
186-
workspace->strm.avail_in = min(bytes_left,
187-
(unsigned long) workspace->buf_size);
188201
}
189202

190203
ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH);

fs/btrfs/zstd.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,10 @@ int zstd_compress_folios(struct list_head *ws, struct address_space *mapping,
389389
unsigned long tot_out = 0;
390390
unsigned long len = *total_out;
391391
const unsigned long nr_dest_folios = *out_folios;
392+
const u64 orig_end = start + len;
392393
unsigned long max_out = nr_dest_folios * PAGE_SIZE;
394+
unsigned int pg_off;
395+
unsigned int cur_len;
393396
zstd_parameters params = zstd_get_btrfs_parameters(workspace->req_level,
394397
len);
395398

@@ -415,9 +418,11 @@ int zstd_compress_folios(struct list_head *ws, struct address_space *mapping,
415418
ret = btrfs_compress_filemap_get_folio(mapping, start, &in_folio);
416419
if (ret < 0)
417420
goto out;
418-
workspace->in_buf.src = kmap_local_folio(in_folio, 0);
421+
pg_off = offset_in_page(start);
422+
cur_len = btrfs_calc_input_length(orig_end, start);
423+
workspace->in_buf.src = kmap_local_folio(in_folio, pg_off);
419424
workspace->in_buf.pos = 0;
420-
workspace->in_buf.size = min_t(size_t, len, PAGE_SIZE);
425+
workspace->in_buf.size = cur_len;
421426

422427
/* Allocate and map in the output buffer */
423428
out_folio = btrfs_alloc_compr_folio();
@@ -494,14 +499,16 @@ int zstd_compress_folios(struct list_head *ws, struct address_space *mapping,
494499
kunmap_local(workspace->in_buf.src);
495500
workspace->in_buf.src = NULL;
496501
folio_put(in_folio);
497-
start += PAGE_SIZE;
498-
len -= PAGE_SIZE;
502+
start += cur_len;
503+
len -= cur_len;
499504
ret = btrfs_compress_filemap_get_folio(mapping, start, &in_folio);
500505
if (ret < 0)
501506
goto out;
502-
workspace->in_buf.src = kmap_local_folio(in_folio, 0);
507+
pg_off = offset_in_page(start);
508+
cur_len = btrfs_calc_input_length(orig_end, start);
509+
workspace->in_buf.src = kmap_local_folio(in_folio, pg_off);
503510
workspace->in_buf.pos = 0;
504-
workspace->in_buf.size = min_t(size_t, len, PAGE_SIZE);
511+
workspace->in_buf.size = cur_len;
505512
}
506513
}
507514
while (1) {

0 commit comments

Comments
 (0)