summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Sorenson <sorenson@redhat.com>2026-08-26 20:57:38 -0500
committerPaulo Alcantara <pc@manguebit.org>2026-08-30 14:05:38 -0300
commitfe39cd9d48f2346605f3746e0cc19e89d5f373eb (patch)
tree7d28c79d4aca0bc49afec35daede293e5c415118
parent1dac61e2c29d1a71784604b48cf3b1234a65ec29 (diff)
downloadlinux-next-fe39cd9d48f2346605f3746e0cc19e89d5f373eb.tar.gz
linux-next-fe39cd9d48f2346605f3746e0cc19e89d5f373eb.zip
cifs: don't update i_size in cifs_do_truncate without a cached handle
If find_writable_file() returns null, cifs_file_flush will return 0 without issuing set_file_size, and the outer 'if (!rc)' block will set i_size to 0 before telling the server to truncate. If the cifs_open() then fails, the inode will have size 0, while the server file is unchanged. Move the netfs_resize_file() and cifs_setsize() into the 'if (cfile)', so they only run after a successful set_file_size. In the no-handle else branch, evict stale pages with truncate_inode_pages before the O_TRUNC open to dispose of old cache pages, and let the open response set the i_size. Fixes: 110fee6b9bb5 ("smb: client: fix missing timestamp updates with O_TRUNC") Cc: stable@vger.kernel.org Signed-off-by: Frank Sorenson <sorenson@redhat.com> Acked-by: David Howells <dhowells@redhat.com> Signed-off-by: Paulo Alcantara <pc@manguebit.org>
-rw-r--r--fs/smb/client/file.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index 389083f9ce00..100acc76e9be 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -1012,10 +1012,26 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)
server = tcon->ses->server;
rc = server->ops->set_file_size(xid, tcon,
cfile, 0, false);
- }
- if (!rc) {
- netfs_resize_file(&cinode->netfs, 0, true);
- cifs_setsize(inode, 0);
+ if (!rc) {
+ inode_lock(inode);
+ filemap_invalidate_lock(inode->i_mapping);
+ netfs_resize_file(&cinode->netfs, 0, true);
+ cifs_setsize(inode, 0);
+ filemap_invalidate_unlock(inode->i_mapping);
+ inode_unlock(inode);
+ cifs_invalidate_cache(inode, 0);
+ }
+ } else {
+ /*
+ * No cached handle; evict stale pages so they can't
+ * be served after the file is later extended; let
+ * the server's O_TRUNC open response set the i_size
+ */
+ inode_lock(inode);
+ filemap_invalidate_lock(inode->i_mapping);
+ truncate_inode_pages(inode->i_mapping, 0);
+ filemap_invalidate_unlock(inode->i_mapping);
+ inode_unlock(inode);
cifs_invalidate_cache(inode, 0);
}
}