Преглед изворни кода

Merge tag '4.19-rc6-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Steve writes:
  "SMB3 fixes

   four small SMB3 fixes: one for stable, the others to address a more
   recent regression"

* tag '4.19-rc6-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  smb3: fix lease break problem introduced by compounding
  cifs: only wake the thread for the very last PDU in a compound
  cifs: add a warning if we try to to dequeue a deleted mid
  smb2: fix missing files in root share directory listing
Greg Kroah-Hartman пре 6 година
родитељ
комит
087f759a41
4 измењених фајлова са 31 додато и 6 уклоњено
  1. 1 0
      fs/cifs/cifsglob.h
  2. 10 3
      fs/cifs/connect.c
  3. 1 1
      fs/cifs/smb2ops.c
  4. 19 2
      fs/cifs/transport.c

+ 1 - 0
fs/cifs/cifsglob.h

@@ -1553,6 +1553,7 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
 
 
 /* Flags */
 /* Flags */
 #define   MID_WAIT_CANCELLED	 1 /* Cancelled while waiting for response */
 #define   MID_WAIT_CANCELLED	 1 /* Cancelled while waiting for response */
+#define   MID_DELETED            2 /* Mid has been dequeued/deleted */
 
 
 /* Types of response buffer returned from SendReceive2 */
 /* Types of response buffer returned from SendReceive2 */
 #define   CIFS_NO_BUFFER        0    /* Response buffer not returned */
 #define   CIFS_NO_BUFFER        0    /* Response buffer not returned */

+ 10 - 3
fs/cifs/connect.c

@@ -659,7 +659,15 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed)
 		mid->mid_state = MID_RESPONSE_RECEIVED;
 		mid->mid_state = MID_RESPONSE_RECEIVED;
 	else
 	else
 		mid->mid_state = MID_RESPONSE_MALFORMED;
 		mid->mid_state = MID_RESPONSE_MALFORMED;
-	list_del_init(&mid->qhead);
+	/*
+	 * Trying to handle/dequeue a mid after the send_recv()
+	 * function has finished processing it is a bug.
+	 */
+	if (mid->mid_flags & MID_DELETED)
+		printk_once(KERN_WARNING
+			    "trying to dequeue a deleted mid\n");
+	else
+		list_del_init(&mid->qhead);
 	spin_unlock(&GlobalMid_Lock);
 	spin_unlock(&GlobalMid_Lock);
 }
 }
 
 
@@ -938,8 +946,7 @@ next_pdu:
 		} else {
 		} else {
 			mids[0] = server->ops->find_mid(server, buf);
 			mids[0] = server->ops->find_mid(server, buf);
 			bufs[0] = buf;
 			bufs[0] = buf;
-			if (mids[0])
-				num_mids = 1;
+			num_mids = 1;
 
 
 			if (!mids[0] || !mids[0]->receive)
 			if (!mids[0] || !mids[0]->receive)
 				length = standard_receive3(server, mids[0]);
 				length = standard_receive3(server, mids[0]);

+ 1 - 1
fs/cifs/smb2ops.c

@@ -1477,7 +1477,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
 	}
 	}
 
 
 	srch_inf->entries_in_buffer = 0;
 	srch_inf->entries_in_buffer = 0;
-	srch_inf->index_of_last_entry = 0;
+	srch_inf->index_of_last_entry = 2;
 
 
 	rc = SMB2_query_directory(xid, tcon, fid->persistent_fid,
 	rc = SMB2_query_directory(xid, tcon, fid->persistent_fid,
 				  fid->volatile_fid, 0, srch_inf);
 				  fid->volatile_fid, 0, srch_inf);

+ 19 - 2
fs/cifs/transport.c

@@ -142,7 +142,8 @@ void
 cifs_delete_mid(struct mid_q_entry *mid)
 cifs_delete_mid(struct mid_q_entry *mid)
 {
 {
 	spin_lock(&GlobalMid_Lock);
 	spin_lock(&GlobalMid_Lock);
-	list_del(&mid->qhead);
+	list_del_init(&mid->qhead);
+	mid->mid_flags |= MID_DELETED;
 	spin_unlock(&GlobalMid_Lock);
 	spin_unlock(&GlobalMid_Lock);
 
 
 	DeleteMidQEntry(mid);
 	DeleteMidQEntry(mid);
@@ -772,6 +773,11 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
 	return mid;
 	return mid;
 }
 }
 
 
+static void
+cifs_noop_callback(struct mid_q_entry *mid)
+{
+}
+
 int
 int
 compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
 compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
 		   const int flags, const int num_rqst, struct smb_rqst *rqst,
 		   const int flags, const int num_rqst, struct smb_rqst *rqst,
@@ -826,8 +832,13 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
 		}
 		}
 
 
 		midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
 		midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
+		/*
+		 * We don't invoke the callback compounds unless it is the last
+		 * request.
+		 */
+		if (i < num_rqst - 1)
+			midQ[i]->callback = cifs_noop_callback;
 	}
 	}
-
 	cifs_in_send_inc(ses->server);
 	cifs_in_send_inc(ses->server);
 	rc = smb_send_rqst(ses->server, num_rqst, rqst, flags);
 	rc = smb_send_rqst(ses->server, num_rqst, rqst, flags);
 	cifs_in_send_dec(ses->server);
 	cifs_in_send_dec(ses->server);
@@ -908,6 +919,12 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
 			midQ[i]->resp_buf = NULL;
 			midQ[i]->resp_buf = NULL;
 	}
 	}
 out:
 out:
+	/*
+	 * This will dequeue all mids. After this it is important that the
+	 * demultiplex_thread will not process any of these mids any futher.
+	 * This is prevented above by using a noop callback that will not
+	 * wake this thread except for the very last PDU.
+	 */
 	for (i = 0; i < num_rqst; i++)
 	for (i = 0; i < num_rqst; i++)
 		cifs_delete_mid(midQ[i]);
 		cifs_delete_mid(midQ[i]);
 	add_credits(ses->server, credits, optype);
 	add_credits(ses->server, credits, optype);