FAILED: patch "[PATCH] smb: client: clear post-EOF pagecache when extending a file" failed to apply to 7.2-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 7.2-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-7.2.y
git checkout FETCH_HEAD
git cherry-pick -x 35024595f641e790e24609f3f046e1667e3b280a
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026100502-cognitive-zipping-a488@gregkh' --subject-prefix 'PATCH 7.2.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 35024595f641e790e24609f3f046e1667e3b280a Mon Sep 17 00:00:00 2001
From: Paulo Alcantara <[email protected]>
Date: Sun, 20 Sep 2026 15:05:44 -0300
Subject: [PATCH] smb: client: clear post-EOF pagecache when extending a file
via truncate
cifs_setsize() relied on pagecache_isize_extended() to zero the tail of the folio straddling the old EOF, but that helper is a no-op on CIFS (i_blkbits is 14), so data dirtied past EOF through an mmap survived and became visible once the file was extended.
Use netfs_clear_stale_post_isize() instead, called after i_size is updated since cifs_setsize() callers hold i_rwsem exclusively for the whole resize. truncate_pagecache() is then called as in truncate_setsize(): a no-op on extend, and it drops the pagecache beyond the new EOF on shrink.
Also thread old_size as an explicit parameter through cifs_setsize() and cifs_resize_file_locked(), captured by each caller before its own resize RPC. This closes a race where a concurrent stat() could adopt the RPC's already-updated server size via is_size_safe_to_change() before cifs_setsize() reads old_size itself.
fs/smb/client/cifsfs.h +3 -2
@@ -146,8 +146,9 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, struct file *src_file, unsigned int flags);long cifs_ioctl (struct file *filep,unsigned int command,unsigned long arg); -void cifs_setsize (struct inode *inode,loff_t offset); -void cifs_resize_file_locked (struct inode *inode,loff_t offset); +void cifs_setsize (struct inode *inode,loff_t old_size,loff_t offset); +void cifs_resize_file_locked (struct inode *inode,loff_t old_size, +loff_t offset);struct fs_context ;struct smb3_fs_context ;
fs/smb/client/file.c +2 -1
@@ -1017,6 +1017,7 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)if (!rc) {if (cfile) {struct netfs_inode *ictx =netfs_inode (inode); +loff_t old_size =i_size_read (inode); tcon =tlink_tcon (cfile->tlink); server = tcon->ses->server;
@@ -1025,7 +1026,7 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry) cfile, 0, false);if (!rc) {netfs_resize_file (&cinode->netfs,0 , true); -cifs_setsize (inode,0 ); +cifs_setsize (inode, old_size,0 );cifs_invalidate_cache (inode,0 ); }netfs_wb_end (ictx);
fs/smb/client/inode.c +14 -8
@@ -3053,15 +3053,12 @@ int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,return -EOPNOTSUPP ; } -void cifs_setsize (struct inode *inode,loff_t offset) +void cifs_setsize (struct inode *inode,loff_t old_size,loff_t offset) { -loff_t old_size;u64 blocks =CIFS_INO_BLOCKS (offset);spin_lock (&inode->i_lock); - old_size =i_size_read (inode);i_size_write (inode, offset); -/* * Extending EOF does not allocate the intervening range. Only clamp * i_blocks on shrink; allocation growth comes from writes or from the
@@ -3071,20 +3068,28 @@ void cifs_setsize(struct inode *inode, loff_t offset) inode->i_blocks = blocks;spin_unlock (&inode->i_lock);inode_set_mtime_to_ts (inode,inode_set_ctime_current (inode)); + +/* +* Zero the tail of the folio straddling the old EOF so data dirtied +* past EOF through an mmap isn't exposed. truncate_pagecache() then +* drops any pagecache beyond the new EOF, as in truncate_setsize(). +*/ if (offset > old_size) -pagecache_isize_extended (inode, old_size, offset); +netfs_clear_stale_post_isize (inode, old_size, offset); +truncate_pagecache (inode, offset);netfs_wait_for_outstanding_io (inode); } -void cifs_resize_file_locked (struct inode *inode,loff_t offset) +void cifs_resize_file_locked (struct inode *inode,loff_t old_size, +loff_t offset) {struct fscache_cookie *cookie =cifs_inode_cookie (inode);lockdep_assert_held_write (&inode->i_rwsem);netfs_resize_file (netfs_inode (inode), offset, true); -cifs_setsize (inode, offset); +cifs_setsize (inode, old_size, offset);if (!cookie)return ;
@@ -3101,6 +3106,7 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,struct inode *inode =d_inode (dentry);struct cifs_sb_info *cifs_sb =CIFS_SB (inode->i_sb);struct cifsInodeInfo *cifsInode =CIFS_I (inode); +loff_t old_size =i_size_read (inode);struct tcon_link *tlink =NULL ;struct cifs_tcon *tcon =NULL ;struct TCP_Server_Info *server;
@@ -3159,7 +3165,7 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry, set_size_out:if (rc ==0 ) -cifs_resize_file_locked (inode, size); +cifs_resize_file_locked (inode, old_size, size);return rc; }
fs/smb/client/smb2ops.c +6 -4
@@ -2287,6 +2287,7 @@ smb2_duplicate_extents(const unsigned int xid,struct duplicate_extents_to_file dup_ext_buf;struct timespec64 ts;struct cifs_tcon *tcon =tlink_tcon (trgtfile->tlink); +loff_t old_size;u64 asize;/* server fileays advertise duplicate extent support with this flag */
@@ -2305,11 +2306,12 @@ smb2_duplicate_extents(const unsigned int xid, trgtfile->fid.volatile_fid, tcon->tid, tcon->ses->Suid, src_off, dest_off, len); inode =d_inode (trgtfile->dentry); -if (i_size_read (inode) < dest_off + len) { + old_size =i_size_read (inode); +if (old_size < dest_off + len) { rc =smb2_set_file_size (xid, tcon, trgtfile, dest_off + len, false);if (rc) goto duplicate_extents_out; -cifs_resize_file_locked (inode, dest_off + len); +cifs_resize_file_locked (inode, old_size, dest_off + len); } rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, trgtfile->fid.volatile_fid,
@@ -3883,7 +3885,7 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, } new_eof = off + len; -cifs_resize_file_locked (inode, new_eof); +cifs_resize_file_locked (inode, old_eof, new_eof); qrc = SMB2_query_info(xid, tcon, cfile->fid.persistent_fid,
@@ -3931,7 +3933,7 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,if (rc) goto out; -cifs_resize_file_locked (inode, new_eof); +cifs_resize_file_locked (inode, old_eof, new_eof); qrc = SMB2_query_info(xid, tcon, cfile->fid.persistent_fid,