smb3: add debug messages for closing unmatched open
authorRonnie Sahlberg <lsahlber@redhat.com>
Thu, 14 Nov 2019 18:32:12 +0000 (12:32 -0600)
committerSteve French <stfrench@microsoft.com>
Mon, 25 Nov 2019 07:14:53 +0000 (01:14 -0600)
Helps distinguish between an interrupted close and a truly
unmatched open.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/cifsglob.h
fs/cifs/smb2misc.c

index 5d2dd04..5745322 100644 (file)
@@ -1552,6 +1552,8 @@ struct close_cancelled_open {
        struct cifs_fid         fid;
        struct cifs_tcon        *tcon;
        struct work_struct      work;
+       __u64 mid;
+       __u16 cmd;
 };
 
 /*     Make code in transport.c a little cleaner by moving
index 5668fb7..289915f 100644 (file)
@@ -729,19 +729,35 @@ smb2_cancelled_close_fid(struct work_struct *work)
 {
        struct close_cancelled_open *cancelled = container_of(work,
                                        struct close_cancelled_open, work);
+       struct cifs_tcon *tcon = cancelled->tcon;
+       int rc;
+
+       if (cancelled->mid)
+               cifs_tcon_dbg(VFS, "Close unmatched open for MID:%llx\n",
+                             cancelled->mid);
+       else
+               cifs_tcon_dbg(VFS, "Close interrupted close\n");
 
-       cifs_dbg(VFS, "Close unmatched open\n");
+       rc = SMB2_close(0, tcon, cancelled->fid.persistent_fid,
+                       cancelled->fid.volatile_fid);
+       if (rc)
+               cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc);
 
-       SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid,
-                  cancelled->fid.volatile_fid);
-       cifs_put_tcon(cancelled->tcon);
+       cifs_put_tcon(tcon);
        kfree(cancelled);
 }
 
-/* Caller should already has an extra reference to @tcon */
+/*
+ * Caller should already has an extra reference to @tcon
+ * This function is used to queue work to close a handle to prevent leaks
+ * on the server.
+ * We handle two cases. If an open was interrupted after we sent the
+ * SMB2_CREATE to the server but before we processed the reply, and second
+ * if a close was interrupted before we sent the SMB2_CLOSE to the server.
+ */
 static int
-__smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
-                             __u64 volatile_fid)
+__smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid,
+                           __u64 persistent_fid, __u64 volatile_fid)
 {
        struct close_cancelled_open *cancelled;
 
@@ -752,6 +768,8 @@ __smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
        cancelled->fid.persistent_fid = persistent_fid;
        cancelled->fid.volatile_fid = volatile_fid;
        cancelled->tcon = tcon;
+       cancelled->cmd = cmd;
+       cancelled->mid = mid;
        INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
        WARN_ON(queue_work(cifsiod_wq, &cancelled->work) == false);
 
@@ -769,7 +787,8 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
        tcon->tc_count++;
        spin_unlock(&cifs_tcp_ses_lock);
 
-       rc = __smb2_handle_cancelled_close(tcon, persistent_fid, volatile_fid);
+       rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0,
+                                        persistent_fid, volatile_fid);
        if (rc)
                cifs_put_tcon(tcon);
 
@@ -793,8 +812,11 @@ smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
        if (!tcon)
                return -ENOENT;
 
-       rc = __smb2_handle_cancelled_close(tcon, rsp->PersistentFileId,
-                                          rsp->VolatileFileId);
+       rc = __smb2_handle_cancelled_cmd(tcon,
+                                        le16_to_cpu(sync_hdr->Command),
+                                        le64_to_cpu(sync_hdr->MessageId),
+                                        rsp->PersistentFileId,
+                                        rsp->VolatileFileId);
        if (rc)
                cifs_put_tcon(tcon);