]> Git Repo - linux.git/commitdiff
btrfs: make compression path to be subpage compatible
authorQu Wenruo <[email protected]>
Wed, 29 May 2024 07:33:47 +0000 (17:03 +0930)
committerDavid Sterba <[email protected]>
Tue, 10 Sep 2024 14:51:20 +0000 (16:51 +0200)
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]>
fs/btrfs/compression.h
fs/btrfs/zlib.c
fs/btrfs/zstd.c

index cfdc643191862ab6f919cc6bc6c9348408af7919..5d01f092ae13f2350e38b6770474bcd3561ad1e0 100644 (file)
@@ -82,6 +82,14 @@ static inline unsigned int btrfs_compress_level(unsigned int type_level)
        return ((type_level & 0xF0) >> 4);
 }
 
+/* @range_end must be exclusive. */
+static inline u32 btrfs_calc_input_length(u64 range_end, u64 cur)
+{
+       u64 page_end = round_down(cur, PAGE_SIZE) + PAGE_SIZE;
+
+       return min(range_end, page_end) - cur;
+}
+
 int __init btrfs_init_compress(void);
 void __cold btrfs_exit_compress(void);
 
index 30971dd741e2df7c6eff8c38f3bd0e27438af6cd..ee80d064b9549c61d1472ea0f3211429062725e7 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/refcount.h>
 #include "btrfs_inode.h"
 #include "compression.h"
+#include "fs.h"
+#include "subpage.h"
 
 /* workspace buffer size for s390 zlib hardware support */
 #define ZLIB_DFLTCC_BUF_SIZE    (4 * PAGE_SIZE)
@@ -108,6 +110,7 @@ int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
        unsigned long len = *total_out;
        unsigned long nr_dest_folios = *out_folios;
        const unsigned long max_out = nr_dest_folios * PAGE_SIZE;
+       const u64 orig_end = start + len;
 
        *out_folios = 0;
        *total_out = 0;
@@ -153,6 +156,10 @@ int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
                        if (in_buf_folios > 1) {
                                int i;
 
+                               /* S390 hardware acceleration path, not subpage. */
+                               ASSERT(!btrfs_is_subpage(
+                                               inode_to_fs_info(mapping->host),
+                                               mapping));
                                for (i = 0; i < in_buf_folios; i++) {
                                        if (data_in) {
                                                kunmap_local(data_in);
@@ -167,9 +174,14 @@ int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
                                        copy_page(workspace->buf + i * PAGE_SIZE,
                                                  data_in);
                                        start += PAGE_SIZE;
+                                       workspace->strm.avail_in =
+                                               (in_buf_folios << PAGE_SHIFT);
                                }
                                workspace->strm.next_in = workspace->buf;
                        } else {
+                               unsigned int pg_off;
+                               unsigned int cur_len;
+
                                if (data_in) {
                                        kunmap_local(data_in);
                                        folio_put(in_folio);
@@ -179,12 +191,13 @@ int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
                                                start, &in_folio);
                                if (ret < 0)
                                        goto out;
-                               data_in = kmap_local_folio(in_folio, 0);
+                               pg_off = offset_in_page(start);
+                               cur_len = btrfs_calc_input_length(orig_end, start);
+                               data_in = kmap_local_folio(in_folio, pg_off);
                                start += PAGE_SIZE;
                                workspace->strm.next_in = data_in;
+                               workspace->strm.avail_in = cur_len;
                        }
-                       workspace->strm.avail_in = min(bytes_left,
-                                                      (unsigned long) workspace->buf_size);
                }
 
                ret = zlib_deflate(&workspace->strm, Z_SYNC_FLUSH);
index 2a079561b2b10b95d84dc2f31c2096ce6c11ebe7..05cf7cebc17c85180c6c210c8d055834eae6da05 100644 (file)
@@ -389,7 +389,10 @@ int zstd_compress_folios(struct list_head *ws, struct address_space *mapping,
        unsigned long tot_out = 0;
        unsigned long len = *total_out;
        const unsigned long nr_dest_folios = *out_folios;
+       const u64 orig_end = start + len;
        unsigned long max_out = nr_dest_folios * PAGE_SIZE;
+       unsigned int pg_off;
+       unsigned int cur_len;
        zstd_parameters params = zstd_get_btrfs_parameters(workspace->req_level,
                                                           len);
 
@@ -415,9 +418,11 @@ int zstd_compress_folios(struct list_head *ws, struct address_space *mapping,
        ret = btrfs_compress_filemap_get_folio(mapping, start, &in_folio);
        if (ret < 0)
                goto out;
-       workspace->in_buf.src = kmap_local_folio(in_folio, 0);
+       pg_off = offset_in_page(start);
+       cur_len = btrfs_calc_input_length(orig_end, start);
+       workspace->in_buf.src = kmap_local_folio(in_folio, pg_off);
        workspace->in_buf.pos = 0;
-       workspace->in_buf.size = min_t(size_t, len, PAGE_SIZE);
+       workspace->in_buf.size = cur_len;
 
        /* Allocate and map in the output buffer */
        out_folio = btrfs_alloc_compr_folio();
@@ -494,14 +499,16 @@ int zstd_compress_folios(struct list_head *ws, struct address_space *mapping,
                        kunmap_local(workspace->in_buf.src);
                        workspace->in_buf.src = NULL;
                        folio_put(in_folio);
-                       start += PAGE_SIZE;
-                       len -= PAGE_SIZE;
+                       start += cur_len;
+                       len -= cur_len;
                        ret = btrfs_compress_filemap_get_folio(mapping, start, &in_folio);
                        if (ret < 0)
                                goto out;
-                       workspace->in_buf.src = kmap_local_folio(in_folio, 0);
+                       pg_off = offset_in_page(start);
+                       cur_len = btrfs_calc_input_length(orig_end, start);
+                       workspace->in_buf.src = kmap_local_folio(in_folio, pg_off);
                        workspace->in_buf.pos = 0;
-                       workspace->in_buf.size = min_t(size_t, len, PAGE_SIZE);
+                       workspace->in_buf.size = cur_len;
                }
        }
        while (1) {
This page took 0.062185 seconds and 4 git commands to generate.