diff options
-rw-r--r-- | fs/cifs/cifsglob.h | 6 | ||||
-rw-r--r-- | fs/cifs/connect.c | 30 | ||||
-rw-r--r-- | fs/cifs/transport.c | 23 |
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 | */ |
550 | typedef void (mid_callback_t)(struct mid_q_entry *mid); | 549 | typedef 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 | ||
428 | static int | 428 | static int |
429 | sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) | 429 | cifs_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 | ||