Skip to content

Commit b6bdffa

Browse files
committed
smb: client: fix filename matching of deferred files
JIRA: https://issues.redhat.com/browse/RHEL-114295 Conflicts: - Context difference due to missing 3ee1a1f ("cifs: Cut over to using netfslib") and bb57c81 ("cifs: Fix rmdir failure due to ongoing I/O on deleted file") in RHEL 9. 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 48087fe commit b6bdffa

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
@@ -297,8 +297,8 @@ extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
297297

298298
extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
299299

300-
extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
301-
const char *path);
300+
void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
301+
struct dentry *dentry);
302302

303303
extern void cifs_mark_open_handles_for_deleted_file(struct inode *inode,
304304
const char *path);

fs/smb/client/inode.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,7 +1964,7 @@ static int __cifs_unlink(struct inode *dir, struct dentry *dentry, bool sillyren
19641964
goto unlink_out;
19651965
}
19661966

1967-
cifs_close_deferred_file_under_dentry(tcon, full_path);
1967+
cifs_close_deferred_file_under_dentry(tcon, dentry);
19681968
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
19691969
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
19701970
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
@@ -2518,9 +2518,9 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,
25182518
goto cifs_rename_exit;
25192519
}
25202520

2521-
cifs_close_deferred_file_under_dentry(tcon, from_name);
2521+
cifs_close_deferred_file_under_dentry(tcon, source_dentry);
25222522
if (d_inode(target_dentry) != NULL)
2523-
cifs_close_deferred_file_under_dentry(tcon, to_name);
2523+
cifs_close_deferred_file_under_dentry(tcon, target_dentry);
25242524

25252525
rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
25262526
to_name);

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)