Skip to content

Commit 83898e4

Browse files
bharathsm-mssmfrench
authored andcommitted
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: 037e1ba ("smb: client: use ParentLeaseKey in cifs_do_create") Signed-off-by: Bharath SM <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent b220bed commit 83898e4

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

fs/smb/client/dir.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
190190
int disposition;
191191
struct TCP_Server_Info *server = tcon->ses->server;
192192
struct cifs_open_parms oparms;
193+
struct cached_fid *parent_cfid = NULL;
193194
int rdwr_for_fscache = 0;
194195
__le32 lease_flags = 0;
195196

@@ -313,10 +314,10 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
313314
if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
314315
create_options |= CREATE_OPTION_READONLY;
315316

317+
316318
retry_open:
317319
if (tcon->cfids && direntry->d_parent && server->dialect >= SMB30_PROT_ID) {
318-
struct cached_fid *parent_cfid;
319-
320+
parent_cfid = NULL;
320321
spin_lock(&tcon->cfids->cfid_list_lock);
321322
list_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) {
322323
if (parent_cfid->dentry == direntry->d_parent) {
@@ -327,6 +328,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
327328
memcpy(fid->parent_lease_key,
328329
parent_cfid->fid.lease_key,
329330
SMB2_LEASE_KEY_SIZE);
331+
parent_cfid->dirents.is_valid = false;
330332
}
331333
break;
332334
}

0 commit comments

Comments
 (0)