aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsglob.h6
-rw-r--r--fs/cifs/connect.c30
-rw-r--r--fs/cifs/transport.c23
3 files changed, 35 insertions, 24 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 76b4517e74b0..fd877c110e4c 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -543,9 +543,8 @@ struct mid_q_entry;
543 * This is the prototype for the mid callback function. When creating one, 543 * This is the prototype for the mid callback function. When creating one,
544 * take special care to avoid deadlocks. Things to bear in mind: 544 * take special care to avoid deadlocks. Things to bear in mind:
545 * 545 *
546 * - it will be called by cifsd 546 * - it will be called by cifsd, with no locks held
547 * - the GlobalMid_Lock will be held 547 * - the mid will be removed from any lists
548 * - the mid will be removed from the pending_mid_q list
549 */ 548 */
550typedef void (mid_callback_t)(struct mid_q_entry *mid); 549typedef void (mid_callback_t)(struct mid_q_entry *mid);
551 550
@@ -656,6 +655,7 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
656#define MID_RESPONSE_RECEIVED 4 655#define MID_RESPONSE_RECEIVED 4
657#define MID_RETRY_NEEDED 8 /* session closed while this request out */ 656#define MID_RETRY_NEEDED 8 /* session closed while this request out */
658#define MID_RESPONSE_MALFORMED 0x10 657#define MID_RESPONSE_MALFORMED 0x10
658#define MID_SHUTDOWN 0x20
659 659
660/* Types of response buffer returned from SendReceive2 */ 660/* Types of response buffer returned from SendReceive2 */
661#define CIFS_NO_BUFFER 0 /* Response buffer not returned */ 661#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 273cf42b2915..6070ba69647b 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -137,6 +137,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
137 struct cifsSesInfo *ses; 137 struct cifsSesInfo *ses;
138 struct cifsTconInfo *tcon; 138 struct cifsTconInfo *tcon;
139 struct mid_q_entry *mid_entry; 139 struct mid_q_entry *mid_entry;
140 struct list_head retry_list;
140 141
141 spin_lock(&GlobalMid_Lock); 142 spin_lock(&GlobalMid_Lock);
142 if (server->tcpStatus == CifsExiting) { 143 if (server->tcpStatus == CifsExiting) {
@@ -188,16 +189,23 @@ cifs_reconnect(struct TCP_Server_Info *server)
188 mutex_unlock(&server->srv_mutex); 189 mutex_unlock(&server->srv_mutex);
189 190
190 /* mark submitted MIDs for retry and issue callback */ 191 /* mark submitted MIDs for retry and issue callback */
191 cFYI(1, "%s: issuing mid callbacks", __func__); 192 INIT_LIST_HEAD(&retry_list);
193 cFYI(1, "%s: moving mids to private list", __func__);
192 spin_lock(&GlobalMid_Lock); 194 spin_lock(&GlobalMid_Lock);
193 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { 195 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
194 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 196 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
195 if (mid_entry->midState == MID_REQUEST_SUBMITTED) 197 if (mid_entry->midState == MID_REQUEST_SUBMITTED)
196 mid_entry->midState = MID_RETRY_NEEDED; 198 mid_entry->midState = MID_RETRY_NEEDED;
199 list_move(&mid_entry->qhead, &retry_list);
200 }
201 spin_unlock(&GlobalMid_Lock);
202
203 cFYI(1, "%s: issuing mid callbacks", __func__);
204 list_for_each_safe(tmp, tmp2, &retry_list) {
205 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
197 list_del_init(&mid_entry->qhead); 206 list_del_init(&mid_entry->qhead);
198 mid_entry->callback(mid_entry); 207 mid_entry->callback(mid_entry);
199 } 208 }
200 spin_unlock(&GlobalMid_Lock);
201 209
202 while (server->tcpStatus == CifsNeedReconnect) { 210 while (server->tcpStatus == CifsNeedReconnect) {
203 try_to_freeze(); 211 try_to_freeze();
@@ -671,12 +679,12 @@ multi_t2_fnd:
671 mid_entry->when_received = jiffies; 679 mid_entry->when_received = jiffies;
672#endif 680#endif
673 list_del_init(&mid_entry->qhead); 681 list_del_init(&mid_entry->qhead);
674 mid_entry->callback(mid_entry);
675 break; 682 break;
676 } 683 }
677 spin_unlock(&GlobalMid_Lock); 684 spin_unlock(&GlobalMid_Lock);
678 685
679 if (mid_entry != NULL) { 686 if (mid_entry != NULL) {
687 mid_entry->callback(mid_entry);
680 /* Was previous buf put in mpx struct for multi-rsp? */ 688 /* Was previous buf put in mpx struct for multi-rsp? */
681 if (!isMultiRsp) { 689 if (!isMultiRsp) {
682 /* smb buffer will be freed by user thread */ 690 /* smb buffer will be freed by user thread */
@@ -740,15 +748,25 @@ multi_t2_fnd:
740 cifs_small_buf_release(smallbuf); 748 cifs_small_buf_release(smallbuf);
741 749
742 if (!list_empty(&server->pending_mid_q)) { 750 if (!list_empty(&server->pending_mid_q)) {
751 struct list_head dispose_list;
752
753 INIT_LIST_HEAD(&dispose_list);
743 spin_lock(&GlobalMid_Lock); 754 spin_lock(&GlobalMid_Lock);
744 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { 755 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
745 mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 756 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
746 cFYI(1, "Clearing Mid 0x%x - issuing callback", 757 cFYI(1, "Clearing mid 0x%x", mid_entry->mid);
747 mid_entry->mid); 758 mid_entry->midState = MID_SHUTDOWN;
759 list_move(&mid_entry->qhead, &dispose_list);
760 }
761 spin_unlock(&GlobalMid_Lock);
762
763 /* now walk dispose list and issue callbacks */
764 list_for_each_safe(tmp, tmp2, &dispose_list) {
765 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
766 cFYI(1, "Callback mid 0x%x", mid_entry->mid);
748 list_del_init(&mid_entry->qhead); 767 list_del_init(&mid_entry->qhead);
749 mid_entry->callback(mid_entry); 768 mid_entry->callback(mid_entry);
750 } 769 }
751 spin_unlock(&GlobalMid_Lock);
752 /* 1/8th of sec is more than enough time for them to exit */ 770 /* 1/8th of sec is more than enough time for them to exit */
753 msleep(125); 771 msleep(125);
754 } 772 }
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 16bcc0725cee..d1998b6086ef 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -426,7 +426,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
426} 426}
427 427
428static int 428static int
429sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) 429cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
430{ 430{
431 int rc = 0; 431 int rc = 0;
432 432
@@ -434,28 +434,21 @@ sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
434 mid->mid, mid->midState); 434 mid->mid, mid->midState);
435 435
436 spin_lock(&GlobalMid_Lock); 436 spin_lock(&GlobalMid_Lock);
437 /* ensure that it's no longer on the pending_mid_q */
438 list_del_init(&mid->qhead);
439
440 switch (mid->midState) { 437 switch (mid->midState) {
441 case MID_RESPONSE_RECEIVED: 438 case MID_RESPONSE_RECEIVED:
442 spin_unlock(&GlobalMid_Lock); 439 spin_unlock(&GlobalMid_Lock);
443 return rc; 440 return rc;
444 case MID_REQUEST_SUBMITTED:
445 /* socket is going down, reject all calls */
446 if (server->tcpStatus == CifsExiting) {
447 cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d",
448 __func__, mid->mid, mid->command, mid->midState);
449 rc = -EHOSTDOWN;
450 break;
451 }
452 case MID_RETRY_NEEDED: 441 case MID_RETRY_NEEDED:
453 rc = -EAGAIN; 442 rc = -EAGAIN;
454 break; 443 break;
455 case MID_RESPONSE_MALFORMED: 444 case MID_RESPONSE_MALFORMED:
456 rc = -EIO; 445 rc = -EIO;
457 break; 446 break;
447 case MID_SHUTDOWN:
448 rc = -EHOSTDOWN;
449 break;
458 default: 450 default:
451 list_del_init(&mid->qhead);
459 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__, 452 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
460 mid->mid, mid->midState); 453 mid->mid, mid->midState);
461 rc = -EIO; 454 rc = -EIO;
@@ -618,7 +611,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
618 611
619 cifs_small_buf_release(in_buf); 612 cifs_small_buf_release(in_buf);
620 613
621 rc = sync_mid_result(midQ, ses->server); 614 rc = cifs_sync_mid_result(midQ, ses->server);
622 if (rc != 0) { 615 if (rc != 0) {
623 atomic_dec(&ses->server->inFlight); 616 atomic_dec(&ses->server->inFlight);
624 wake_up(&ses->server->request_q); 617 wake_up(&ses->server->request_q);
@@ -739,7 +732,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
739 spin_unlock(&GlobalMid_Lock); 732 spin_unlock(&GlobalMid_Lock);
740 } 733 }
741 734
742 rc = sync_mid_result(midQ, ses->server); 735 rc = cifs_sync_mid_result(midQ, ses->server);
743 if (rc != 0) { 736 if (rc != 0) {
744 atomic_dec(&ses->server->inFlight); 737 atomic_dec(&ses->server->inFlight);
745 wake_up(&ses->server->request_q); 738 wake_up(&ses->server->request_q);
@@ -914,7 +907,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
914 rstart = 1; 907 rstart = 1;
915 } 908 }
916 909
917 rc = sync_mid_result(midQ, ses->server); 910 rc = cifs_sync_mid_result(midQ, ses->server);
918 if (rc != 0) 911 if (rc != 0)
919 return rc; 912 return rc;
920 913