Re: [PATCH 1/3] cifs: use cifs_invalidate_cache() in cifs_do_truncate() for O_TRUNC

Huiwen He <[email protected]> Wed, 29 Jul 2026 12:20:04 +0800
Newsgroups org.kernel.vger.linux-cifs,org.kernel.vger.stable
Message-ID <[email protected]>
Hi Frank,

Patch 1 handles the quiescent-cookie case, but the cookie is not
guaranteed to be quiescent here: another open may already keep it
active. In that case, cifs_setsize() may still call
fscache_resize_cookie() without i_rwsem before the invalidation.

Maybe we could keep cifs_setsize() as the basic size/page-cache helper
and add a wrapper for the paths holding i_rwsem, for example:

   /* Caller must hold inode->i_rwsem for write. */
   void cifs_resize_file_locked(struct inode *inode, 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);

   	if (!cookie)
   		return;

   	fscache_use_cookie(cookie, true);
   	fscache_resize_cookie(cookie, offset);
   	cifs_fscache_unuse_inode_cookie(inode, true);
   }

cifs_file_set_size(), smb2_duplicate_extents(), and both
smb3_simple_falloc() branches could use this wrapper, since those paths 
already hold i_rwsem. O_TRUNC could continue to use cifs_setsize()
followed by cifs_invalidate_cache(), without attempting a resize.

Patches 2 and 3 look good to me.

Thanks,

Huiwen


在 2026/7/29 05:14, Frank Sorenson 写道:
> cifs_setsize() now calls fscache_resize_cookie() since commit
> fa724e235cfd ("cifs: add fscache_resize_cookie() to cifs_setsize()").
> However, cifs_do_truncate() is called from cifs_open() before
> fscache_use_cookie() activates the cookie, so the fscache cookie is
> still quiescent at this point.  fscache_begin_operation() requires
> FSCACHE_COOKIE_IS_CACHING to be set and returns failure for a quiescent
> cookie, making fscache_resize_cookie() a null operation in this path.
> 
> The correct fix for this path is cifs_invalidate_cache(), which calls
> fscache_invalidate().  Unlike fscache_resize_cookie(), fscache_invalidate()
> works on quiescent cookies: it unconditionally increments inval_counter
> and sets FSCACHE_COOKIE_NO_DATA_TO_READ, ensuring that stale cached data
> is not served once the cookie is later activated by fscache_use_cookie().
> 
> Truncation to zero leaves no valid cached data, making invalidation the
> correct semantic.  No inode lock is required for cifs_invalidate_cache().
> 
> Fixes: fa724e235cfd ("cifs: add fscache_resize_cookie() to cifs_setsize()")
> Cc: [email protected]
> Cc: Huiwen He <[email protected]>
> Cc: David Howells <[email protected]>
> Cc: Paulo Alcantara <[email protected]>
> Signed-off-by: Frank Sorenson <[email protected]>
> ---
>   fs/smb/client/file.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
> index ac89c1ba56b1..389083f9ce00 100644
> --- a/fs/smb/client/file.c
> +++ b/fs/smb/client/file.c
> @@ -1016,6 +1016,7 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)
>   		if (!rc) {
>   			netfs_resize_file(&cinode->netfs, 0, true);
>   			cifs_setsize(inode, 0);
> +			cifs_invalidate_cache(inode, 0);
>   		}
>   	}
>   	if (cfile)