Skip to content

Commit 2346ae7

Browse files
committed
smb: client: fix filename matching of deferred files
JIRA: https://issues.redhat.com/browse/RHEL-124956 commit 93ed9a2 Author: Paulo Alcantara <pc@manguebit.org> Date: Wed Sep 17 16:03:22 2025 -0300 smb: client: fix filename matching of deferred files Fix the following case where the client would end up closing both deferred files (foo.tmp & foo) after unlink(foo) due to strstr() call in cifs_close_deferred_file_under_dentry(): fd1 = openat(AT_FDCWD, "foo", O_WRONLY|O_CREAT|O_TRUNC, 0666); fd2 = openat(AT_FDCWD, "foo.tmp", O_WRONLY|O_CREAT|O_TRUNC, 0666); close(fd1); close(fd2); unlink("foo"); Fixes: e3fc065 ("cifs: Deferred close performance improvements") Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Reviewed-by: Enzo Matsumiya <ematsumiya@suse.de> Cc: Frank Sorenson <sorenson@redhat.com> Cc: David Howells <dhowells@redhat.com> Cc: linux-cifs@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Paulo Alcantara <paalcant@redhat.com>
1 parent a2dff6e commit 2346ae7

File tree

3 files changed

+21
-27
lines changed

3 files changed

+21
-27
lines changed

fs/smb/client/cifsproto.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,8 @@ extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
312312

313313
extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
314314

315-
extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
316-
const char *path);
315+
void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
316+
struct dentry *dentry);
317317

318318
extern void cifs_mark_open_handles_for_deleted_file(struct inode *inode,
319319
const char *path);

fs/smb/client/inode.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,7 +1984,7 @@ static int __cifs_unlink(struct inode *dir, struct dentry *dentry, bool sillyren
19841984
}
19851985

19861986
netfs_wait_for_outstanding_io(inode);
1987-
cifs_close_deferred_file_under_dentry(tcon, full_path);
1987+
cifs_close_deferred_file_under_dentry(tcon, dentry);
19881988
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
19891989
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
19901990
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
@@ -2551,10 +2551,10 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,
25512551
goto cifs_rename_exit;
25522552
}
25532553

2554-
cifs_close_deferred_file_under_dentry(tcon, from_name);
2554+
cifs_close_deferred_file_under_dentry(tcon, source_dentry);
25552555
if (d_inode(target_dentry) != NULL) {
25562556
netfs_wait_for_outstanding_io(d_inode(target_dentry));
2557-
cifs_close_deferred_file_under_dentry(tcon, to_name);
2557+
cifs_close_deferred_file_under_dentry(tcon, target_dentry);
25582558
}
25592559

25602560
rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,

fs/smb/client/misc.c

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -832,33 +832,28 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
832832
kfree(tmp_list);
833833
}
834834
}
835-
void
836-
cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
835+
836+
void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
837+
struct dentry *dentry)
837838
{
838-
struct cifsFileInfo *cfile;
839839
struct file_list *tmp_list, *tmp_next_list;
840-
void *page;
841-
const char *full_path;
840+
struct cifsFileInfo *cfile;
842841
LIST_HEAD(file_head);
843842

844-
page = alloc_dentry_path();
845843
spin_lock(&tcon->open_file_lock);
846844
list_for_each_entry(cfile, &tcon->openFileList, tlist) {
847-
full_path = build_path_from_dentry(cfile->dentry, page);
848-
if (strstr(full_path, path)) {
849-
if (delayed_work_pending(&cfile->deferred)) {
850-
if (cancel_delayed_work(&cfile->deferred)) {
851-
spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
852-
cifs_del_deferred_close(cfile);
853-
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
854-
855-
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
856-
if (tmp_list == NULL)
857-
break;
858-
tmp_list->cfile = cfile;
859-
list_add_tail(&tmp_list->list, &file_head);
860-
}
861-
}
845+
if ((cfile->dentry == dentry) &&
846+
delayed_work_pending(&cfile->deferred) &&
847+
cancel_delayed_work(&cfile->deferred)) {
848+
spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
849+
cifs_del_deferred_close(cfile);
850+
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
851+
852+
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
853+
if (tmp_list == NULL)
854+
break;
855+
tmp_list->cfile = cfile;
856+
list_add_tail(&tmp_list->list, &file_head);
862857
}
863858
}
864859
spin_unlock(&tcon->open_file_lock);
@@ -868,7 +863,6 @@ cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
868863
list_del(&tmp_list->list);
869864
kfree(tmp_list);
870865
}
871-
free_dentry_path(page);
872866
}
873867

874868
/*

0 commit comments

Comments
 (0)