Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7754D3C0A12 for ; Sun, 6 Sep 2026 19:30:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788723059; cv=none; b=bsph0giyizHdpbGxERUvUyHCJ27UG421RBvW4V7SlQYXaJNK/PRc8YQES9rNiVqGSRMJWPHgeEHq70GCIDoihMYaKwWvFXjQ6qTW6DjOwBxOEnEzPe1Ivvh7PujTtKAzQ0MzfHQPqZ9EesiFXzJn5rpD5+8byJBfDl//tMzCN9I= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788723059; c=relaxed/simple; bh=Adwa74+UqPhchl2S5VWWfMLXL4IdDqdZVh94QeeM2T0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NNVj2qKINyv1x3tuJj13k5hbvtaTz+/BsF+rHY3ldOFRYJ/gsC0vdoUxcJQO9qlKDVq/TrlieKByxdQrZjARks96QQzVpQmdbLgmpGhtjTsZy9RXFaT1ujIl2a2Jka0umtS2oyO7bt8cF8biGv+QiFrdSywIwq1Z7Wby8usqnEw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Xf8tk1sq; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Xf8tk1sq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A19F41F00A3A; Sun, 6 Sep 2026 19:30:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788723057; bh=Lny+VAJe4aO2Zo/nLoBaDK0huQUBJ7xTc4jppBizjaQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Xf8tk1sqAbwh2tYGVaBOw+wLToZiMc1roDKGZIMv/AC4TVxs9kWSH4LwvRUycqiUz DUleVugKRk4a0w2atwezaXl1HbB5V63ngpTL24qiK8D3Qxa3u4qJoIfRPBZBu5Cz3g 5C3vflu2SRwBqqYbJY5RBFIEBdK8bTTSMJhvPsAdfxk7GgpauHLF3acmIdX+pMFiSq rIAuhlyEKZNdZ/n6dC2t1IQd6kAP9izYab3LwfZxm0MES6QQl69nu9LQEHCJMPDFfc xdC1VaZJX9QqJwg+oq87AvgbqHAjUPAYGMWK2sv12MmzBpQrP8dKneljGE6854fol5 ghdnVJWcJ8UzQ== From: Sasha Levin To: stable@vger.kernel.org Cc: Frank Sorenson , David Howells , Paulo Alcantara , Namjae Jeon , Paulo Alcantara , Sasha Levin Subject: [PATCH 6.18.y 4/4] cifs: add cifs_resize_file_locked() to guard fscache_resize_cookie() under i_rwsem Date: Sun, 6 Sep 2026 15:30:52 -0400 Message-ID: <20260906193052.1791917-4-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260906193052.1791917-1-sashal@kernel.org> References: <2026090358-afar-boss-f2c3@gregkh> <20260906193052.1791917-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Frank Sorenson [ Upstream commit 32a7af68df7361fe7cf153cf36124d04b94aec00 ] cifs_setsize() calls fscache_resize_cookie() without holding i_rwsem. When the fscache cookie is active (FSCACHE_COOKIE_IS_CACHING is set), fscache_resize_cookie() performs a real resize that requires i_rwsem held exclusively. If another file descriptor has the same inode open, fscache_use_cookie() was already called from that cifs_open(), making the cookie active. In that case, calling cifs_setsize() from cifs_do_truncate() (invoked from cifs_open() without i_rwsem) races against concurrent fscache I/O. Strip fscache_resize_cookie() from cifs_setsize(), making it a pure size/page-cache helper. Add cifs_resize_file_locked() for callers that already hold i_rwsem: it calls netfs_resize_file() and cifs_setsize(), then temporarily activates the cookie with fscache_use_cookie() to perform the resize under the lock, then deactivates it with cifs_fscache_unuse_inode_cookie(). Using fscache_use_cookie() before the resize ensures correctness whether or not another fd already holds the cookie active. Switch cifs_file_set_size(), smb2_duplicate_extents(), and both size- extension branches of smb3_simple_falloc() to the new wrapper; those paths already hold i_rwsem via VFS setattr, lock_two_nondirectories(), or cifs_fallocate() respectively. cifs_do_truncate() continues to call cifs_setsize() followed by cifs_invalidate_cache(), since it runs without i_rwsem. Fixes: fa724e235cfd ("cifs: add fscache_resize_cookie() to cifs_setsize()") Cc: stable@vger.kernel.org Cc: David Howells Cc: Paulo Alcantara Signed-off-by: Frank Sorenson Signed-off-by: Namjae Jeon Signed-off-by: Paulo Alcantara Signed-off-by: Sasha Levin --- fs/smb/client/cifsfs.h | 1 + fs/smb/client/inode.c | 24 +++++++++++++++++++----- fs/smb/client/smb2ops.c | 9 +++------ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h index de32a0ae53ae7..3d632d22da6fc 100644 --- a/fs/smb/client/cifsfs.h +++ b/fs/smb/client/cifsfs.h @@ -135,6 +135,7 @@ extern ssize_t cifs_file_copychunk_range(unsigned int xid, 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); struct fs_context; struct smb3_fs_context; diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index c9e955d0d799e..15b9f44553d5f 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -3039,7 +3039,23 @@ void cifs_setsize(struct inode *inode, loff_t offset) inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); truncate_pagecache(inode, offset); netfs_wait_for_outstanding_io(inode); - fscache_resize_cookie(cifs_inode_cookie(inode), offset); +} + +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); } int cifs_file_set_size(const unsigned int xid, struct dentry *dentry, @@ -3105,10 +3121,8 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry, cifs_put_tlink(tlink); set_size_out: - if (rc == 0) { - netfs_resize_file(&cifsInode->netfs, size, true); - cifs_setsize(inode, size); - } + if (rc == 0) + cifs_resize_file_locked(inode, size); return rc; } diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index c25914888beae..7ca606868596d 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -2197,8 +2197,7 @@ smb2_duplicate_extents(const unsigned int xid, rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false); if (rc) goto duplicate_extents_out; - netfs_resize_file(netfs_inode(inode), dest_off + len, true); - cifs_setsize(inode, dest_off + len); + cifs_resize_file_locked(inode, dest_off + len); } rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, trgtfile->fid.volatile_fid, @@ -3702,8 +3701,7 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, } new_eof = off + len; - netfs_resize_file(&cifsi->netfs, new_eof, true); - cifs_setsize(inode, new_eof); + cifs_resize_file_locked(inode, new_eof); qrc = SMB2_query_info(xid, tcon, cfile->fid.persistent_fid, @@ -3728,8 +3726,7 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, if (rc) goto out; - netfs_resize_file(&cifsi->netfs, new_eof, true); - cifs_setsize(inode, new_eof); + cifs_resize_file_locked(inode, new_eof); qrc = SMB2_query_info(xid, tcon, cfile->fid.persistent_fid, -- 2.53.0