diff options
| author | Paulo Alcantara <pc@manguebit.org> | 2026-08-28 19:08:09 -0300 |
|---|---|---|
| committer | Paulo Alcantara <pc@manguebit.org> | 2026-08-31 11:49:50 -0300 |
| commit | a8603b52b39f520ea8a34def74c23fba87396d3e (patch) | |
| tree | 5ea7c8fb174a879ab21c69f88bfc9f4bd4e02f0f /include/linux/execmem.h | |
| parent | fe39cd9d48f2346605f3746e0cc19e89d5f373eb (diff) | |
smb: client: fix data corruption with concurrent writes and O_TRUNC
cifs_do_truncate() flushes dirty pages with filemap_write_and_wait()
and truncates the file on the server, but in the old code both
operations ran without holding i_rwsem or invalidate_lock. A
concurrent buffered write via netfs_perform_write() -- which only
needs i_rwsem shared -- could dirty new pages after the flush but
before the local truncation, and those pages would be silently
discarded by cifs_setsize() -> truncate_pagecache().
Fix by acquiring inode_lock (exclusive i_rwsem) and
filemap_invalidate_lock at the top of cifs_do_truncate(), so the
entire flush-truncate-resize sequence is atomic with respect to:
- buffered writes (blocked by exclusive i_rwsem, since
netfs_start_io_write takes i_rwsem shared),
- read page faults (blocked by exclusive invalidate_lock, since
filemap_fault takes it shared),
- writeback collection (blocked by netfs_wb_begin/netfs_wb_end
around the server truncate and local resize, since
netfs_writepages also acquires the wb lock).
Fixes: 110fee6b9bb5 ("smb: client: fix missing timestamp updates with O_TRUNC")
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Cc: Shyam Prasad N <sprasad@microsoft.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Bharath SM <bharathsm@microsoft.com>
Cc: stable@vger.kernel.org
Diffstat (limited to 'include/linux/execmem.h')
0 files changed, 0 insertions, 0 deletions
