mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
smb: client: fix filename matching of deferred files
[ Upstream commit93ed9a2951] 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:e3fc065682("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: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
ea5cbcecd5
commit
b814660334
@@ -298,8 +298,8 @@ extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
|
||||
|
||||
extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
|
||||
|
||||
extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
|
||||
const char *path);
|
||||
void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
|
||||
struct dentry *dentry);
|
||||
|
||||
extern void cifs_mark_open_handles_for_deleted_file(struct inode *inode,
|
||||
const char *path);
|
||||
|
||||
@@ -1958,7 +1958,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
}
|
||||
|
||||
netfs_wait_for_outstanding_io(inode);
|
||||
cifs_close_deferred_file_under_dentry(tcon, full_path);
|
||||
cifs_close_deferred_file_under_dentry(tcon, dentry);
|
||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
@@ -2489,10 +2489,10 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,
|
||||
goto cifs_rename_exit;
|
||||
}
|
||||
|
||||
cifs_close_deferred_file_under_dentry(tcon, from_name);
|
||||
cifs_close_deferred_file_under_dentry(tcon, source_dentry);
|
||||
if (d_inode(target_dentry) != NULL) {
|
||||
netfs_wait_for_outstanding_io(d_inode(target_dentry));
|
||||
cifs_close_deferred_file_under_dentry(tcon, to_name);
|
||||
cifs_close_deferred_file_under_dentry(tcon, target_dentry);
|
||||
}
|
||||
|
||||
rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
|
||||
|
||||
@@ -829,33 +829,28 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
|
||||
kfree(tmp_list);
|
||||
}
|
||||
}
|
||||
void
|
||||
cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
|
||||
|
||||
void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
struct cifsFileInfo *cfile;
|
||||
struct file_list *tmp_list, *tmp_next_list;
|
||||
void *page;
|
||||
const char *full_path;
|
||||
struct cifsFileInfo *cfile;
|
||||
LIST_HEAD(file_head);
|
||||
|
||||
page = alloc_dentry_path();
|
||||
spin_lock(&tcon->open_file_lock);
|
||||
list_for_each_entry(cfile, &tcon->openFileList, tlist) {
|
||||
full_path = build_path_from_dentry(cfile->dentry, page);
|
||||
if (strstr(full_path, path)) {
|
||||
if (delayed_work_pending(&cfile->deferred)) {
|
||||
if (cancel_delayed_work(&cfile->deferred)) {
|
||||
spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
|
||||
cifs_del_deferred_close(cfile);
|
||||
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
|
||||
if ((cfile->dentry == dentry) &&
|
||||
delayed_work_pending(&cfile->deferred) &&
|
||||
cancel_delayed_work(&cfile->deferred)) {
|
||||
spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
|
||||
cifs_del_deferred_close(cfile);
|
||||
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
|
||||
|
||||
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
|
||||
if (tmp_list == NULL)
|
||||
break;
|
||||
tmp_list->cfile = cfile;
|
||||
list_add_tail(&tmp_list->list, &file_head);
|
||||
}
|
||||
}
|
||||
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
|
||||
if (tmp_list == NULL)
|
||||
break;
|
||||
tmp_list->cfile = cfile;
|
||||
list_add_tail(&tmp_list->list, &file_head);
|
||||
}
|
||||
}
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
@@ -865,7 +860,6 @@ cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
|
||||
list_del(&tmp_list->list);
|
||||
kfree(tmp_list);
|
||||
}
|
||||
free_dentry_path(page);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user