summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamjae Jeon <linkinjeon@kernel.org>2026-07-21 08:44:57 +0900
committerNamjae Jeon <linkinjeon@kernel.org>2026-07-27 18:11:29 +0900
commita8af29cd136fc7319dc601abc03bd29abf9844d9 (patch)
tree3f775c45f27d0cf4aa097d2e3246f2428f837222
parent306f066a64d44b59e1a0ed11193b8ba14571b5b2 (diff)
downloadlinux-next-a8af29cd136fc7319dc601abc03bd29abf9844d9.tar.gz
linux-next-a8af29cd136fc7319dc601abc03bd29abf9844d9.zip
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>
-rw-r--r--fs/ntfs/compress.c28
1 files 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 @@ out:
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 @@ release_pages:
}
out:
+ kvfree(ctx);
kfree(pages);
if (err < 0)
written = err;