[PATCH 06/11] ntfs: reuse the compression context during writes
Namjae Jeon <[email protected]> Tue, 21 Jul 2026 18:54:26 +0900
| Newsgroups | dev.linux.lists.ntfs |
|---|---|
| Message-ID | <[email protected]> |
ntfs_compress_block() allocates and initializes a roughly 40 KiB match finder context for every 4 KiB sub-block. A 64 KiB compression unit thus performs sixteen large allocations even though the calls are serialized. Allocate one context for the complete write request and reset its hash chains for each sub-block as before. Signed-off-by: Namjae Jeon <[email protected]> --- fs/ntfs/compress.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index a993cba3b961..f073a53f6136 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c @@ -1072,10 +1072,9 @@ static void ntfs_skip_position(struct compress_context *pctx, const int i) * header (minimal size is 2, maximum size is 4098) * A negative error code if an error has been met. */ -static int ntfs_compress_block(const char *inbuf, const int bufsize, - char *outbuf) +static int ntfs_compress_block(struct compress_context *pctx, + const char *inbuf, const int bufsize, char *outbuf) { - struct compress_context *pctx; int i; /* current position */ int j; /* end of best match from current position */ int k; /* end of best match from next position */ @@ -1090,10 +1089,6 @@ static int ntfs_compress_block(const char *inbuf, const int bufsize, int tag; /* current value of tag */ int ntag; /* count of bits still undefined in tag */ - pctx = kvzalloc(sizeof(struct compress_context), GFP_NOFS); - if (!pctx) - return -ENOMEM; - /* * All hash chains start as empty. The special value '-1' indicates the * end of each hash chain. @@ -1249,16 +1244,12 @@ static int ntfs_compress_block(const char *inbuf, const int bufsize, xout = NTFS_SB_SIZE + 2; } - /* - * Free the compression context and return the total number of bytes - * written to 'outbuf'. - */ - kvfree(pctx); return xout; } static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages, - int pages_per_cb, unsigned int page_offset) + int pages_per_cb, unsigned int page_offset, + struct compress_context *ctx) { struct ntfs_volume *vol = ni->vol; char *outbuf = NULL, *pbuf, *inbuf, *in_mapping; @@ -1321,7 +1312,7 @@ static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages, else bsz = insz - p; pbuf = &outbuf[compsz]; - sz = ntfs_compress_block(&inbuf[p], bsz, pbuf); + sz = ntfs_compress_block(ctx, &inbuf[p], bsz, pbuf); if (sz < 0) { err = sz; goto out; @@ -1472,6 +1463,7 @@ static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages, int ntfs_compress_write(struct ntfs_inode *ni, loff_t pos, size_t count, struct iov_iter *from) { + struct compress_context *ctx; struct folio *folio; struct page **pages = NULL, *page; int pages_per_cb; @@ -1486,6 +1478,11 @@ int ntfs_compress_write(struct ntfs_inode *ni, loff_t pos, size_t count, pages = kmalloc_array(pages_per_cb, sizeof(struct page *), GFP_NOFS); if (!pages) return -ENOMEM; + ctx = kvzalloc_obj(*ctx, GFP_NOFS); + if (!ctx) { + kfree(pages); + return -ENOMEM; + } while (count) { pgoff_t index; @@ -1554,7 +1551,7 @@ int ntfs_compress_write(struct ntfs_inode *ni, loff_t pos, size_t count, goto release_pages; } - err = ntfs_write_cb(ni, pos, pages, pages_per_cb, page_offset); + err = ntfs_write_cb(ni, pos, pages, pages_per_cb, page_offset, ctx); if (!err && pos + copied > ni->initialized_size) { mutex_lock(&ni->mrec_lock); err = ntfs_attr_set_initialized_size(ni, pos + copied); @@ -1584,6 +1581,7 @@ int ntfs_compress_write(struct ntfs_inode *ni, loff_t pos, size_t count, } out: + kvfree(ctx); kfree(pages); if (err < 0) written = err; -- 2.34.1