Skip to content

Commit e1bc83f

Browse files
adam900710kdave
authored andcommitted
btrfs: get rid of compressed_folios[] usage for encoded writes
Currently only encoded writes utilized btrfs_submit_compressed_write(), which utilized compressed_bio::compressed_folios[] array. Change the only call site to call the new helper, btrfs_alloc_compressed_write(), to allocate a compressed bio, then queue needed folios into that bio, and finally call btrfs_submit_compressed_write() to submit the compressed bio. This change has one hidden benefit, previously we used btrfs_alloc_folio_array() for the folios of btrfs_submit_compressed_read(), which doesn't utilize the compression page pool for bs == ps cases. Now we call btrfs_alloc_compr_folio() which will benefit from the page pool. The other obvious benefit is that we no longer need to allocate an array to hold all those folios, thus one less error path. Reviewed-by: Boris Burkov <boris@bur.io> 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 dafcfa1 commit e1bc83f

3 files changed

Lines changed: 57 additions & 62 deletions

File tree

fs/btrfs/compression.c

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -304,25 +304,6 @@ static void end_bbio_compressed_write(struct btrfs_bio *bbio)
304304
bio_put(&cb->bbio.bio);
305305
}
306306

307-
static void btrfs_add_compressed_bio_folios(struct compressed_bio *cb)
308-
{
309-
struct bio *bio = &cb->bbio.bio;
310-
u32 offset = 0;
311-
unsigned int findex = 0;
312-
313-
while (offset < cb->compressed_len) {
314-
struct folio *folio = cb->compressed_folios[findex];
315-
u32 len = min_t(u32, cb->compressed_len - offset, folio_size(folio));
316-
int ret;
317-
318-
/* Maximum compressed extent is smaller than bio size limit. */
319-
ret = bio_add_folio(bio, folio, len, 0);
320-
ASSERT(ret);
321-
offset += len;
322-
findex++;
323-
}
324-
}
325-
326307
/*
327308
* worker function to build and submit bios for previously compressed pages.
328309
* The corresponding pages in the inode should be marked for writeback
@@ -333,34 +314,43 @@ static void btrfs_add_compressed_bio_folios(struct compressed_bio *cb)
333314
* the end io hooks.
334315
*/
335316
void btrfs_submit_compressed_write(struct btrfs_ordered_extent *ordered,
336-
struct folio **compressed_folios,
337-
unsigned int nr_folios,
338-
blk_opf_t write_flags,
339-
bool writeback)
317+
struct compressed_bio *cb)
340318
{
341319
struct btrfs_inode *inode = ordered->inode;
342320
struct btrfs_fs_info *fs_info = inode->root->fs_info;
343-
struct compressed_bio *cb;
344321

345322
ASSERT(IS_ALIGNED(ordered->file_offset, fs_info->sectorsize));
346323
ASSERT(IS_ALIGNED(ordered->num_bytes, fs_info->sectorsize));
324+
ASSERT(cb->writeback);
347325

348-
cb = alloc_compressed_bio(inode, ordered->file_offset,
349-
REQ_OP_WRITE | write_flags,
350-
end_bbio_compressed_write);
351326
cb->start = ordered->file_offset;
352327
cb->len = ordered->num_bytes;
353-
cb->compressed_folios = compressed_folios;
354328
cb->compressed_len = ordered->disk_num_bytes;
355-
cb->writeback = writeback;
356-
cb->nr_folios = nr_folios;
357329
cb->bbio.bio.bi_iter.bi_sector = ordered->disk_bytenr >> SECTOR_SHIFT;
358330
cb->bbio.ordered = ordered;
359-
btrfs_add_compressed_bio_folios(cb);
360331

361332
btrfs_submit_bbio(&cb->bbio, 0);
362333
}
363334

335+
/*
336+
* Allocate a compressed write bio for @inode file offset @start length @len.
337+
*
338+
* The caller still needs to properly queue all folios and populate involved
339+
* members.
340+
*/
341+
struct compressed_bio *btrfs_alloc_compressed_write(struct btrfs_inode *inode,
342+
u64 start, u64 len)
343+
{
344+
struct compressed_bio *cb;
345+
346+
cb = alloc_compressed_bio(inode, start, REQ_OP_WRITE, end_bbio_compressed_write);
347+
cb->start = start;
348+
cb->len = len;
349+
cb->writeback = true;
350+
351+
return cb;
352+
}
353+
364354
/*
365355
* Add extra pages in the same compressed file extent so that we don't need to
366356
* re-read the same extent again and again.

fs/btrfs/compression.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ int btrfs_decompress(int type, const u8 *data_in, struct folio *dest_folio,
9696
int btrfs_decompress_buf2page(const char *buf, u32 buf_len,
9797
struct compressed_bio *cb, u32 decompressed);
9898

99+
struct compressed_bio *btrfs_alloc_compressed_write(struct btrfs_inode *inode,
100+
u64 start, u64 len);
99101
void btrfs_submit_compressed_write(struct btrfs_ordered_extent *ordered,
100-
struct folio **compressed_folios,
101-
unsigned int nr_folios, blk_opf_t write_flags,
102-
bool writeback);
102+
struct compressed_bio *cb);
103103
void btrfs_submit_compressed_read(struct btrfs_bio *bbio);
104104

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

fs/btrfs/inode.c

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9828,12 +9828,12 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
98289828
struct extent_state *cached_state = NULL;
98299829
struct btrfs_ordered_extent *ordered;
98309830
struct btrfs_file_extent file_extent;
9831+
struct compressed_bio *cb = NULL;
98319832
int compression;
98329833
size_t orig_count;
9834+
const u32 min_folio_size = btrfs_min_folio_size(fs_info);
98339835
u64 start, end;
98349836
u64 num_bytes, ram_bytes, disk_num_bytes;
9835-
unsigned long nr_folios, i;
9836-
struct folio **folios;
98379837
struct btrfs_key ins;
98389838
bool extent_reserved = false;
98399839
struct extent_map *em;
@@ -9922,39 +9922,46 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
99229922
* isn't.
99239923
*/
99249924
disk_num_bytes = ALIGN(orig_count, fs_info->sectorsize);
9925-
nr_folios = DIV_ROUND_UP(disk_num_bytes, PAGE_SIZE);
9926-
folios = kvcalloc(nr_folios, sizeof(struct folio *), GFP_KERNEL_ACCOUNT);
9927-
if (!folios)
9928-
return -ENOMEM;
9929-
for (i = 0; i < nr_folios; i++) {
9930-
size_t bytes = min_t(size_t, PAGE_SIZE, iov_iter_count(from));
9925+
9926+
cb = btrfs_alloc_compressed_write(inode, start, num_bytes);
9927+
for (int i = 0; i * min_folio_size < disk_num_bytes; i++) {
9928+
struct folio *folio;
9929+
size_t bytes = min(min_folio_size, iov_iter_count(from));
99319930
char *kaddr;
99329931

9933-
folios[i] = folio_alloc(GFP_KERNEL_ACCOUNT, 0);
9934-
if (!folios[i]) {
9932+
folio = btrfs_alloc_compr_folio(fs_info);
9933+
if (!folio) {
99359934
ret = -ENOMEM;
9936-
goto out_folios;
9935+
goto out_cb;
99379936
}
9938-
kaddr = kmap_local_folio(folios[i], 0);
9939-
if (copy_from_iter(kaddr, bytes, from) != bytes) {
9940-
kunmap_local(kaddr);
9937+
kaddr = kmap_local_folio(folio, 0);
9938+
ret = copy_from_iter(kaddr, bytes, from);
9939+
kunmap_local(kaddr);
9940+
if (ret != bytes) {
9941+
folio_put(folio);
99419942
ret = -EFAULT;
9942-
goto out_folios;
9943+
goto out_cb;
9944+
}
9945+
if (bytes < min_folio_size)
9946+
folio_zero_range(folio, bytes, min_folio_size - bytes);
9947+
ret = bio_add_folio(&cb->bbio.bio, folio, folio_size(folio), 0);
9948+
if (unlikely(!ret)) {
9949+
folio_put(folio);
9950+
ret = -EINVAL;
9951+
goto out_cb;
99439952
}
9944-
if (bytes < PAGE_SIZE)
9945-
memset(kaddr + bytes, 0, PAGE_SIZE - bytes);
9946-
kunmap_local(kaddr);
99479953
}
9954+
ASSERT(cb->bbio.bio.bi_iter.bi_size == disk_num_bytes);
99489955

99499956
for (;;) {
99509957
ret = btrfs_wait_ordered_range(inode, start, num_bytes);
99519958
if (ret)
9952-
goto out_folios;
9959+
goto out_cb;
99539960
ret = invalidate_inode_pages2_range(inode->vfs_inode.i_mapping,
99549961
start >> PAGE_SHIFT,
99559962
end >> PAGE_SHIFT);
99569963
if (ret)
9957-
goto out_folios;
9964+
goto out_cb;
99589965
btrfs_lock_extent(io_tree, start, end, &cached_state);
99599966
ordered = btrfs_lookup_ordered_range(inode, start, num_bytes);
99609967
if (!ordered &&
@@ -9986,7 +9993,8 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
99869993
encoded->unencoded_offset == 0 &&
99879994
can_cow_file_range_inline(inode, start, encoded->len, orig_count)) {
99889995
ret = __cow_file_range_inline(inode, encoded->len,
9989-
orig_count, compression, folios[0],
9996+
orig_count, compression,
9997+
bio_first_folio_all(&cb->bbio.bio),
99909998
true);
99919999
if (ret <= 0) {
999210000
if (ret == 0)
@@ -10031,7 +10039,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
1003110039

1003210040
btrfs_delalloc_release_extents(inode, num_bytes);
1003310041

10034-
btrfs_submit_compressed_write(ordered, folios, nr_folios, 0, false);
10042+
btrfs_submit_compressed_write(ordered, cb);
1003510043
ret = orig_count;
1003610044
goto out;
1003710045

@@ -10053,12 +10061,9 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
1005310061
btrfs_free_reserved_data_space_noquota(inode, disk_num_bytes);
1005410062
out_unlock:
1005510063
btrfs_unlock_extent(io_tree, start, end, &cached_state);
10056-
out_folios:
10057-
for (i = 0; i < nr_folios; i++) {
10058-
if (folios[i])
10059-
folio_put(folios[i]);
10060-
}
10061-
kvfree(folios);
10064+
out_cb:
10065+
if (cb)
10066+
cleanup_compressed_bio(cb);
1006210067
out:
1006310068
if (ret >= 0)
1006410069
iocb->ki_pos += encoded->len;

0 commit comments

Comments
 (0)