diff options
author | Rohith Surabattula <rohiths@microsoft.com> | 2021-07-29 09:45:29 +0200 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2021-08-12 18:29:54 +0200 |
commit | 41535701da3324b80029cabb501e86c4fafe339d (patch) | |
tree | e2e6e814c984cf9620ac6b5cbbb31953ee7bf852 /fs/cifs/misc.c | |
parent | cifs: use the correct max-length for dentry_path_raw() (diff) | |
download | linux-41535701da3324b80029cabb501e86c4fafe339d.tar.xz linux-41535701da3324b80029cabb501e86c4fafe339d.zip |
cifs: Handle race conditions during rename
When rename is executed on directory which has files for which
close is deferred, then rename will fail with EACCES.
This patch will try to close all deferred files when EACCES is received
and retry rename on a directory.
Signed-off-by: Rohith Surabattula <rohiths@microsoft.com>
Cc: stable@vger.kernel.org # 5.13
Reviewed-by: Shyam Prasad N <sprasad@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs/misc.c')
-rw-r--r-- | fs/cifs/misc.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 844abeb2b48f..cdb1ec1461de 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -723,13 +723,19 @@ void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode) { struct cifsFileInfo *cfile = NULL; - struct cifs_deferred_close *dclose; + + if (cifs_inode == NULL) + return; list_for_each_entry(cfile, &cifs_inode->openFileList, flist) { - spin_lock(&cifs_inode->deferred_lock); - if (cifs_is_deferred_close(cfile, &dclose)) - mod_delayed_work(deferredclose_wq, &cfile->deferred, 0); - spin_unlock(&cifs_inode->deferred_lock); + if (delayed_work_pending(&cfile->deferred)) { + /* + * If there is no pending work, mod_delayed_work queues new work. + * So, Increase the ref count to avoid use-after-free. + */ + if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0)) + cifsFileInfo_get(cfile); + } } } |