diff options
| author | Namjae Jeon <linkinjeon@kernel.org> | 2026-07-21 08:44:57 +0900 |
|---|---|---|
| committer | Namjae Jeon <linkinjeon@kernel.org> | 2026-07-27 18:11:29 +0900 |
| commit | a8af29cd136fc7319dc601abc03bd29abf9844d9 (patch) | |
| tree | 3f775c45f27d0cf4aa097d2e3246f2428f837222 | |
| parent | 306f066a64d44b59e1a0ed11193b8ba14571b5b2 (diff) | |
| download | linux-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.c | 28 |
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; |
