ntfs: reuse the compression context during writes

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.

Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
Namjae Jeon 2026-07-21 08:44:57 +09:00
parent b54559689a
commit 33200693eb

View File

@ -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;