diff options
-rw-r--r-- | fs/cifs/cifsglob.h | 23 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 5 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 5 | ||||
-rw-r--r-- | fs/cifs/connect.c | 6 | ||||
-rw-r--r-- | fs/cifs/transport.c | 5 |
5 files changed, 34 insertions, 10 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a73dd1d5e7ef..d153d0b89d39 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -656,8 +656,24 @@ static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon, | |||
656 | struct mid_q_entry; | 656 | struct mid_q_entry; |
657 | 657 | ||
658 | /* | 658 | /* |
659 | * This is the prototype for the mid callback function. When creating one, | 659 | * This is the prototype for the mid receive function. This function is for |
660 | * take special care to avoid deadlocks. Things to bear in mind: | 660 | * receiving the rest of the SMB frame, starting with the WordCount (which is |
661 | * just after the MID in struct smb_hdr). Note: | ||
662 | * | ||
663 | * - This will be called by cifsd, with no locks held. | ||
664 | * - The mid will still be on the pending_mid_q. | ||
665 | * - mid->resp_buf will point to the current buffer. | ||
666 | * | ||
667 | * Returns zero on a successful receive, or an error. The receive state in | ||
668 | * the TCP_Server_Info will also be updated. | ||
669 | */ | ||
670 | typedef int (mid_receive_t)(struct TCP_Server_Info *server, | ||
671 | struct mid_q_entry *mid); | ||
672 | |||
673 | /* | ||
674 | * This is the prototype for the mid callback function. This is called once the | ||
675 | * mid has been received off of the socket. When creating one, take special | ||
676 | * care to avoid deadlocks. Things to bear in mind: | ||
661 | * | 677 | * |
662 | * - it will be called by cifsd, with no locks held | 678 | * - it will be called by cifsd, with no locks held |
663 | * - the mid will be removed from any lists | 679 | * - the mid will be removed from any lists |
@@ -675,9 +691,10 @@ struct mid_q_entry { | |||
675 | unsigned long when_sent; /* time when smb send finished */ | 691 | unsigned long when_sent; /* time when smb send finished */ |
676 | unsigned long when_received; /* when demux complete (taken off wire) */ | 692 | unsigned long when_received; /* when demux complete (taken off wire) */ |
677 | #endif | 693 | #endif |
694 | mid_receive_t *receive; /* call receive callback */ | ||
678 | mid_callback_t *callback; /* call completion callback */ | 695 | mid_callback_t *callback; /* call completion callback */ |
679 | void *callback_data; /* general purpose pointer for callback */ | 696 | void *callback_data; /* general purpose pointer for callback */ |
680 | struct smb_hdr *resp_buf; /* response buffer */ | 697 | struct smb_hdr *resp_buf; /* pointer to received SMB header */ |
681 | int midState; /* wish this were enum but can not pass to wait_event */ | 698 | int midState; /* wish this were enum but can not pass to wait_event */ |
682 | __u8 command; /* smb command code */ | 699 | __u8 command; /* smb command code */ |
683 | bool largeBuf:1; /* if valid response, is pointer to large buf */ | 700 | bool largeBuf:1; /* if valid response, is pointer to large buf */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index a1fa9cec05d6..8a7adb31ffed 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -69,8 +69,9 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer, | |||
69 | struct TCP_Server_Info *server); | 69 | struct TCP_Server_Info *server); |
70 | extern void DeleteMidQEntry(struct mid_q_entry *midEntry); | 70 | extern void DeleteMidQEntry(struct mid_q_entry *midEntry); |
71 | extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, | 71 | extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, |
72 | unsigned int nvec, mid_callback_t *callback, | 72 | unsigned int nvec, mid_receive_t *receive, |
73 | void *cbdata, bool ignore_pend); | 73 | mid_callback_t *callback, void *cbdata, |
74 | bool ignore_pend); | ||
74 | extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, | 75 | extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, |
75 | struct smb_hdr * /* input */ , | 76 | struct smb_hdr * /* input */ , |
76 | struct smb_hdr * /* out */ , | 77 | struct smb_hdr * /* out */ , |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index c824c106b2b7..0613df4d8e74 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -737,7 +737,8 @@ CIFSSMBEcho(struct TCP_Server_Info *server) | |||
737 | iov.iov_base = smb; | 737 | iov.iov_base = smb; |
738 | iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; | 738 | iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; |
739 | 739 | ||
740 | rc = cifs_call_async(server, &iov, 1, cifs_echo_callback, server, true); | 740 | rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback, |
741 | server, true); | ||
741 | if (rc) | 742 | if (rc) |
742 | cFYI(1, "Echo request failed: %d", rc); | 743 | cFYI(1, "Echo request failed: %d", rc); |
743 | 744 | ||
@@ -1834,7 +1835,7 @@ cifs_async_writev(struct cifs_writedata *wdata) | |||
1834 | 1835 | ||
1835 | kref_get(&wdata->refcount); | 1836 | kref_get(&wdata->refcount); |
1836 | rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1, | 1837 | rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1, |
1837 | cifs_writev_callback, wdata, false); | 1838 | NULL, cifs_writev_callback, wdata, false); |
1838 | 1839 | ||
1839 | if (rc == 0) | 1840 | if (rc == 0) |
1840 | cifs_stats_inc(&tcon->num_writes); | 1841 | cifs_stats_inc(&tcon->num_writes); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f05dedda37c6..eeee2f5d13ce 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -824,7 +824,11 @@ cifs_demultiplex_thread(void *p) | |||
824 | 824 | ||
825 | mid_entry = find_mid(server, smb_buffer); | 825 | mid_entry = find_mid(server, smb_buffer); |
826 | 826 | ||
827 | length = standard_receive3(server, mid_entry); | 827 | if (!mid_entry || !mid_entry->receive) |
828 | length = standard_receive3(server, mid_entry); | ||
829 | else | ||
830 | length = mid_entry->receive(server, mid_entry); | ||
831 | |||
828 | if (length < 0) | 832 | if (length < 0) |
829 | continue; | 833 | continue; |
830 | 834 | ||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 33a3fbf3a3a5..e7398d0cd054 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -339,8 +339,8 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) | |||
339 | */ | 339 | */ |
340 | int | 340 | int |
341 | cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, | 341 | cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, |
342 | unsigned int nvec, mid_callback_t *callback, void *cbdata, | 342 | unsigned int nvec, mid_receive_t *receive, |
343 | bool ignore_pend) | 343 | mid_callback_t *callback, void *cbdata, bool ignore_pend) |
344 | { | 344 | { |
345 | int rc; | 345 | int rc; |
346 | struct mid_q_entry *mid; | 346 | struct mid_q_entry *mid; |
@@ -374,6 +374,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, | |||
374 | goto out_err; | 374 | goto out_err; |
375 | } | 375 | } |
376 | 376 | ||
377 | mid->receive = receive; | ||
377 | mid->callback = callback; | 378 | mid->callback = callback; |
378 | mid->callback_data = cbdata; | 379 | mid->callback_data = cbdata; |
379 | mid->midState = MID_REQUEST_SUBMITTED; | 380 | mid->midState = MID_REQUEST_SUBMITTED; |