Merge tag '5.15-rc-first-ksmbd-merge' of git://git.samba.org/ksmbd
[linux-2.6-microblaze.git] / fs / cifs / file.c
index 0a72840..bb98fbd 100644 (file)
@@ -4847,17 +4847,6 @@ void cifs_oplock_break(struct work_struct *work)
                cifs_dbg(VFS, "Push locks rc = %d\n", rc);
 
 oplock_break_ack:
-       /*
-        * releasing stale oplock after recent reconnect of smb session using
-        * a now incorrect file handle is not a data integrity issue but do
-        * not bother sending an oplock release if session to server still is
-        * disconnected since oplock already released by the server
-        */
-       if (!cfile->oplock_break_cancelled) {
-               rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
-                                                            cinode);
-               cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
-       }
        /*
         * When oplock break is received and there are no active
         * file handles but cached, then schedule deferred close immediately.
@@ -4865,17 +4854,27 @@ oplock_break_ack:
         */
        spin_lock(&CIFS_I(inode)->deferred_lock);
        is_deferred = cifs_is_deferred_close(cfile, &dclose);
+       spin_unlock(&CIFS_I(inode)->deferred_lock);
        if (is_deferred &&
            cfile->deferred_close_scheduled &&
            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);
+               if (cancel_delayed_work(&cfile->deferred)) {
+                       _cifsFileInfo_put(cfile, false, false);
+                       goto oplock_break_done;
+               }
        }
-       spin_unlock(&CIFS_I(inode)->deferred_lock);
+       /*
+        * releasing stale oplock after recent reconnect of smb session using
+        * a now incorrect file handle is not a data integrity issue but do
+        * not bother sending an oplock release if session to server still is
+        * disconnected since oplock already released by the server
+        */
+       if (!cfile->oplock_break_cancelled) {
+               rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
+                                                            cinode);
+               cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
+       }
+oplock_break_done:
        _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
        cifs_done_oplock_break(cinode);
 }