]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
CIFS: Do not miss cancelled OPEN responses
authorPavel Shilovsky <pshilov@microsoft.com>
Thu, 21 Nov 2019 19:35:14 +0000 (11:35 -0800)
committerSteve French <stfrench@microsoft.com>
Mon, 25 Nov 2019 07:14:53 +0000 (01:14 -0600)
When an OPEN command is cancelled we mark a mid as
cancelled and let the demultiplex thread process it
by closing an open handle. The problem is there is
a race between a system call thread and the demultiplex
thread and there may be a situation when the mid has
been already processed before it is set as cancelled.

Fix this by processing cancelled requests when mids
are being destroyed which means that there is only
one thread referencing a particular mid. Also set
mids as cancelled unconditionally on their state.

Cc: Stable <stable@vger.kernel.org>
Tested-by: Frank Sorenson <sorenson@redhat.com>
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/connect.c
fs/cifs/transport.c

index 40b2a173ba0dfddac6d1905b422b09acabc9b91f..a7a026795bc2c4f470359c60da9545263feeb536 100644 (file)
@@ -1237,12 +1237,6 @@ cifs_demultiplex_thread(void *p)
                for (i = 0; i < num_mids; i++) {
                        if (mids[i] != NULL) {
                                mids[i]->resp_buf_size = server->pdu_size;
-                               if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) &&
-                                   mids[i]->mid_state == MID_RESPONSE_RECEIVED &&
-                                   server->ops->handle_cancelled_mid)
-                                       server->ops->handle_cancelled_mid(
-                                                       mids[i]->resp_buf,
-                                                       server);
 
                                if (!mids[i]->multiRsp || mids[i]->multiEnd)
                                        mids[i]->callback(mids[i]);
index f27842fb9f7561ca2eacc9f4acc2f2fe98200299..19300e0cf1d692abf5c5653a7cdacc2ffeed65ac 100644 (file)
@@ -93,8 +93,14 @@ static void _cifs_mid_q_entry_release(struct kref *refcount)
        __u16 smb_cmd = le16_to_cpu(midEntry->command);
        unsigned long now;
        unsigned long roundtrip_time;
-       struct TCP_Server_Info *server = midEntry->server;
 #endif
+       struct TCP_Server_Info *server = midEntry->server;
+
+       if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) &&
+           midEntry->mid_state == MID_RESPONSE_RECEIVED &&
+           server->ops->handle_cancelled_mid)
+               server->ops->handle_cancelled_mid(midEntry->resp_buf, server);
+
        midEntry->mid_state = MID_FREE;
        atomic_dec(&midCount);
        if (midEntry->large_buf)
@@ -1119,8 +1125,8 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                                 midQ[i]->mid, le16_to_cpu(midQ[i]->command));
                        send_cancel(server, &rqst[i], midQ[i]);
                        spin_lock(&GlobalMid_Lock);
+                       midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
                        if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
-                               midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
                                midQ[i]->callback = cifs_cancelled_callback;
                                cancelled_mid[i] = true;
                                credits[i].value = 0;