summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBharath SM <bharathsm@microsoft.com>2025-06-30 21:53:03 +0300
committerSteve French <stfrench@microsoft.com>2025-07-14 01:16:29 +0300
commit83898e4a858387c88cd7456f713cb8fd49440cf9 (patch)
tree6282fa0b2488e2098ebd5ee3c3e9f01ec55df540
parentb220bed63330c0e1733dc06ea8e75d5b9962b6b6 (diff)
downloadlinux-83898e4a858387c88cd7456f713cb8fd49440cf9.tar.xz
smb: invalidate and close cached directory when creating child entries
When a parent lease key is passed to the server during a create operation while holding a directory lease, the server may not send a lease break to the client. In such cases, it becomes the client’s responsibility to ensure cache consistency. This led to a problem where directory listings (e.g., `ls` or `readdir`) could return stale results after a new file is created. eg: ls /mnt/share/ touch /mnt/share/file1 ls /mnt/share/ In this scenario, the final `ls` may not show `file1` due to the stale directory cache. For now, fix this by marking the cached directory as invalid if using the parent lease key during create, and explicitly closing the cached directory after successful file creation. Fixes: 037e1bae588eacf ("smb: client: use ParentLeaseKey in cifs_do_create") Signed-off-by: Bharath SM <bharathsm@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r--fs/smb/client/dir.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
index 1c6e5389c51f..5223edf6d11a 100644
--- a/fs/smb/client/dir.c
+++ b/fs/smb/client/dir.c
@@ -190,6 +190,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
int disposition;
struct TCP_Server_Info *server = tcon->ses->server;
struct cifs_open_parms oparms;
+ struct cached_fid *parent_cfid = NULL;
int rdwr_for_fscache = 0;
__le32 lease_flags = 0;
@@ -313,10 +314,10 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
create_options |= CREATE_OPTION_READONLY;
+
retry_open:
if (tcon->cfids && direntry->d_parent && server->dialect >= SMB30_PROT_ID) {
- struct cached_fid *parent_cfid;
-
+ parent_cfid = NULL;
spin_lock(&tcon->cfids->cfid_list_lock);
list_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) {
if (parent_cfid->dentry == direntry->d_parent) {
@@ -327,6 +328,7 @@ retry_open:
memcpy(fid->parent_lease_key,
parent_cfid->fid.lease_key,
SMB2_LEASE_KEY_SIZE);
+ parent_cfid->dirents.is_valid = false;
}
break;
}