ntfs: skip reads for full compression unit overwrites

ntfs_compress_write() reads every page in a compression unit before copying
new data into it. The read is unnecessary when an aligned write replaces
every byte covered by the page-cache folios.

Detect full page-aligned compression unit overwrites and grab locked cache
folios without reading them. Keep the read-modify-write path for partial
units and units that cover only part of a large page.

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:46:33 +09:00
parent a8a4681f2b
commit 5b676a77f3

View File

@ -1501,6 +1501,7 @@ int ntfs_compress_write(struct ntfs_inode *ni, loff_t pos, size_t count,
pgoff_t index;
size_t copied, bytes;
unsigned int page_offset;
bool full_cb;
int off;
off = pos & (cb_size - 1);
@ -1512,6 +1513,8 @@ int ntfs_compress_write(struct ntfs_inode *ni, loff_t pos, size_t count,
page_offset = offset_in_page(cb_off);
pages_per_cb = DIV_ROUND_UP(page_offset + cb_size, PAGE_SIZE);
index = cb_off >> PAGE_SHIFT;
full_cb = !off && bytes == cb_size && !page_offset &&
!(cb_size & (PAGE_SIZE - 1));
if (unlikely(fault_in_iov_iter_readable(from, bytes))) {
err = -EFAULT;
@ -1519,7 +1522,10 @@ int ntfs_compress_write(struct ntfs_inode *ni, loff_t pos, size_t count,
}
for (i = 0; i < pages_per_cb; i++) {
folio = read_mapping_folio(mapping, index + i, NULL);
if (full_cb)
folio = filemap_grab_folio(mapping, index + i);
else
folio = read_mapping_folio(mapping, index + i, NULL);
if (IS_ERR(folio)) {
for (ip = 0; ip < i; ip++) {
folio_unlock(page_folio(pages[ip]));
@ -1529,7 +1535,8 @@ int ntfs_compress_write(struct ntfs_inode *ni, loff_t pos, size_t count,
goto out;
}
folio_lock(folio);
if (!full_cb)
folio_lock(folio);
pages[i] = folio_page(folio, 0);
}