mirror of
https://github.com/torvalds/linux.git
synced 2026-11-10 17:11:02 +01:00
ntfs: clear stale pagecache on initialized-size extension
iomap_zero_range() skips holes, so EOF-polluted cache data can survive
gap zeroing. Discard the uninitialized cache range before advancing
initialized_size so later reads cannot expose stale bytes.
Perform the cleanup in ntfs_extend_initialized_size() so both file writes
and shared writable mmap preparation use it. Hold the invalidate lock
while reading initialized_size, clearing the cache, zeroing the gap, and
updating the attribute. Release the lock on every exit path.
Fixes: af0db57d42 ("ntfs: update inode operations")
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
3e38885ff6
commit
58442927b7
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include "lcnalloc.h"
|
||||
#include "time.h"
|
||||
|
|
@ -2484,38 +2485,50 @@ int ntfs_extend_initialized_size(struct inode *vi, const loff_t offset,
|
|||
const loff_t new_size)
|
||||
{
|
||||
struct ntfs_inode *ni = NTFS_I(vi);
|
||||
loff_t old_init_size;
|
||||
loff_t old_init_size, clear_size;
|
||||
unsigned long flags;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
if (!NInoNonResident(ni))
|
||||
return -EINVAL;
|
||||
|
||||
filemap_invalidate_lock(vi->i_mapping);
|
||||
read_lock_irqsave(&ni->size_lock, flags);
|
||||
old_init_size = ni->initialized_size;
|
||||
read_unlock_irqrestore(&ni->size_lock, flags);
|
||||
|
||||
if (!NInoNonResident(ni))
|
||||
return -EINVAL;
|
||||
if (old_init_size >= new_size)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
err = ntfs_attr_map_whole_runlist(ni);
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
|
||||
if (!NInoCompressed(ni) && old_init_size < offset) {
|
||||
err = iomap_zero_range(vi, old_init_size,
|
||||
offset - old_init_size,
|
||||
NULL, &ntfs_seek_iomap_ops,
|
||||
&ntfs_iomap_folio_ops, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
if (!NInoCompressed(ni)) {
|
||||
/*
|
||||
* Zeroing skips holes, so discard cached uninitialized bytes
|
||||
* before making them visible to writes or shared mappings.
|
||||
*/
|
||||
clear_size = max_t(loff_t, i_size_read(vi), new_size);
|
||||
truncate_pagecache_range(vi, old_init_size, clear_size - 1);
|
||||
|
||||
if (old_init_size < offset) {
|
||||
err = iomap_zero_range(vi, old_init_size,
|
||||
offset - old_init_size,
|
||||
NULL, &ntfs_seek_iomap_ops,
|
||||
&ntfs_iomap_folio_ops, NULL);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mutex_lock(&ni->mrec_lock);
|
||||
err = ntfs_attr_set_initialized_size(ni, new_size);
|
||||
mutex_unlock(&ni->mrec_lock);
|
||||
if (err)
|
||||
truncate_setsize(vi, old_init_size);
|
||||
out:
|
||||
filemap_invalidate_unlock(vi->i_mapping);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user