138c8a9a5SSteve French // SPDX-License-Identifier: LGPL-2.1
238c8a9a5SSteve French /*
338c8a9a5SSteve French *
438c8a9a5SSteve French * Copyright (C) International Business Machines Corp., 2002,2008
538c8a9a5SSteve French * Author(s): Steve French (sfrench@us.ibm.com)
638c8a9a5SSteve French * Jeremy Allison (jra@samba.org) 2006.
738c8a9a5SSteve French *
838c8a9a5SSteve French */
938c8a9a5SSteve French
1038c8a9a5SSteve French #include <linux/fs.h>
1138c8a9a5SSteve French #include <linux/list.h>
1238c8a9a5SSteve French #include <linux/gfp.h>
1338c8a9a5SSteve French #include <linux/wait.h>
1438c8a9a5SSteve French #include <linux/net.h>
1538c8a9a5SSteve French #include <linux/delay.h>
1638c8a9a5SSteve French #include <linux/freezer.h>
1738c8a9a5SSteve French #include <linux/tcp.h>
1838c8a9a5SSteve French #include <linux/bvec.h>
1938c8a9a5SSteve French #include <linux/highmem.h>
2038c8a9a5SSteve French #include <linux/uaccess.h>
212c75426cSSteve French #include <linux/processor.h>
2238c8a9a5SSteve French #include <linux/mempool.h>
2338c8a9a5SSteve French #include <linux/sched/signal.h>
2438c8a9a5SSteve French #include <linux/task_io_accounting_ops.h>
2538c8a9a5SSteve French #include "cifspdu.h"
2638c8a9a5SSteve French #include "cifsglob.h"
2738c8a9a5SSteve French #include "cifsproto.h"
2838c8a9a5SSteve French #include "cifs_debug.h"
2938c8a9a5SSteve French #include "smb2proto.h"
3038c8a9a5SSteve French #include "smbdirect.h"
3138c8a9a5SSteve French
3238c8a9a5SSteve French /* Max number of iovectors we can use off the stack when sending requests. */
3338c8a9a5SSteve French #define CIFS_MAX_IOV_SIZE 8
3438c8a9a5SSteve French
3538c8a9a5SSteve French void
cifs_wake_up_task(struct mid_q_entry * mid)3638c8a9a5SSteve French cifs_wake_up_task(struct mid_q_entry *mid)
3738c8a9a5SSteve French {
38d527f513SZhang Xiaoxu if (mid->mid_state == MID_RESPONSE_RECEIVED)
39d527f513SZhang Xiaoxu mid->mid_state = MID_RESPONSE_READY;
4038c8a9a5SSteve French wake_up_process(mid->callback_data);
4138c8a9a5SSteve French }
4238c8a9a5SSteve French
4338c8a9a5SSteve French static struct mid_q_entry *
alloc_mid(const struct smb_hdr * smb_buffer,struct TCP_Server_Info * server)4438c8a9a5SSteve French alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
4538c8a9a5SSteve French {
4638c8a9a5SSteve French struct mid_q_entry *temp;
4738c8a9a5SSteve French
4838c8a9a5SSteve French if (server == NULL) {
4938c8a9a5SSteve French cifs_dbg(VFS, "%s: null TCP session\n", __func__);
5038c8a9a5SSteve French return NULL;
5138c8a9a5SSteve French }
5238c8a9a5SSteve French
5338c8a9a5SSteve French temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
5438c8a9a5SSteve French memset(temp, 0, sizeof(struct mid_q_entry));
5538c8a9a5SSteve French kref_init(&temp->refcount);
5638c8a9a5SSteve French temp->mid = get_mid(smb_buffer);
5738c8a9a5SSteve French temp->pid = current->pid;
5838c8a9a5SSteve French temp->command = cpu_to_le16(smb_buffer->Command);
5938c8a9a5SSteve French cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command);
60a5998a9eS鑫华 /* easier to use jiffies */
6138c8a9a5SSteve French /* when mid allocated can be before when sent */
6238c8a9a5SSteve French temp->when_alloc = jiffies;
6338c8a9a5SSteve French temp->server = server;
6438c8a9a5SSteve French
6538c8a9a5SSteve French /*
6638c8a9a5SSteve French * The default is for the mid to be synchronous, so the
6738c8a9a5SSteve French * default callback just wakes up the current task.
6838c8a9a5SSteve French */
6938c8a9a5SSteve French get_task_struct(current);
7038c8a9a5SSteve French temp->creator = current;
7138c8a9a5SSteve French temp->callback = cifs_wake_up_task;
7238c8a9a5SSteve French temp->callback_data = current;
7338c8a9a5SSteve French
7438c8a9a5SSteve French atomic_inc(&mid_count);
7538c8a9a5SSteve French temp->mid_state = MID_REQUEST_ALLOCATED;
7638c8a9a5SSteve French return temp;
7738c8a9a5SSteve French }
7838c8a9a5SSteve French
__release_mid(struct kref * refcount)79c1a5962fSPaulo Alcantara void __release_mid(struct kref *refcount)
8038c8a9a5SSteve French {
8138c8a9a5SSteve French struct mid_q_entry *midEntry =
8238c8a9a5SSteve French container_of(refcount, struct mid_q_entry, refcount);
8338c8a9a5SSteve French #ifdef CONFIG_CIFS_STATS2
8438c8a9a5SSteve French __le16 command = midEntry->server->vals->lock_cmd;
8538c8a9a5SSteve French __u16 smb_cmd = le16_to_cpu(midEntry->command);
8638c8a9a5SSteve French unsigned long now;
8738c8a9a5SSteve French unsigned long roundtrip_time;
8838c8a9a5SSteve French #endif
8938c8a9a5SSteve French struct TCP_Server_Info *server = midEntry->server;
9038c8a9a5SSteve French
9138c8a9a5SSteve French if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) &&
92d527f513SZhang Xiaoxu (midEntry->mid_state == MID_RESPONSE_RECEIVED ||
93d527f513SZhang Xiaoxu midEntry->mid_state == MID_RESPONSE_READY) &&
9438c8a9a5SSteve French server->ops->handle_cancelled_mid)
9538c8a9a5SSteve French server->ops->handle_cancelled_mid(midEntry, server);
9638c8a9a5SSteve French
9738c8a9a5SSteve French midEntry->mid_state = MID_FREE;
9838c8a9a5SSteve French atomic_dec(&mid_count);
9938c8a9a5SSteve French if (midEntry->large_buf)
10038c8a9a5SSteve French cifs_buf_release(midEntry->resp_buf);
10138c8a9a5SSteve French else
10238c8a9a5SSteve French cifs_small_buf_release(midEntry->resp_buf);
10338c8a9a5SSteve French #ifdef CONFIG_CIFS_STATS2
10438c8a9a5SSteve French now = jiffies;
10538c8a9a5SSteve French if (now < midEntry->when_alloc)
10638c8a9a5SSteve French cifs_server_dbg(VFS, "Invalid mid allocation time\n");
10738c8a9a5SSteve French roundtrip_time = now - midEntry->when_alloc;
10838c8a9a5SSteve French
10938c8a9a5SSteve French if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) {
11038c8a9a5SSteve French if (atomic_read(&server->num_cmds[smb_cmd]) == 0) {
11138c8a9a5SSteve French server->slowest_cmd[smb_cmd] = roundtrip_time;
11238c8a9a5SSteve French server->fastest_cmd[smb_cmd] = roundtrip_time;
11338c8a9a5SSteve French } else {
11438c8a9a5SSteve French if (server->slowest_cmd[smb_cmd] < roundtrip_time)
11538c8a9a5SSteve French server->slowest_cmd[smb_cmd] = roundtrip_time;
11638c8a9a5SSteve French else if (server->fastest_cmd[smb_cmd] > roundtrip_time)
11738c8a9a5SSteve French server->fastest_cmd[smb_cmd] = roundtrip_time;
11838c8a9a5SSteve French }
11938c8a9a5SSteve French cifs_stats_inc(&server->num_cmds[smb_cmd]);
12038c8a9a5SSteve French server->time_per_cmd[smb_cmd] += roundtrip_time;
12138c8a9a5SSteve French }
12238c8a9a5SSteve French /*
12338c8a9a5SSteve French * commands taking longer than one second (default) can be indications
12438c8a9a5SSteve French * that something is wrong, unless it is quite a slow link or a very
12538c8a9a5SSteve French * busy server. Note that this calc is unlikely or impossible to wrap
12638c8a9a5SSteve French * as long as slow_rsp_threshold is not set way above recommended max
12738c8a9a5SSteve French * value (32767 ie 9 hours) and is generally harmless even if wrong
12838c8a9a5SSteve French * since only affects debug counters - so leaving the calc as simple
12938c8a9a5SSteve French * comparison rather than doing multiple conversions and overflow
13038c8a9a5SSteve French * checks
13138c8a9a5SSteve French */
13238c8a9a5SSteve French if ((slow_rsp_threshold != 0) &&
13338c8a9a5SSteve French time_after(now, midEntry->when_alloc + (slow_rsp_threshold * HZ)) &&
13438c8a9a5SSteve French (midEntry->command != command)) {
13538c8a9a5SSteve French /*
13638c8a9a5SSteve French * smb2slowcmd[NUMBER_OF_SMB2_COMMANDS] counts by command
13738c8a9a5SSteve French * NB: le16_to_cpu returns unsigned so can not be negative below
13838c8a9a5SSteve French */
13938c8a9a5SSteve French if (smb_cmd < NUMBER_OF_SMB2_COMMANDS)
14038c8a9a5SSteve French cifs_stats_inc(&server->smb2slowcmd[smb_cmd]);
14138c8a9a5SSteve French
14238c8a9a5SSteve French trace_smb3_slow_rsp(smb_cmd, midEntry->mid, midEntry->pid,
14338c8a9a5SSteve French midEntry->when_sent, midEntry->when_received);
14438c8a9a5SSteve French if (cifsFYI & CIFS_TIMER) {
14538c8a9a5SSteve French pr_debug("slow rsp: cmd %d mid %llu",
14638c8a9a5SSteve French midEntry->command, midEntry->mid);
14738c8a9a5SSteve French cifs_info("A: 0x%lx S: 0x%lx R: 0x%lx\n",
14838c8a9a5SSteve French now - midEntry->when_alloc,
14938c8a9a5SSteve French now - midEntry->when_sent,
15038c8a9a5SSteve French now - midEntry->when_received);
15138c8a9a5SSteve French }
15238c8a9a5SSteve French }
15338c8a9a5SSteve French #endif
15438c8a9a5SSteve French put_task_struct(midEntry->creator);
15538c8a9a5SSteve French
15638c8a9a5SSteve French mempool_free(midEntry, cifs_mid_poolp);
15738c8a9a5SSteve French }
15838c8a9a5SSteve French
15938c8a9a5SSteve French void
delete_mid(struct mid_q_entry * mid)16038c8a9a5SSteve French delete_mid(struct mid_q_entry *mid)
16138c8a9a5SSteve French {
16238c8a9a5SSteve French spin_lock(&mid->server->mid_lock);
16338c8a9a5SSteve French if (!(mid->mid_flags & MID_DELETED)) {
16438c8a9a5SSteve French list_del_init(&mid->qhead);
16538c8a9a5SSteve French mid->mid_flags |= MID_DELETED;
16638c8a9a5SSteve French }
16738c8a9a5SSteve French spin_unlock(&mid->server->mid_lock);
16838c8a9a5SSteve French
16938c8a9a5SSteve French release_mid(mid);
17038c8a9a5SSteve French }
17138c8a9a5SSteve French
17238c8a9a5SSteve French /*
17338c8a9a5SSteve French * smb_send_kvec - send an array of kvecs to the server
17438c8a9a5SSteve French * @server: Server to send the data to
17538c8a9a5SSteve French * @smb_msg: Message to send
17638c8a9a5SSteve French * @sent: amount of data sent on socket is stored here
17738c8a9a5SSteve French *
17838c8a9a5SSteve French * Our basic "send data to server" function. Should be called with srv_mutex
17938c8a9a5SSteve French * held. The caller is responsible for handling the results.
18038c8a9a5SSteve French */
18138c8a9a5SSteve French static int
smb_send_kvec(struct TCP_Server_Info * server,struct msghdr * smb_msg,size_t * sent)18238c8a9a5SSteve French smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
18338c8a9a5SSteve French size_t *sent)
18438c8a9a5SSteve French {
18538c8a9a5SSteve French int rc = 0;
18638c8a9a5SSteve French int retries = 0;
18738c8a9a5SSteve French struct socket *ssocket = server->ssocket;
18838c8a9a5SSteve French
18938c8a9a5SSteve French *sent = 0;
19038c8a9a5SSteve French
19138c8a9a5SSteve French if (server->noblocksnd)
19238c8a9a5SSteve French smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
19338c8a9a5SSteve French else
19438c8a9a5SSteve French smb_msg->msg_flags = MSG_NOSIGNAL;
19538c8a9a5SSteve French
19638c8a9a5SSteve French while (msg_data_left(smb_msg)) {
19738c8a9a5SSteve French /*
19838c8a9a5SSteve French * If blocking send, we try 3 times, since each can block
19938c8a9a5SSteve French * for 5 seconds. For nonblocking we have to try more
20038c8a9a5SSteve French * but wait increasing amounts of time allowing time for
20138c8a9a5SSteve French * socket to clear. The overall time we wait in either
20238c8a9a5SSteve French * case to send on the socket is about 15 seconds.
20338c8a9a5SSteve French * Similarly we wait for 15 seconds for a response from
20438c8a9a5SSteve French * the server in SendReceive[2] for the server to send
20538c8a9a5SSteve French * a response back for most types of requests (except
20638c8a9a5SSteve French * SMB Write past end of file which can be slow, and
20738c8a9a5SSteve French * blocking lock operations). NFS waits slightly longer
20838c8a9a5SSteve French * than CIFS, but this can make it take longer for
20938c8a9a5SSteve French * nonresponsive servers to be detected and 15 seconds
21038c8a9a5SSteve French * is more than enough time for modern networks to
21138c8a9a5SSteve French * send a packet. In most cases if we fail to send
21238c8a9a5SSteve French * after the retries we will kill the socket and
21338c8a9a5SSteve French * reconnect which may clear the network problem.
21438c8a9a5SSteve French */
21538c8a9a5SSteve French rc = sock_sendmsg(ssocket, smb_msg);
21638c8a9a5SSteve French if (rc == -EAGAIN) {
21738c8a9a5SSteve French retries++;
21838c8a9a5SSteve French if (retries >= 14 ||
21938c8a9a5SSteve French (!server->noblocksnd && (retries > 2))) {
22038c8a9a5SSteve French cifs_server_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
22138c8a9a5SSteve French ssocket);
22238c8a9a5SSteve French return -EAGAIN;
22338c8a9a5SSteve French }
22438c8a9a5SSteve French msleep(1 << retries);
22538c8a9a5SSteve French continue;
22638c8a9a5SSteve French }
22738c8a9a5SSteve French
22838c8a9a5SSteve French if (rc < 0)
22938c8a9a5SSteve French return rc;
23038c8a9a5SSteve French
23138c8a9a5SSteve French if (rc == 0) {
23238c8a9a5SSteve French /* should never happen, letting socket clear before
23338c8a9a5SSteve French retrying is our only obvious option here */
23438c8a9a5SSteve French cifs_server_dbg(VFS, "tcp sent no data\n");
23538c8a9a5SSteve French msleep(500);
23638c8a9a5SSteve French continue;
23738c8a9a5SSteve French }
23838c8a9a5SSteve French
23938c8a9a5SSteve French /* send was at least partially successful */
24038c8a9a5SSteve French *sent += rc;
24138c8a9a5SSteve French retries = 0; /* in case we get ENOSPC on the next send */
24238c8a9a5SSteve French }
24338c8a9a5SSteve French return 0;
24438c8a9a5SSteve French }
24538c8a9a5SSteve French
24638c8a9a5SSteve French unsigned long
smb_rqst_len(struct TCP_Server_Info * server,struct smb_rqst * rqst)24738c8a9a5SSteve French smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst)
24838c8a9a5SSteve French {
24938c8a9a5SSteve French unsigned int i;
25038c8a9a5SSteve French struct kvec *iov;
25138c8a9a5SSteve French int nvec;
25238c8a9a5SSteve French unsigned long buflen = 0;
25338c8a9a5SSteve French
25438c8a9a5SSteve French if (!is_smb1(server) && rqst->rq_nvec >= 2 &&
25538c8a9a5SSteve French rqst->rq_iov[0].iov_len == 4) {
25638c8a9a5SSteve French iov = &rqst->rq_iov[1];
25738c8a9a5SSteve French nvec = rqst->rq_nvec - 1;
25838c8a9a5SSteve French } else {
25938c8a9a5SSteve French iov = rqst->rq_iov;
26038c8a9a5SSteve French nvec = rqst->rq_nvec;
26138c8a9a5SSteve French }
26238c8a9a5SSteve French
26338c8a9a5SSteve French /* total up iov array first */
26438c8a9a5SSteve French for (i = 0; i < nvec; i++)
26538c8a9a5SSteve French buflen += iov[i].iov_len;
26638c8a9a5SSteve French
26738c8a9a5SSteve French buflen += iov_iter_count(&rqst->rq_iter);
26838c8a9a5SSteve French return buflen;
26938c8a9a5SSteve French }
27038c8a9a5SSteve French
27138c8a9a5SSteve French static int
__smb_send_rqst(struct TCP_Server_Info * server,int num_rqst,struct smb_rqst * rqst)27238c8a9a5SSteve French __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
27338c8a9a5SSteve French struct smb_rqst *rqst)
27438c8a9a5SSteve French {
27538c8a9a5SSteve French int rc;
27638c8a9a5SSteve French struct kvec *iov;
27738c8a9a5SSteve French int n_vec;
27838c8a9a5SSteve French unsigned int send_length = 0;
27938c8a9a5SSteve French unsigned int i, j;
28038c8a9a5SSteve French sigset_t mask, oldmask;
28138c8a9a5SSteve French size_t total_len = 0, sent, size;
28238c8a9a5SSteve French struct socket *ssocket = server->ssocket;
28338c8a9a5SSteve French struct msghdr smb_msg = {};
28438c8a9a5SSteve French __be32 rfc1002_marker;
28538c8a9a5SSteve French
28638c8a9a5SSteve French cifs_in_send_inc(server);
28738c8a9a5SSteve French if (cifs_rdma_enabled(server)) {
28838c8a9a5SSteve French /* return -EAGAIN when connecting or reconnecting */
28938c8a9a5SSteve French rc = -EAGAIN;
29038c8a9a5SSteve French if (server->smbd_conn)
29138c8a9a5SSteve French rc = smbd_send(server, num_rqst, rqst);
29238c8a9a5SSteve French goto smbd_done;
29338c8a9a5SSteve French }
29438c8a9a5SSteve French
29538c8a9a5SSteve French rc = -EAGAIN;
29638c8a9a5SSteve French if (ssocket == NULL)
29738c8a9a5SSteve French goto out;
29838c8a9a5SSteve French
29938c8a9a5SSteve French rc = -ERESTARTSYS;
30038c8a9a5SSteve French if (fatal_signal_pending(current)) {
30138c8a9a5SSteve French cifs_dbg(FYI, "signal pending before send request\n");
30238c8a9a5SSteve French goto out;
30338c8a9a5SSteve French }
30438c8a9a5SSteve French
30538c8a9a5SSteve French rc = 0;
30638c8a9a5SSteve French /* cork the socket */
30738c8a9a5SSteve French tcp_sock_set_cork(ssocket->sk, true);
30838c8a9a5SSteve French
30938c8a9a5SSteve French for (j = 0; j < num_rqst; j++)
31038c8a9a5SSteve French send_length += smb_rqst_len(server, &rqst[j]);
31138c8a9a5SSteve French rfc1002_marker = cpu_to_be32(send_length);
31238c8a9a5SSteve French
31338c8a9a5SSteve French /*
31438c8a9a5SSteve French * We should not allow signals to interrupt the network send because
31538c8a9a5SSteve French * any partial send will cause session reconnects thus increasing
31638c8a9a5SSteve French * latency of system calls and overload a server with unnecessary
31738c8a9a5SSteve French * requests.
31838c8a9a5SSteve French */
31938c8a9a5SSteve French
32038c8a9a5SSteve French sigfillset(&mask);
32138c8a9a5SSteve French sigprocmask(SIG_BLOCK, &mask, &oldmask);
32238c8a9a5SSteve French
32338c8a9a5SSteve French /* Generate a rfc1002 marker for SMB2+ */
32438c8a9a5SSteve French if (!is_smb1(server)) {
32538c8a9a5SSteve French struct kvec hiov = {
32638c8a9a5SSteve French .iov_base = &rfc1002_marker,
32738c8a9a5SSteve French .iov_len = 4
32838c8a9a5SSteve French };
32938c8a9a5SSteve French iov_iter_kvec(&smb_msg.msg_iter, ITER_SOURCE, &hiov, 1, 4);
33038c8a9a5SSteve French rc = smb_send_kvec(server, &smb_msg, &sent);
33138c8a9a5SSteve French if (rc < 0)
33238c8a9a5SSteve French goto unmask;
33338c8a9a5SSteve French
33438c8a9a5SSteve French total_len += sent;
33538c8a9a5SSteve French send_length += 4;
33638c8a9a5SSteve French }
33738c8a9a5SSteve French
33838c8a9a5SSteve French cifs_dbg(FYI, "Sending smb: smb_len=%u\n", send_length);
33938c8a9a5SSteve French
34038c8a9a5SSteve French for (j = 0; j < num_rqst; j++) {
34138c8a9a5SSteve French iov = rqst[j].rq_iov;
34238c8a9a5SSteve French n_vec = rqst[j].rq_nvec;
34338c8a9a5SSteve French
34438c8a9a5SSteve French size = 0;
34538c8a9a5SSteve French for (i = 0; i < n_vec; i++) {
34638c8a9a5SSteve French dump_smb(iov[i].iov_base, iov[i].iov_len);
34738c8a9a5SSteve French size += iov[i].iov_len;
34838c8a9a5SSteve French }
34938c8a9a5SSteve French
35038c8a9a5SSteve French iov_iter_kvec(&smb_msg.msg_iter, ITER_SOURCE, iov, n_vec, size);
35138c8a9a5SSteve French
35238c8a9a5SSteve French rc = smb_send_kvec(server, &smb_msg, &sent);
35338c8a9a5SSteve French if (rc < 0)
35438c8a9a5SSteve French goto unmask;
35538c8a9a5SSteve French
35638c8a9a5SSteve French total_len += sent;
35738c8a9a5SSteve French
35838c8a9a5SSteve French if (iov_iter_count(&rqst[j].rq_iter) > 0) {
35938c8a9a5SSteve French smb_msg.msg_iter = rqst[j].rq_iter;
36038c8a9a5SSteve French rc = smb_send_kvec(server, &smb_msg, &sent);
36138c8a9a5SSteve French if (rc < 0)
36238c8a9a5SSteve French break;
36338c8a9a5SSteve French total_len += sent;
36438c8a9a5SSteve French }
36538c8a9a5SSteve French
36638c8a9a5SSteve French }
36738c8a9a5SSteve French
36838c8a9a5SSteve French unmask:
36938c8a9a5SSteve French sigprocmask(SIG_SETMASK, &oldmask, NULL);
37038c8a9a5SSteve French
37138c8a9a5SSteve French /*
37238c8a9a5SSteve French * If signal is pending but we have already sent the whole packet to
37338c8a9a5SSteve French * the server we need to return success status to allow a corresponding
37438c8a9a5SSteve French * mid entry to be kept in the pending requests queue thus allowing
37538c8a9a5SSteve French * to handle responses from the server by the client.
37638c8a9a5SSteve French *
37738c8a9a5SSteve French * If only part of the packet has been sent there is no need to hide
37838c8a9a5SSteve French * interrupt because the session will be reconnected anyway, so there
37938c8a9a5SSteve French * won't be any response from the server to handle.
38038c8a9a5SSteve French */
38138c8a9a5SSteve French
38238c8a9a5SSteve French if (signal_pending(current) && (total_len != send_length)) {
38338c8a9a5SSteve French cifs_dbg(FYI, "signal is pending after attempt to send\n");
38438c8a9a5SSteve French rc = -ERESTARTSYS;
38538c8a9a5SSteve French }
38638c8a9a5SSteve French
38738c8a9a5SSteve French /* uncork it */
38838c8a9a5SSteve French tcp_sock_set_cork(ssocket->sk, false);
38938c8a9a5SSteve French
39038c8a9a5SSteve French if ((total_len > 0) && (total_len != send_length)) {
39138c8a9a5SSteve French cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",
39238c8a9a5SSteve French send_length, total_len);
39338c8a9a5SSteve French /*
39438c8a9a5SSteve French * If we have only sent part of an SMB then the next SMB could
39538c8a9a5SSteve French * be taken as the remainder of this one. We need to kill the
39638c8a9a5SSteve French * socket so the server throws away the partial SMB
39738c8a9a5SSteve French */
39838c8a9a5SSteve French cifs_signal_cifsd_for_reconnect(server, false);
39938c8a9a5SSteve French trace_smb3_partial_send_reconnect(server->CurrentMid,
40038c8a9a5SSteve French server->conn_id, server->hostname);
40138c8a9a5SSteve French }
40238c8a9a5SSteve French smbd_done:
403c09de6bbSShyam Prasad N /*
404c09de6bbSShyam Prasad N * there's hardly any use for the layers above to know the
405c09de6bbSShyam Prasad N * actual error code here. All they should do at this point is
406c09de6bbSShyam Prasad N * to retry the connection and hope it goes away.
407c09de6bbSShyam Prasad N */
408c09de6bbSShyam Prasad N if (rc < 0 && rc != -EINTR && rc != -EAGAIN) {
40938c8a9a5SSteve French cifs_server_dbg(VFS, "Error %d sending data on socket to server\n",
41038c8a9a5SSteve French rc);
411c09de6bbSShyam Prasad N rc = -ECONNABORTED;
412c09de6bbSShyam Prasad N cifs_signal_cifsd_for_reconnect(server, false);
413c09de6bbSShyam Prasad N } else if (rc > 0)
41438c8a9a5SSteve French rc = 0;
41538c8a9a5SSteve French out:
41638c8a9a5SSteve French cifs_in_send_dec(server);
41738c8a9a5SSteve French return rc;
41838c8a9a5SSteve French }
41938c8a9a5SSteve French
420933148a4SPaulo Alcantara struct send_req_vars {
421933148a4SPaulo Alcantara struct smb2_transform_hdr tr_hdr;
422933148a4SPaulo Alcantara struct smb_rqst rqst[MAX_COMPOUND];
423933148a4SPaulo Alcantara struct kvec iov;
424933148a4SPaulo Alcantara };
425933148a4SPaulo Alcantara
42638c8a9a5SSteve French static int
smb_send_rqst(struct TCP_Server_Info * server,int num_rqst,struct smb_rqst * rqst,int flags)42738c8a9a5SSteve French smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
42838c8a9a5SSteve French struct smb_rqst *rqst, int flags)
42938c8a9a5SSteve French {
430933148a4SPaulo Alcantara struct send_req_vars *vars;
431933148a4SPaulo Alcantara struct smb_rqst *cur_rqst;
432933148a4SPaulo Alcantara struct kvec *iov;
43338c8a9a5SSteve French int rc;
43438c8a9a5SSteve French
43538c8a9a5SSteve French if (!(flags & CIFS_TRANSFORM_REQ))
43638c8a9a5SSteve French return __smb_send_rqst(server, num_rqst, rqst);
43738c8a9a5SSteve French
4382fdb5551SPaulo Alcantara if (WARN_ON_ONCE(num_rqst > MAX_COMPOUND - 1))
4392fdb5551SPaulo Alcantara return -EIO;
44038c8a9a5SSteve French
44138c8a9a5SSteve French if (!server->ops->init_transform_rq) {
44238c8a9a5SSteve French cifs_server_dbg(VFS, "Encryption requested but transform callback is missing\n");
44338c8a9a5SSteve French return -EIO;
44438c8a9a5SSteve French }
44538c8a9a5SSteve French
446933148a4SPaulo Alcantara vars = kzalloc(sizeof(*vars), GFP_NOFS);
447933148a4SPaulo Alcantara if (!vars)
44838c8a9a5SSteve French return -ENOMEM;
449933148a4SPaulo Alcantara cur_rqst = vars->rqst;
450933148a4SPaulo Alcantara iov = &vars->iov;
45138c8a9a5SSteve French
452933148a4SPaulo Alcantara iov->iov_base = &vars->tr_hdr;
453933148a4SPaulo Alcantara iov->iov_len = sizeof(vars->tr_hdr);
454933148a4SPaulo Alcantara cur_rqst[0].rq_iov = iov;
45538c8a9a5SSteve French cur_rqst[0].rq_nvec = 1;
45638c8a9a5SSteve French
45738c8a9a5SSteve French rc = server->ops->init_transform_rq(server, num_rqst + 1,
45838c8a9a5SSteve French &cur_rqst[0], rqst);
45938c8a9a5SSteve French if (rc)
46038c8a9a5SSteve French goto out;
46138c8a9a5SSteve French
46238c8a9a5SSteve French rc = __smb_send_rqst(server, num_rqst + 1, &cur_rqst[0]);
46338c8a9a5SSteve French smb3_free_compound_rqst(num_rqst, &cur_rqst[1]);
46438c8a9a5SSteve French out:
465933148a4SPaulo Alcantara kfree(vars);
46638c8a9a5SSteve French return rc;
46738c8a9a5SSteve French }
46838c8a9a5SSteve French
46938c8a9a5SSteve French int
smb_send(struct TCP_Server_Info * server,struct smb_hdr * smb_buffer,unsigned int smb_buf_length)47038c8a9a5SSteve French smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
47138c8a9a5SSteve French unsigned int smb_buf_length)
47238c8a9a5SSteve French {
47338c8a9a5SSteve French struct kvec iov[2];
47438c8a9a5SSteve French struct smb_rqst rqst = { .rq_iov = iov,
47538c8a9a5SSteve French .rq_nvec = 2 };
47638c8a9a5SSteve French
47738c8a9a5SSteve French iov[0].iov_base = smb_buffer;
47838c8a9a5SSteve French iov[0].iov_len = 4;
47938c8a9a5SSteve French iov[1].iov_base = (char *)smb_buffer + 4;
48038c8a9a5SSteve French iov[1].iov_len = smb_buf_length;
48138c8a9a5SSteve French
48238c8a9a5SSteve French return __smb_send_rqst(server, 1, &rqst);
48338c8a9a5SSteve French }
48438c8a9a5SSteve French
48538c8a9a5SSteve French static int
wait_for_free_credits(struct TCP_Server_Info * server,const int num_credits,const int timeout,const int flags,unsigned int * instance)48638c8a9a5SSteve French wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
48738c8a9a5SSteve French const int timeout, const int flags,
48838c8a9a5SSteve French unsigned int *instance)
48938c8a9a5SSteve French {
49038c8a9a5SSteve French long rc;
49138c8a9a5SSteve French int *credits;
49238c8a9a5SSteve French int optype;
49338c8a9a5SSteve French long int t;
49438c8a9a5SSteve French int scredits, in_flight;
49538c8a9a5SSteve French
49638c8a9a5SSteve French if (timeout < 0)
49738c8a9a5SSteve French t = MAX_JIFFY_OFFSET;
49838c8a9a5SSteve French else
49938c8a9a5SSteve French t = msecs_to_jiffies(timeout);
50038c8a9a5SSteve French
50138c8a9a5SSteve French optype = flags & CIFS_OP_MASK;
50238c8a9a5SSteve French
50338c8a9a5SSteve French *instance = 0;
50438c8a9a5SSteve French
50538c8a9a5SSteve French credits = server->ops->get_credits_field(server, optype);
50638c8a9a5SSteve French /* Since an echo is already inflight, no need to wait to send another */
50738c8a9a5SSteve French if (*credits <= 0 && optype == CIFS_ECHO_OP)
50838c8a9a5SSteve French return -EAGAIN;
50938c8a9a5SSteve French
51038c8a9a5SSteve French spin_lock(&server->req_lock);
51138c8a9a5SSteve French if ((flags & CIFS_TIMEOUT_MASK) == CIFS_NON_BLOCKING) {
51238c8a9a5SSteve French /* oplock breaks must not be held up */
51338c8a9a5SSteve French server->in_flight++;
51438c8a9a5SSteve French if (server->in_flight > server->max_in_flight)
51538c8a9a5SSteve French server->max_in_flight = server->in_flight;
51638c8a9a5SSteve French *credits -= 1;
51738c8a9a5SSteve French *instance = server->reconnect_instance;
51838c8a9a5SSteve French scredits = *credits;
51938c8a9a5SSteve French in_flight = server->in_flight;
52038c8a9a5SSteve French spin_unlock(&server->req_lock);
52138c8a9a5SSteve French
52238c8a9a5SSteve French trace_smb3_nblk_credits(server->CurrentMid,
52338c8a9a5SSteve French server->conn_id, server->hostname, scredits, -1, in_flight);
52438c8a9a5SSteve French cifs_dbg(FYI, "%s: remove %u credits total=%d\n",
52538c8a9a5SSteve French __func__, 1, scredits);
52638c8a9a5SSteve French
52738c8a9a5SSteve French return 0;
52838c8a9a5SSteve French }
52938c8a9a5SSteve French
53038c8a9a5SSteve French while (1) {
531326a8d04SShyam Prasad N spin_unlock(&server->req_lock);
532326a8d04SShyam Prasad N
533326a8d04SShyam Prasad N spin_lock(&server->srv_lock);
534326a8d04SShyam Prasad N if (server->tcpStatus == CifsExiting) {
535326a8d04SShyam Prasad N spin_unlock(&server->srv_lock);
536326a8d04SShyam Prasad N return -ENOENT;
537326a8d04SShyam Prasad N }
538326a8d04SShyam Prasad N spin_unlock(&server->srv_lock);
539326a8d04SShyam Prasad N
540326a8d04SShyam Prasad N spin_lock(&server->req_lock);
54138c8a9a5SSteve French if (*credits < num_credits) {
54238c8a9a5SSteve French scredits = *credits;
54338c8a9a5SSteve French spin_unlock(&server->req_lock);
54438c8a9a5SSteve French
54538c8a9a5SSteve French cifs_num_waiters_inc(server);
54638c8a9a5SSteve French rc = wait_event_killable_timeout(server->request_q,
54738c8a9a5SSteve French has_credits(server, credits, num_credits), t);
54838c8a9a5SSteve French cifs_num_waiters_dec(server);
54938c8a9a5SSteve French if (!rc) {
55038c8a9a5SSteve French spin_lock(&server->req_lock);
55138c8a9a5SSteve French scredits = *credits;
55238c8a9a5SSteve French in_flight = server->in_flight;
55338c8a9a5SSteve French spin_unlock(&server->req_lock);
55438c8a9a5SSteve French
55538c8a9a5SSteve French trace_smb3_credit_timeout(server->CurrentMid,
55638c8a9a5SSteve French server->conn_id, server->hostname, scredits,
55738c8a9a5SSteve French num_credits, in_flight);
55838c8a9a5SSteve French cifs_server_dbg(VFS, "wait timed out after %d ms\n",
55938c8a9a5SSteve French timeout);
56038c8a9a5SSteve French return -EBUSY;
56138c8a9a5SSteve French }
56238c8a9a5SSteve French if (rc == -ERESTARTSYS)
56338c8a9a5SSteve French return -ERESTARTSYS;
56438c8a9a5SSteve French spin_lock(&server->req_lock);
56538c8a9a5SSteve French } else {
56638c8a9a5SSteve French /*
56738c8a9a5SSteve French * For normal commands, reserve the last MAX_COMPOUND
56838c8a9a5SSteve French * credits to compound requests.
56938c8a9a5SSteve French * Otherwise these compounds could be permanently
57038c8a9a5SSteve French * starved for credits by single-credit requests.
57138c8a9a5SSteve French *
57238c8a9a5SSteve French * To prevent spinning CPU, block this thread until
57338c8a9a5SSteve French * there are >MAX_COMPOUND credits available.
57438c8a9a5SSteve French * But only do this is we already have a lot of
57538c8a9a5SSteve French * credits in flight to avoid triggering this check
57638c8a9a5SSteve French * for servers that are slow to hand out credits on
57738c8a9a5SSteve French * new sessions.
57838c8a9a5SSteve French */
57938c8a9a5SSteve French if (!optype && num_credits == 1 &&
58038c8a9a5SSteve French server->in_flight > 2 * MAX_COMPOUND &&
58138c8a9a5SSteve French *credits <= MAX_COMPOUND) {
58238c8a9a5SSteve French spin_unlock(&server->req_lock);
58338c8a9a5SSteve French
58438c8a9a5SSteve French cifs_num_waiters_inc(server);
58538c8a9a5SSteve French rc = wait_event_killable_timeout(
58638c8a9a5SSteve French server->request_q,
58738c8a9a5SSteve French has_credits(server, credits,
58838c8a9a5SSteve French MAX_COMPOUND + 1),
58938c8a9a5SSteve French t);
59038c8a9a5SSteve French cifs_num_waiters_dec(server);
59138c8a9a5SSteve French if (!rc) {
59238c8a9a5SSteve French spin_lock(&server->req_lock);
59338c8a9a5SSteve French scredits = *credits;
59438c8a9a5SSteve French in_flight = server->in_flight;
59538c8a9a5SSteve French spin_unlock(&server->req_lock);
59638c8a9a5SSteve French
59738c8a9a5SSteve French trace_smb3_credit_timeout(
59838c8a9a5SSteve French server->CurrentMid,
59938c8a9a5SSteve French server->conn_id, server->hostname,
60038c8a9a5SSteve French scredits, num_credits, in_flight);
60138c8a9a5SSteve French cifs_server_dbg(VFS, "wait timed out after %d ms\n",
60238c8a9a5SSteve French timeout);
60338c8a9a5SSteve French return -EBUSY;
60438c8a9a5SSteve French }
60538c8a9a5SSteve French if (rc == -ERESTARTSYS)
60638c8a9a5SSteve French return -ERESTARTSYS;
60738c8a9a5SSteve French spin_lock(&server->req_lock);
60838c8a9a5SSteve French continue;
60938c8a9a5SSteve French }
61038c8a9a5SSteve French
61138c8a9a5SSteve French /*
61238c8a9a5SSteve French * Can not count locking commands against total
61338c8a9a5SSteve French * as they are allowed to block on server.
61438c8a9a5SSteve French */
61538c8a9a5SSteve French
61638c8a9a5SSteve French /* update # of requests on the wire to server */
61738c8a9a5SSteve French if ((flags & CIFS_TIMEOUT_MASK) != CIFS_BLOCKING_OP) {
61838c8a9a5SSteve French *credits -= num_credits;
61938c8a9a5SSteve French server->in_flight += num_credits;
62038c8a9a5SSteve French if (server->in_flight > server->max_in_flight)
62138c8a9a5SSteve French server->max_in_flight = server->in_flight;
62238c8a9a5SSteve French *instance = server->reconnect_instance;
62338c8a9a5SSteve French }
62438c8a9a5SSteve French scredits = *credits;
62538c8a9a5SSteve French in_flight = server->in_flight;
62638c8a9a5SSteve French spin_unlock(&server->req_lock);
62738c8a9a5SSteve French
62838c8a9a5SSteve French trace_smb3_waitff_credits(server->CurrentMid,
62938c8a9a5SSteve French server->conn_id, server->hostname, scredits,
63038c8a9a5SSteve French -(num_credits), in_flight);
63138c8a9a5SSteve French cifs_dbg(FYI, "%s: remove %u credits total=%d\n",
63238c8a9a5SSteve French __func__, num_credits, scredits);
63338c8a9a5SSteve French break;
63438c8a9a5SSteve French }
63538c8a9a5SSteve French }
63638c8a9a5SSteve French return 0;
63738c8a9a5SSteve French }
63838c8a9a5SSteve French
63938c8a9a5SSteve French static int
wait_for_free_request(struct TCP_Server_Info * server,const int flags,unsigned int * instance)64038c8a9a5SSteve French wait_for_free_request(struct TCP_Server_Info *server, const int flags,
64138c8a9a5SSteve French unsigned int *instance)
64238c8a9a5SSteve French {
64338c8a9a5SSteve French return wait_for_free_credits(server, 1, -1, flags,
64438c8a9a5SSteve French instance);
64538c8a9a5SSteve French }
64638c8a9a5SSteve French
64738c8a9a5SSteve French static int
wait_for_compound_request(struct TCP_Server_Info * server,int num,const int flags,unsigned int * instance)64838c8a9a5SSteve French wait_for_compound_request(struct TCP_Server_Info *server, int num,
64938c8a9a5SSteve French const int flags, unsigned int *instance)
65038c8a9a5SSteve French {
65138c8a9a5SSteve French int *credits;
65238c8a9a5SSteve French int scredits, in_flight;
65338c8a9a5SSteve French
65438c8a9a5SSteve French credits = server->ops->get_credits_field(server, flags & CIFS_OP_MASK);
65538c8a9a5SSteve French
65638c8a9a5SSteve French spin_lock(&server->req_lock);
65738c8a9a5SSteve French scredits = *credits;
65838c8a9a5SSteve French in_flight = server->in_flight;
65938c8a9a5SSteve French
66038c8a9a5SSteve French if (*credits < num) {
66138c8a9a5SSteve French /*
66238c8a9a5SSteve French * If the server is tight on resources or just gives us less
66338c8a9a5SSteve French * credits for other reasons (e.g. requests are coming out of
66438c8a9a5SSteve French * order and the server delays granting more credits until it
66538c8a9a5SSteve French * processes a missing mid) and we exhausted most available
66638c8a9a5SSteve French * credits there may be situations when we try to send
66738c8a9a5SSteve French * a compound request but we don't have enough credits. At this
66838c8a9a5SSteve French * point the client needs to decide if it should wait for
66938c8a9a5SSteve French * additional credits or fail the request. If at least one
67038c8a9a5SSteve French * request is in flight there is a high probability that the
67138c8a9a5SSteve French * server will return enough credits to satisfy this compound
67238c8a9a5SSteve French * request.
67338c8a9a5SSteve French *
67438c8a9a5SSteve French * Return immediately if no requests in flight since we will be
67538c8a9a5SSteve French * stuck on waiting for credits.
67638c8a9a5SSteve French */
67738c8a9a5SSteve French if (server->in_flight == 0) {
67838c8a9a5SSteve French spin_unlock(&server->req_lock);
67938c8a9a5SSteve French trace_smb3_insufficient_credits(server->CurrentMid,
68038c8a9a5SSteve French server->conn_id, server->hostname, scredits,
68138c8a9a5SSteve French num, in_flight);
68238c8a9a5SSteve French cifs_dbg(FYI, "%s: %d requests in flight, needed %d total=%d\n",
68338c8a9a5SSteve French __func__, in_flight, num, scredits);
68438c8a9a5SSteve French return -EDEADLK;
68538c8a9a5SSteve French }
68638c8a9a5SSteve French }
68738c8a9a5SSteve French spin_unlock(&server->req_lock);
68838c8a9a5SSteve French
68938c8a9a5SSteve French return wait_for_free_credits(server, num, 60000, flags,
69038c8a9a5SSteve French instance);
69138c8a9a5SSteve French }
69238c8a9a5SSteve French
69338c8a9a5SSteve French int
cifs_wait_mtu_credits(struct TCP_Server_Info * server,unsigned int size,unsigned int * num,struct cifs_credits * credits)69438c8a9a5SSteve French cifs_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
69538c8a9a5SSteve French unsigned int *num, struct cifs_credits *credits)
69638c8a9a5SSteve French {
69738c8a9a5SSteve French *num = size;
69838c8a9a5SSteve French credits->value = 0;
69938c8a9a5SSteve French credits->instance = server->reconnect_instance;
70038c8a9a5SSteve French return 0;
70138c8a9a5SSteve French }
70238c8a9a5SSteve French
allocate_mid(struct cifs_ses * ses,struct smb_hdr * in_buf,struct mid_q_entry ** ppmidQ)70338c8a9a5SSteve French static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
70438c8a9a5SSteve French struct mid_q_entry **ppmidQ)
70538c8a9a5SSteve French {
70638c8a9a5SSteve French spin_lock(&ses->ses_lock);
70738c8a9a5SSteve French if (ses->ses_status == SES_NEW) {
70838c8a9a5SSteve French if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
70938c8a9a5SSteve French (in_buf->Command != SMB_COM_NEGOTIATE)) {
71038c8a9a5SSteve French spin_unlock(&ses->ses_lock);
71138c8a9a5SSteve French return -EAGAIN;
71238c8a9a5SSteve French }
71338c8a9a5SSteve French /* else ok - we are setting up session */
71438c8a9a5SSteve French }
71538c8a9a5SSteve French
71638c8a9a5SSteve French if (ses->ses_status == SES_EXITING) {
71738c8a9a5SSteve French /* check if SMB session is bad because we are setting it up */
71838c8a9a5SSteve French if (in_buf->Command != SMB_COM_LOGOFF_ANDX) {
71938c8a9a5SSteve French spin_unlock(&ses->ses_lock);
72038c8a9a5SSteve French return -EAGAIN;
72138c8a9a5SSteve French }
72238c8a9a5SSteve French /* else ok - we are shutting down session */
72338c8a9a5SSteve French }
72438c8a9a5SSteve French spin_unlock(&ses->ses_lock);
72538c8a9a5SSteve French
72638c8a9a5SSteve French *ppmidQ = alloc_mid(in_buf, ses->server);
72738c8a9a5SSteve French if (*ppmidQ == NULL)
72838c8a9a5SSteve French return -ENOMEM;
72938c8a9a5SSteve French spin_lock(&ses->server->mid_lock);
73038c8a9a5SSteve French list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
73138c8a9a5SSteve French spin_unlock(&ses->server->mid_lock);
73238c8a9a5SSteve French return 0;
73338c8a9a5SSteve French }
73438c8a9a5SSteve French
73538c8a9a5SSteve French static int
wait_for_response(struct TCP_Server_Info * server,struct mid_q_entry * midQ)73638c8a9a5SSteve French wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
73738c8a9a5SSteve French {
73838c8a9a5SSteve French int error;
73938c8a9a5SSteve French
74038c8a9a5SSteve French error = wait_event_state(server->response_q,
741d527f513SZhang Xiaoxu midQ->mid_state != MID_REQUEST_SUBMITTED &&
742d527f513SZhang Xiaoxu midQ->mid_state != MID_RESPONSE_RECEIVED,
74338c8a9a5SSteve French (TASK_KILLABLE|TASK_FREEZABLE_UNSAFE));
74438c8a9a5SSteve French if (error < 0)
74538c8a9a5SSteve French return -ERESTARTSYS;
74638c8a9a5SSteve French
74738c8a9a5SSteve French return 0;
74838c8a9a5SSteve French }
74938c8a9a5SSteve French
75038c8a9a5SSteve French struct mid_q_entry *
cifs_setup_async_request(struct TCP_Server_Info * server,struct smb_rqst * rqst)75138c8a9a5SSteve French cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
75238c8a9a5SSteve French {
75338c8a9a5SSteve French int rc;
75438c8a9a5SSteve French struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
75538c8a9a5SSteve French struct mid_q_entry *mid;
75638c8a9a5SSteve French
75738c8a9a5SSteve French if (rqst->rq_iov[0].iov_len != 4 ||
75838c8a9a5SSteve French rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
75938c8a9a5SSteve French return ERR_PTR(-EIO);
76038c8a9a5SSteve French
76138c8a9a5SSteve French /* enable signing if server requires it */
76238c8a9a5SSteve French if (server->sign)
76338c8a9a5SSteve French hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
76438c8a9a5SSteve French
76538c8a9a5SSteve French mid = alloc_mid(hdr, server);
76638c8a9a5SSteve French if (mid == NULL)
76738c8a9a5SSteve French return ERR_PTR(-ENOMEM);
76838c8a9a5SSteve French
76938c8a9a5SSteve French rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
77038c8a9a5SSteve French if (rc) {
77138c8a9a5SSteve French release_mid(mid);
77238c8a9a5SSteve French return ERR_PTR(rc);
77338c8a9a5SSteve French }
77438c8a9a5SSteve French
77538c8a9a5SSteve French return mid;
77638c8a9a5SSteve French }
77738c8a9a5SSteve French
77838c8a9a5SSteve French /*
77938c8a9a5SSteve French * Send a SMB request and set the callback function in the mid to handle
78038c8a9a5SSteve French * the result. Caller is responsible for dealing with timeouts.
78138c8a9a5SSteve French */
78238c8a9a5SSteve French int
cifs_call_async(struct TCP_Server_Info * server,struct smb_rqst * rqst,mid_receive_t * receive,mid_callback_t * callback,mid_handle_t * handle,void * cbdata,const int flags,const struct cifs_credits * exist_credits)78338c8a9a5SSteve French cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
78438c8a9a5SSteve French mid_receive_t *receive, mid_callback_t *callback,
78538c8a9a5SSteve French mid_handle_t *handle, void *cbdata, const int flags,
78638c8a9a5SSteve French const struct cifs_credits *exist_credits)
78738c8a9a5SSteve French {
78838c8a9a5SSteve French int rc;
78938c8a9a5SSteve French struct mid_q_entry *mid;
79038c8a9a5SSteve French struct cifs_credits credits = { .value = 0, .instance = 0 };
79138c8a9a5SSteve French unsigned int instance;
79238c8a9a5SSteve French int optype;
79338c8a9a5SSteve French
79438c8a9a5SSteve French optype = flags & CIFS_OP_MASK;
79538c8a9a5SSteve French
79638c8a9a5SSteve French if ((flags & CIFS_HAS_CREDITS) == 0) {
79738c8a9a5SSteve French rc = wait_for_free_request(server, flags, &instance);
79838c8a9a5SSteve French if (rc)
79938c8a9a5SSteve French return rc;
80038c8a9a5SSteve French credits.value = 1;
80138c8a9a5SSteve French credits.instance = instance;
80238c8a9a5SSteve French } else
80338c8a9a5SSteve French instance = exist_credits->instance;
80438c8a9a5SSteve French
80538c8a9a5SSteve French cifs_server_lock(server);
80638c8a9a5SSteve French
80738c8a9a5SSteve French /*
80838c8a9a5SSteve French * We can't use credits obtained from the previous session to send this
80938c8a9a5SSteve French * request. Check if there were reconnects after we obtained credits and
81038c8a9a5SSteve French * return -EAGAIN in such cases to let callers handle it.
81138c8a9a5SSteve French */
81238c8a9a5SSteve French if (instance != server->reconnect_instance) {
81338c8a9a5SSteve French cifs_server_unlock(server);
81438c8a9a5SSteve French add_credits_and_wake_if(server, &credits, optype);
81538c8a9a5SSteve French return -EAGAIN;
81638c8a9a5SSteve French }
81738c8a9a5SSteve French
81838c8a9a5SSteve French mid = server->ops->setup_async_request(server, rqst);
81938c8a9a5SSteve French if (IS_ERR(mid)) {
82038c8a9a5SSteve French cifs_server_unlock(server);
82138c8a9a5SSteve French add_credits_and_wake_if(server, &credits, optype);
82238c8a9a5SSteve French return PTR_ERR(mid);
82338c8a9a5SSteve French }
82438c8a9a5SSteve French
82538c8a9a5SSteve French mid->receive = receive;
82638c8a9a5SSteve French mid->callback = callback;
82738c8a9a5SSteve French mid->callback_data = cbdata;
82838c8a9a5SSteve French mid->handle = handle;
82938c8a9a5SSteve French mid->mid_state = MID_REQUEST_SUBMITTED;
83038c8a9a5SSteve French
83138c8a9a5SSteve French /* put it on the pending_mid_q */
83238c8a9a5SSteve French spin_lock(&server->mid_lock);
83338c8a9a5SSteve French list_add_tail(&mid->qhead, &server->pending_mid_q);
83438c8a9a5SSteve French spin_unlock(&server->mid_lock);
83538c8a9a5SSteve French
83638c8a9a5SSteve French /*
83738c8a9a5SSteve French * Need to store the time in mid before calling I/O. For call_async,
83838c8a9a5SSteve French * I/O response may come back and free the mid entry on another thread.
83938c8a9a5SSteve French */
84038c8a9a5SSteve French cifs_save_when_sent(mid);
84138c8a9a5SSteve French rc = smb_send_rqst(server, 1, rqst, flags);
84238c8a9a5SSteve French
84338c8a9a5SSteve French if (rc < 0) {
84438c8a9a5SSteve French revert_current_mid(server, mid->credits);
84538c8a9a5SSteve French server->sequence_number -= 2;
84638c8a9a5SSteve French delete_mid(mid);
84738c8a9a5SSteve French }
84838c8a9a5SSteve French
84938c8a9a5SSteve French cifs_server_unlock(server);
85038c8a9a5SSteve French
85138c8a9a5SSteve French if (rc == 0)
85238c8a9a5SSteve French return 0;
85338c8a9a5SSteve French
85438c8a9a5SSteve French add_credits_and_wake_if(server, &credits, optype);
85538c8a9a5SSteve French return rc;
85638c8a9a5SSteve French }
85738c8a9a5SSteve French
85838c8a9a5SSteve French /*
85938c8a9a5SSteve French *
86038c8a9a5SSteve French * Send an SMB Request. No response info (other than return code)
86138c8a9a5SSteve French * needs to be parsed.
86238c8a9a5SSteve French *
86338c8a9a5SSteve French * flags indicate the type of request buffer and how long to wait
86438c8a9a5SSteve French * and whether to log NT STATUS code (error) before mapping it to POSIX error
86538c8a9a5SSteve French *
86638c8a9a5SSteve French */
86738c8a9a5SSteve French int
SendReceiveNoRsp(const unsigned int xid,struct cifs_ses * ses,char * in_buf,int flags)86838c8a9a5SSteve French SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
86938c8a9a5SSteve French char *in_buf, int flags)
87038c8a9a5SSteve French {
87138c8a9a5SSteve French int rc;
87238c8a9a5SSteve French struct kvec iov[1];
87338c8a9a5SSteve French struct kvec rsp_iov;
87438c8a9a5SSteve French int resp_buf_type;
87538c8a9a5SSteve French
87638c8a9a5SSteve French iov[0].iov_base = in_buf;
87738c8a9a5SSteve French iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
87838c8a9a5SSteve French flags |= CIFS_NO_RSP_BUF;
87938c8a9a5SSteve French rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
88038c8a9a5SSteve French cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
88138c8a9a5SSteve French
88238c8a9a5SSteve French return rc;
88338c8a9a5SSteve French }
88438c8a9a5SSteve French
88538c8a9a5SSteve French static int
cifs_sync_mid_result(struct mid_q_entry * mid,struct TCP_Server_Info * server)88638c8a9a5SSteve French cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
88738c8a9a5SSteve French {
88838c8a9a5SSteve French int rc = 0;
88938c8a9a5SSteve French
89038c8a9a5SSteve French cifs_dbg(FYI, "%s: cmd=%d mid=%llu state=%d\n",
89138c8a9a5SSteve French __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state);
89238c8a9a5SSteve French
89338c8a9a5SSteve French spin_lock(&server->mid_lock);
89438c8a9a5SSteve French switch (mid->mid_state) {
895d527f513SZhang Xiaoxu case MID_RESPONSE_READY:
89638c8a9a5SSteve French spin_unlock(&server->mid_lock);
89738c8a9a5SSteve French return rc;
89838c8a9a5SSteve French case MID_RETRY_NEEDED:
89938c8a9a5SSteve French rc = -EAGAIN;
90038c8a9a5SSteve French break;
90138c8a9a5SSteve French case MID_RESPONSE_MALFORMED:
90238c8a9a5SSteve French rc = -EIO;
90338c8a9a5SSteve French break;
90438c8a9a5SSteve French case MID_SHUTDOWN:
90538c8a9a5SSteve French rc = -EHOSTDOWN;
90638c8a9a5SSteve French break;
90738c8a9a5SSteve French default:
90838c8a9a5SSteve French if (!(mid->mid_flags & MID_DELETED)) {
90938c8a9a5SSteve French list_del_init(&mid->qhead);
91038c8a9a5SSteve French mid->mid_flags |= MID_DELETED;
91138c8a9a5SSteve French }
912*699f8958SSteve French spin_unlock(&server->mid_lock);
91338c8a9a5SSteve French cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
91438c8a9a5SSteve French __func__, mid->mid, mid->mid_state);
91538c8a9a5SSteve French rc = -EIO;
916*699f8958SSteve French goto sync_mid_done;
91738c8a9a5SSteve French }
91838c8a9a5SSteve French spin_unlock(&server->mid_lock);
91938c8a9a5SSteve French
920*699f8958SSteve French sync_mid_done:
92138c8a9a5SSteve French release_mid(mid);
92238c8a9a5SSteve French return rc;
92338c8a9a5SSteve French }
92438c8a9a5SSteve French
92538c8a9a5SSteve French static inline int
send_cancel(struct TCP_Server_Info * server,struct smb_rqst * rqst,struct mid_q_entry * mid)92638c8a9a5SSteve French send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst,
92738c8a9a5SSteve French struct mid_q_entry *mid)
92838c8a9a5SSteve French {
92938c8a9a5SSteve French return server->ops->send_cancel ?
93038c8a9a5SSteve French server->ops->send_cancel(server, rqst, mid) : 0;
93138c8a9a5SSteve French }
93238c8a9a5SSteve French
93338c8a9a5SSteve French int
cifs_check_receive(struct mid_q_entry * mid,struct TCP_Server_Info * server,bool log_error)93438c8a9a5SSteve French cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
93538c8a9a5SSteve French bool log_error)
93638c8a9a5SSteve French {
93738c8a9a5SSteve French unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
93838c8a9a5SSteve French
93938c8a9a5SSteve French dump_smb(mid->resp_buf, min_t(u32, 92, len));
94038c8a9a5SSteve French
94138c8a9a5SSteve French /* convert the length into a more usable form */
94238c8a9a5SSteve French if (server->sign) {
94338c8a9a5SSteve French struct kvec iov[2];
94438c8a9a5SSteve French int rc = 0;
94538c8a9a5SSteve French struct smb_rqst rqst = { .rq_iov = iov,
94638c8a9a5SSteve French .rq_nvec = 2 };
94738c8a9a5SSteve French
94838c8a9a5SSteve French iov[0].iov_base = mid->resp_buf;
94938c8a9a5SSteve French iov[0].iov_len = 4;
95038c8a9a5SSteve French iov[1].iov_base = (char *)mid->resp_buf + 4;
95138c8a9a5SSteve French iov[1].iov_len = len - 4;
95238c8a9a5SSteve French /* FIXME: add code to kill session */
95338c8a9a5SSteve French rc = cifs_verify_signature(&rqst, server,
95438c8a9a5SSteve French mid->sequence_number);
95538c8a9a5SSteve French if (rc)
95638c8a9a5SSteve French cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",
95738c8a9a5SSteve French rc);
95838c8a9a5SSteve French }
95938c8a9a5SSteve French
96038c8a9a5SSteve French /* BB special case reconnect tid and uid here? */
96138c8a9a5SSteve French return map_and_check_smb_error(mid, log_error);
96238c8a9a5SSteve French }
96338c8a9a5SSteve French
96438c8a9a5SSteve French struct mid_q_entry *
cifs_setup_request(struct cifs_ses * ses,struct TCP_Server_Info * ignored,struct smb_rqst * rqst)96538c8a9a5SSteve French cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored,
96638c8a9a5SSteve French struct smb_rqst *rqst)
96738c8a9a5SSteve French {
96838c8a9a5SSteve French int rc;
96938c8a9a5SSteve French struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
97038c8a9a5SSteve French struct mid_q_entry *mid;
97138c8a9a5SSteve French
97238c8a9a5SSteve French if (rqst->rq_iov[0].iov_len != 4 ||
97338c8a9a5SSteve French rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
97438c8a9a5SSteve French return ERR_PTR(-EIO);
97538c8a9a5SSteve French
97638c8a9a5SSteve French rc = allocate_mid(ses, hdr, &mid);
97738c8a9a5SSteve French if (rc)
97838c8a9a5SSteve French return ERR_PTR(rc);
97938c8a9a5SSteve French rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
98038c8a9a5SSteve French if (rc) {
98138c8a9a5SSteve French delete_mid(mid);
98238c8a9a5SSteve French return ERR_PTR(rc);
98338c8a9a5SSteve French }
98438c8a9a5SSteve French return mid;
98538c8a9a5SSteve French }
98638c8a9a5SSteve French
98738c8a9a5SSteve French static void
cifs_compound_callback(struct mid_q_entry * mid)98838c8a9a5SSteve French cifs_compound_callback(struct mid_q_entry *mid)
98938c8a9a5SSteve French {
99038c8a9a5SSteve French struct TCP_Server_Info *server = mid->server;
99138c8a9a5SSteve French struct cifs_credits credits;
99238c8a9a5SSteve French
99338c8a9a5SSteve French credits.value = server->ops->get_credits(mid);
99438c8a9a5SSteve French credits.instance = server->reconnect_instance;
99538c8a9a5SSteve French
99638c8a9a5SSteve French add_credits(server, &credits, mid->optype);
997d527f513SZhang Xiaoxu
998d527f513SZhang Xiaoxu if (mid->mid_state == MID_RESPONSE_RECEIVED)
999d527f513SZhang Xiaoxu mid->mid_state = MID_RESPONSE_READY;
100038c8a9a5SSteve French }
100138c8a9a5SSteve French
100238c8a9a5SSteve French static void
cifs_compound_last_callback(struct mid_q_entry * mid)100338c8a9a5SSteve French cifs_compound_last_callback(struct mid_q_entry *mid)
100438c8a9a5SSteve French {
100538c8a9a5SSteve French cifs_compound_callback(mid);
100638c8a9a5SSteve French cifs_wake_up_task(mid);
100738c8a9a5SSteve French }
100838c8a9a5SSteve French
100938c8a9a5SSteve French static void
cifs_cancelled_callback(struct mid_q_entry * mid)101038c8a9a5SSteve French cifs_cancelled_callback(struct mid_q_entry *mid)
101138c8a9a5SSteve French {
101238c8a9a5SSteve French cifs_compound_callback(mid);
101338c8a9a5SSteve French release_mid(mid);
101438c8a9a5SSteve French }
101538c8a9a5SSteve French
101638c8a9a5SSteve French /*
101738c8a9a5SSteve French * Return a channel (master if none) of @ses that can be used to send
101838c8a9a5SSteve French * regular requests.
101938c8a9a5SSteve French *
102038c8a9a5SSteve French * If we are currently binding a new channel (negprot/sess.setup),
102138c8a9a5SSteve French * return the new incomplete channel.
102238c8a9a5SSteve French */
cifs_pick_channel(struct cifs_ses * ses)102338c8a9a5SSteve French struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
102438c8a9a5SSteve French {
102538c8a9a5SSteve French uint index = 0;
102638c8a9a5SSteve French unsigned int min_in_flight = UINT_MAX, max_in_flight = 0;
102738c8a9a5SSteve French struct TCP_Server_Info *server = NULL;
102838c8a9a5SSteve French int i;
102938c8a9a5SSteve French
103038c8a9a5SSteve French if (!ses)
103138c8a9a5SSteve French return NULL;
103238c8a9a5SSteve French
103338c8a9a5SSteve French spin_lock(&ses->chan_lock);
103438c8a9a5SSteve French for (i = 0; i < ses->chan_count; i++) {
103538c8a9a5SSteve French server = ses->chans[i].server;
10363e161536SShyam Prasad N if (!server || server->terminate)
103738c8a9a5SSteve French continue;
103838c8a9a5SSteve French
103959e04d39SShyam Prasad N if (CIFS_CHAN_NEEDS_RECONNECT(ses, i))
104059e04d39SShyam Prasad N continue;
104159e04d39SShyam Prasad N
104238c8a9a5SSteve French /*
104338c8a9a5SSteve French * strictly speaking, we should pick up req_lock to read
104438c8a9a5SSteve French * server->in_flight. But it shouldn't matter much here if we
104538c8a9a5SSteve French * race while reading this data. The worst that can happen is
104638c8a9a5SSteve French * that we could use a channel that's not least loaded. Avoiding
104738c8a9a5SSteve French * taking the lock could help reduce wait time, which is
104838c8a9a5SSteve French * important for this function
104938c8a9a5SSteve French */
105038c8a9a5SSteve French if (server->in_flight < min_in_flight) {
105138c8a9a5SSteve French min_in_flight = server->in_flight;
105238c8a9a5SSteve French index = i;
105338c8a9a5SSteve French }
105438c8a9a5SSteve French if (server->in_flight > max_in_flight)
105538c8a9a5SSteve French max_in_flight = server->in_flight;
105638c8a9a5SSteve French }
105738c8a9a5SSteve French
105838c8a9a5SSteve French /* if all channels are equally loaded, fall back to round-robin */
105938c8a9a5SSteve French if (min_in_flight == max_in_flight) {
106038c8a9a5SSteve French index = (uint)atomic_inc_return(&ses->chan_seq);
106138c8a9a5SSteve French index %= ses->chan_count;
106238c8a9a5SSteve French }
10630fcf7e21SSteve French
10640fcf7e21SSteve French server = ses->chans[index].server;
106538c8a9a5SSteve French spin_unlock(&ses->chan_lock);
106638c8a9a5SSteve French
10670fcf7e21SSteve French return server;
106838c8a9a5SSteve French }
106938c8a9a5SSteve French
107038c8a9a5SSteve French int
compound_send_recv(const unsigned int xid,struct cifs_ses * ses,struct TCP_Server_Info * server,const int flags,const int num_rqst,struct smb_rqst * rqst,int * resp_buf_type,struct kvec * resp_iov)107138c8a9a5SSteve French compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
107238c8a9a5SSteve French struct TCP_Server_Info *server,
107338c8a9a5SSteve French const int flags, const int num_rqst, struct smb_rqst *rqst,
107438c8a9a5SSteve French int *resp_buf_type, struct kvec *resp_iov)
107538c8a9a5SSteve French {
107638c8a9a5SSteve French int i, j, optype, rc = 0;
107738c8a9a5SSteve French struct mid_q_entry *midQ[MAX_COMPOUND];
107838c8a9a5SSteve French bool cancelled_mid[MAX_COMPOUND] = {false};
107938c8a9a5SSteve French struct cifs_credits credits[MAX_COMPOUND] = {
108038c8a9a5SSteve French { .value = 0, .instance = 0 }
108138c8a9a5SSteve French };
108238c8a9a5SSteve French unsigned int instance;
108338c8a9a5SSteve French char *buf;
108438c8a9a5SSteve French
108538c8a9a5SSteve French optype = flags & CIFS_OP_MASK;
108638c8a9a5SSteve French
108738c8a9a5SSteve French for (i = 0; i < num_rqst; i++)
108838c8a9a5SSteve French resp_buf_type[i] = CIFS_NO_BUFFER; /* no response buf yet */
108938c8a9a5SSteve French
109038c8a9a5SSteve French if (!ses || !ses->server || !server) {
109138c8a9a5SSteve French cifs_dbg(VFS, "Null session\n");
109238c8a9a5SSteve French return -EIO;
109338c8a9a5SSteve French }
109438c8a9a5SSteve French
109538c8a9a5SSteve French spin_lock(&server->srv_lock);
109638c8a9a5SSteve French if (server->tcpStatus == CifsExiting) {
109738c8a9a5SSteve French spin_unlock(&server->srv_lock);
109838c8a9a5SSteve French return -ENOENT;
109938c8a9a5SSteve French }
110038c8a9a5SSteve French spin_unlock(&server->srv_lock);
110138c8a9a5SSteve French
110238c8a9a5SSteve French /*
110338c8a9a5SSteve French * Wait for all the requests to become available.
110438c8a9a5SSteve French * This approach still leaves the possibility to be stuck waiting for
110538c8a9a5SSteve French * credits if the server doesn't grant credits to the outstanding
110638c8a9a5SSteve French * requests and if the client is completely idle, not generating any
110738c8a9a5SSteve French * other requests.
110838c8a9a5SSteve French * This can be handled by the eventual session reconnect.
110938c8a9a5SSteve French */
111038c8a9a5SSteve French rc = wait_for_compound_request(server, num_rqst, flags,
111138c8a9a5SSteve French &instance);
111238c8a9a5SSteve French if (rc)
111338c8a9a5SSteve French return rc;
111438c8a9a5SSteve French
111538c8a9a5SSteve French for (i = 0; i < num_rqst; i++) {
111638c8a9a5SSteve French credits[i].value = 1;
111738c8a9a5SSteve French credits[i].instance = instance;
111838c8a9a5SSteve French }
111938c8a9a5SSteve French
112038c8a9a5SSteve French /*
112138c8a9a5SSteve French * Make sure that we sign in the same order that we send on this socket
112238c8a9a5SSteve French * and avoid races inside tcp sendmsg code that could cause corruption
112338c8a9a5SSteve French * of smb data.
112438c8a9a5SSteve French */
112538c8a9a5SSteve French
112638c8a9a5SSteve French cifs_server_lock(server);
112738c8a9a5SSteve French
112838c8a9a5SSteve French /*
112938c8a9a5SSteve French * All the parts of the compound chain belong obtained credits from the
113038c8a9a5SSteve French * same session. We can not use credits obtained from the previous
113138c8a9a5SSteve French * session to send this request. Check if there were reconnects after
113238c8a9a5SSteve French * we obtained credits and return -EAGAIN in such cases to let callers
113338c8a9a5SSteve French * handle it.
113438c8a9a5SSteve French */
113538c8a9a5SSteve French if (instance != server->reconnect_instance) {
113638c8a9a5SSteve French cifs_server_unlock(server);
113738c8a9a5SSteve French for (j = 0; j < num_rqst; j++)
113838c8a9a5SSteve French add_credits(server, &credits[j], optype);
113938c8a9a5SSteve French return -EAGAIN;
114038c8a9a5SSteve French }
114138c8a9a5SSteve French
114238c8a9a5SSteve French for (i = 0; i < num_rqst; i++) {
114338c8a9a5SSteve French midQ[i] = server->ops->setup_request(ses, server, &rqst[i]);
114438c8a9a5SSteve French if (IS_ERR(midQ[i])) {
114538c8a9a5SSteve French revert_current_mid(server, i);
114638c8a9a5SSteve French for (j = 0; j < i; j++)
114738c8a9a5SSteve French delete_mid(midQ[j]);
114838c8a9a5SSteve French cifs_server_unlock(server);
114938c8a9a5SSteve French
115038c8a9a5SSteve French /* Update # of requests on wire to server */
115138c8a9a5SSteve French for (j = 0; j < num_rqst; j++)
115238c8a9a5SSteve French add_credits(server, &credits[j], optype);
115338c8a9a5SSteve French return PTR_ERR(midQ[i]);
115438c8a9a5SSteve French }
115538c8a9a5SSteve French
115638c8a9a5SSteve French midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
115738c8a9a5SSteve French midQ[i]->optype = optype;
115838c8a9a5SSteve French /*
115938c8a9a5SSteve French * Invoke callback for every part of the compound chain
116038c8a9a5SSteve French * to calculate credits properly. Wake up this thread only when
116138c8a9a5SSteve French * the last element is received.
116238c8a9a5SSteve French */
116338c8a9a5SSteve French if (i < num_rqst - 1)
116438c8a9a5SSteve French midQ[i]->callback = cifs_compound_callback;
116538c8a9a5SSteve French else
116638c8a9a5SSteve French midQ[i]->callback = cifs_compound_last_callback;
116738c8a9a5SSteve French }
116838c8a9a5SSteve French rc = smb_send_rqst(server, num_rqst, rqst, flags);
116938c8a9a5SSteve French
117038c8a9a5SSteve French for (i = 0; i < num_rqst; i++)
117138c8a9a5SSteve French cifs_save_when_sent(midQ[i]);
117238c8a9a5SSteve French
117338c8a9a5SSteve French if (rc < 0) {
117438c8a9a5SSteve French revert_current_mid(server, num_rqst);
117538c8a9a5SSteve French server->sequence_number -= 2;
117638c8a9a5SSteve French }
117738c8a9a5SSteve French
117838c8a9a5SSteve French cifs_server_unlock(server);
117938c8a9a5SSteve French
118038c8a9a5SSteve French /*
118138c8a9a5SSteve French * If sending failed for some reason or it is an oplock break that we
118238c8a9a5SSteve French * will not receive a response to - return credits back
118338c8a9a5SSteve French */
118438c8a9a5SSteve French if (rc < 0 || (flags & CIFS_NO_SRV_RSP)) {
118538c8a9a5SSteve French for (i = 0; i < num_rqst; i++)
118638c8a9a5SSteve French add_credits(server, &credits[i], optype);
118738c8a9a5SSteve French goto out;
118838c8a9a5SSteve French }
118938c8a9a5SSteve French
119038c8a9a5SSteve French /*
119138c8a9a5SSteve French * At this point the request is passed to the network stack - we assume
119238c8a9a5SSteve French * that any credits taken from the server structure on the client have
119338c8a9a5SSteve French * been spent and we can't return them back. Once we receive responses
119438c8a9a5SSteve French * we will collect credits granted by the server in the mid callbacks
119538c8a9a5SSteve French * and add those credits to the server structure.
119638c8a9a5SSteve French */
119738c8a9a5SSteve French
119838c8a9a5SSteve French /*
119938c8a9a5SSteve French * Compounding is never used during session establish.
120038c8a9a5SSteve French */
120138c8a9a5SSteve French spin_lock(&ses->ses_lock);
120238c8a9a5SSteve French if ((ses->ses_status == SES_NEW) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) {
120338c8a9a5SSteve French spin_unlock(&ses->ses_lock);
120438c8a9a5SSteve French
120538c8a9a5SSteve French cifs_server_lock(server);
120638c8a9a5SSteve French smb311_update_preauth_hash(ses, server, rqst[0].rq_iov, rqst[0].rq_nvec);
120738c8a9a5SSteve French cifs_server_unlock(server);
120838c8a9a5SSteve French
120938c8a9a5SSteve French spin_lock(&ses->ses_lock);
121038c8a9a5SSteve French }
121138c8a9a5SSteve French spin_unlock(&ses->ses_lock);
121238c8a9a5SSteve French
121338c8a9a5SSteve French for (i = 0; i < num_rqst; i++) {
121438c8a9a5SSteve French rc = wait_for_response(server, midQ[i]);
121538c8a9a5SSteve French if (rc != 0)
121638c8a9a5SSteve French break;
121738c8a9a5SSteve French }
121838c8a9a5SSteve French if (rc != 0) {
121938c8a9a5SSteve French for (; i < num_rqst; i++) {
122038c8a9a5SSteve French cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n",
122138c8a9a5SSteve French midQ[i]->mid, le16_to_cpu(midQ[i]->command));
122238c8a9a5SSteve French send_cancel(server, &rqst[i], midQ[i]);
122338c8a9a5SSteve French spin_lock(&server->mid_lock);
122438c8a9a5SSteve French midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
1225d527f513SZhang Xiaoxu if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED ||
1226d527f513SZhang Xiaoxu midQ[i]->mid_state == MID_RESPONSE_RECEIVED) {
122738c8a9a5SSteve French midQ[i]->callback = cifs_cancelled_callback;
122838c8a9a5SSteve French cancelled_mid[i] = true;
122938c8a9a5SSteve French credits[i].value = 0;
123038c8a9a5SSteve French }
123138c8a9a5SSteve French spin_unlock(&server->mid_lock);
123238c8a9a5SSteve French }
123338c8a9a5SSteve French }
123438c8a9a5SSteve French
123538c8a9a5SSteve French for (i = 0; i < num_rqst; i++) {
123638c8a9a5SSteve French if (rc < 0)
123738c8a9a5SSteve French goto out;
123838c8a9a5SSteve French
123938c8a9a5SSteve French rc = cifs_sync_mid_result(midQ[i], server);
124038c8a9a5SSteve French if (rc != 0) {
124138c8a9a5SSteve French /* mark this mid as cancelled to not free it below */
124238c8a9a5SSteve French cancelled_mid[i] = true;
124338c8a9a5SSteve French goto out;
124438c8a9a5SSteve French }
124538c8a9a5SSteve French
124638c8a9a5SSteve French if (!midQ[i]->resp_buf ||
1247d527f513SZhang Xiaoxu midQ[i]->mid_state != MID_RESPONSE_READY) {
124838c8a9a5SSteve French rc = -EIO;
124938c8a9a5SSteve French cifs_dbg(FYI, "Bad MID state?\n");
125038c8a9a5SSteve French goto out;
125138c8a9a5SSteve French }
125238c8a9a5SSteve French
125338c8a9a5SSteve French buf = (char *)midQ[i]->resp_buf;
125438c8a9a5SSteve French resp_iov[i].iov_base = buf;
125538c8a9a5SSteve French resp_iov[i].iov_len = midQ[i]->resp_buf_size +
125638c8a9a5SSteve French HEADER_PREAMBLE_SIZE(server);
125738c8a9a5SSteve French
125838c8a9a5SSteve French if (midQ[i]->large_buf)
125938c8a9a5SSteve French resp_buf_type[i] = CIFS_LARGE_BUFFER;
126038c8a9a5SSteve French else
126138c8a9a5SSteve French resp_buf_type[i] = CIFS_SMALL_BUFFER;
126238c8a9a5SSteve French
126338c8a9a5SSteve French rc = server->ops->check_receive(midQ[i], server,
126438c8a9a5SSteve French flags & CIFS_LOG_ERROR);
126538c8a9a5SSteve French
126638c8a9a5SSteve French /* mark it so buf will not be freed by delete_mid */
126738c8a9a5SSteve French if ((flags & CIFS_NO_RSP_BUF) == 0)
126838c8a9a5SSteve French midQ[i]->resp_buf = NULL;
126938c8a9a5SSteve French
127038c8a9a5SSteve French }
127138c8a9a5SSteve French
127238c8a9a5SSteve French /*
127338c8a9a5SSteve French * Compounding is never used during session establish.
127438c8a9a5SSteve French */
127538c8a9a5SSteve French spin_lock(&ses->ses_lock);
127638c8a9a5SSteve French if ((ses->ses_status == SES_NEW) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) {
127738c8a9a5SSteve French struct kvec iov = {
127838c8a9a5SSteve French .iov_base = resp_iov[0].iov_base,
127938c8a9a5SSteve French .iov_len = resp_iov[0].iov_len
128038c8a9a5SSteve French };
128138c8a9a5SSteve French spin_unlock(&ses->ses_lock);
128238c8a9a5SSteve French cifs_server_lock(server);
128338c8a9a5SSteve French smb311_update_preauth_hash(ses, server, &iov, 1);
128438c8a9a5SSteve French cifs_server_unlock(server);
128538c8a9a5SSteve French spin_lock(&ses->ses_lock);
128638c8a9a5SSteve French }
128738c8a9a5SSteve French spin_unlock(&ses->ses_lock);
128838c8a9a5SSteve French
128938c8a9a5SSteve French out:
129038c8a9a5SSteve French /*
129138c8a9a5SSteve French * This will dequeue all mids. After this it is important that the
129238c8a9a5SSteve French * demultiplex_thread will not process any of these mids any futher.
129338c8a9a5SSteve French * This is prevented above by using a noop callback that will not
129438c8a9a5SSteve French * wake this thread except for the very last PDU.
129538c8a9a5SSteve French */
129638c8a9a5SSteve French for (i = 0; i < num_rqst; i++) {
129738c8a9a5SSteve French if (!cancelled_mid[i])
129838c8a9a5SSteve French delete_mid(midQ[i]);
129938c8a9a5SSteve French }
130038c8a9a5SSteve French
130138c8a9a5SSteve French return rc;
130238c8a9a5SSteve French }
130338c8a9a5SSteve French
130438c8a9a5SSteve French int
cifs_send_recv(const unsigned int xid,struct cifs_ses * ses,struct TCP_Server_Info * server,struct smb_rqst * rqst,int * resp_buf_type,const int flags,struct kvec * resp_iov)130538c8a9a5SSteve French cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
130638c8a9a5SSteve French struct TCP_Server_Info *server,
130738c8a9a5SSteve French struct smb_rqst *rqst, int *resp_buf_type, const int flags,
130838c8a9a5SSteve French struct kvec *resp_iov)
130938c8a9a5SSteve French {
131038c8a9a5SSteve French return compound_send_recv(xid, ses, server, flags, 1,
131138c8a9a5SSteve French rqst, resp_buf_type, resp_iov);
131238c8a9a5SSteve French }
131338c8a9a5SSteve French
131438c8a9a5SSteve French int
SendReceive2(const unsigned int xid,struct cifs_ses * ses,struct kvec * iov,int n_vec,int * resp_buf_type,const int flags,struct kvec * resp_iov)131538c8a9a5SSteve French SendReceive2(const unsigned int xid, struct cifs_ses *ses,
131638c8a9a5SSteve French struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
131738c8a9a5SSteve French const int flags, struct kvec *resp_iov)
131838c8a9a5SSteve French {
131938c8a9a5SSteve French struct smb_rqst rqst;
132038c8a9a5SSteve French struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov;
132138c8a9a5SSteve French int rc;
132238c8a9a5SSteve French
132338c8a9a5SSteve French if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
132438c8a9a5SSteve French new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec),
132538c8a9a5SSteve French GFP_KERNEL);
132638c8a9a5SSteve French if (!new_iov) {
132738c8a9a5SSteve French /* otherwise cifs_send_recv below sets resp_buf_type */
132838c8a9a5SSteve French *resp_buf_type = CIFS_NO_BUFFER;
132938c8a9a5SSteve French return -ENOMEM;
133038c8a9a5SSteve French }
133138c8a9a5SSteve French } else
133238c8a9a5SSteve French new_iov = s_iov;
133338c8a9a5SSteve French
133438c8a9a5SSteve French /* 1st iov is a RFC1001 length followed by the rest of the packet */
133538c8a9a5SSteve French memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
133638c8a9a5SSteve French
133738c8a9a5SSteve French new_iov[0].iov_base = new_iov[1].iov_base;
133838c8a9a5SSteve French new_iov[0].iov_len = 4;
133938c8a9a5SSteve French new_iov[1].iov_base += 4;
134038c8a9a5SSteve French new_iov[1].iov_len -= 4;
134138c8a9a5SSteve French
134238c8a9a5SSteve French memset(&rqst, 0, sizeof(struct smb_rqst));
134338c8a9a5SSteve French rqst.rq_iov = new_iov;
134438c8a9a5SSteve French rqst.rq_nvec = n_vec + 1;
134538c8a9a5SSteve French
134638c8a9a5SSteve French rc = cifs_send_recv(xid, ses, ses->server,
134738c8a9a5SSteve French &rqst, resp_buf_type, flags, resp_iov);
134838c8a9a5SSteve French if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
134938c8a9a5SSteve French kfree(new_iov);
135038c8a9a5SSteve French return rc;
135138c8a9a5SSteve French }
135238c8a9a5SSteve French
135338c8a9a5SSteve French int
SendReceive(const unsigned int xid,struct cifs_ses * ses,struct smb_hdr * in_buf,struct smb_hdr * out_buf,int * pbytes_returned,const int flags)135438c8a9a5SSteve French SendReceive(const unsigned int xid, struct cifs_ses *ses,
135538c8a9a5SSteve French struct smb_hdr *in_buf, struct smb_hdr *out_buf,
135638c8a9a5SSteve French int *pbytes_returned, const int flags)
135738c8a9a5SSteve French {
135838c8a9a5SSteve French int rc = 0;
135938c8a9a5SSteve French struct mid_q_entry *midQ;
136038c8a9a5SSteve French unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
136138c8a9a5SSteve French struct kvec iov = { .iov_base = in_buf, .iov_len = len };
136238c8a9a5SSteve French struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
136338c8a9a5SSteve French struct cifs_credits credits = { .value = 1, .instance = 0 };
136438c8a9a5SSteve French struct TCP_Server_Info *server;
136538c8a9a5SSteve French
136638c8a9a5SSteve French if (ses == NULL) {
136738c8a9a5SSteve French cifs_dbg(VFS, "Null smb session\n");
136838c8a9a5SSteve French return -EIO;
136938c8a9a5SSteve French }
137038c8a9a5SSteve French server = ses->server;
137138c8a9a5SSteve French if (server == NULL) {
137238c8a9a5SSteve French cifs_dbg(VFS, "Null tcp session\n");
137338c8a9a5SSteve French return -EIO;
137438c8a9a5SSteve French }
137538c8a9a5SSteve French
137638c8a9a5SSteve French spin_lock(&server->srv_lock);
137738c8a9a5SSteve French if (server->tcpStatus == CifsExiting) {
137838c8a9a5SSteve French spin_unlock(&server->srv_lock);
137938c8a9a5SSteve French return -ENOENT;
138038c8a9a5SSteve French }
138138c8a9a5SSteve French spin_unlock(&server->srv_lock);
138238c8a9a5SSteve French
138338c8a9a5SSteve French /* Ensure that we do not send more than 50 overlapping requests
138438c8a9a5SSteve French to the same server. We may make this configurable later or
138538c8a9a5SSteve French use ses->maxReq */
138638c8a9a5SSteve French
138738c8a9a5SSteve French if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
138838c8a9a5SSteve French cifs_server_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
138938c8a9a5SSteve French len);
139038c8a9a5SSteve French return -EIO;
139138c8a9a5SSteve French }
139238c8a9a5SSteve French
139338c8a9a5SSteve French rc = wait_for_free_request(server, flags, &credits.instance);
139438c8a9a5SSteve French if (rc)
139538c8a9a5SSteve French return rc;
139638c8a9a5SSteve French
139738c8a9a5SSteve French /* make sure that we sign in the same order that we send on this socket
139838c8a9a5SSteve French and avoid races inside tcp sendmsg code that could cause corruption
139938c8a9a5SSteve French of smb data */
140038c8a9a5SSteve French
140138c8a9a5SSteve French cifs_server_lock(server);
140238c8a9a5SSteve French
140338c8a9a5SSteve French rc = allocate_mid(ses, in_buf, &midQ);
140438c8a9a5SSteve French if (rc) {
140538c8a9a5SSteve French cifs_server_unlock(server);
140638c8a9a5SSteve French /* Update # of requests on wire to server */
140738c8a9a5SSteve French add_credits(server, &credits, 0);
140838c8a9a5SSteve French return rc;
140938c8a9a5SSteve French }
141038c8a9a5SSteve French
141138c8a9a5SSteve French rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
141238c8a9a5SSteve French if (rc) {
141338c8a9a5SSteve French cifs_server_unlock(server);
141438c8a9a5SSteve French goto out;
141538c8a9a5SSteve French }
141638c8a9a5SSteve French
141738c8a9a5SSteve French midQ->mid_state = MID_REQUEST_SUBMITTED;
141838c8a9a5SSteve French
141938c8a9a5SSteve French rc = smb_send(server, in_buf, len);
142038c8a9a5SSteve French cifs_save_when_sent(midQ);
142138c8a9a5SSteve French
142238c8a9a5SSteve French if (rc < 0)
142338c8a9a5SSteve French server->sequence_number -= 2;
142438c8a9a5SSteve French
142538c8a9a5SSteve French cifs_server_unlock(server);
142638c8a9a5SSteve French
142738c8a9a5SSteve French if (rc < 0)
142838c8a9a5SSteve French goto out;
142938c8a9a5SSteve French
143038c8a9a5SSteve French rc = wait_for_response(server, midQ);
143138c8a9a5SSteve French if (rc != 0) {
143238c8a9a5SSteve French send_cancel(server, &rqst, midQ);
143338c8a9a5SSteve French spin_lock(&server->mid_lock);
1434d527f513SZhang Xiaoxu if (midQ->mid_state == MID_REQUEST_SUBMITTED ||
1435d527f513SZhang Xiaoxu midQ->mid_state == MID_RESPONSE_RECEIVED) {
143638c8a9a5SSteve French /* no longer considered to be "in-flight" */
143738c8a9a5SSteve French midQ->callback = release_mid;
143838c8a9a5SSteve French spin_unlock(&server->mid_lock);
143938c8a9a5SSteve French add_credits(server, &credits, 0);
144038c8a9a5SSteve French return rc;
144138c8a9a5SSteve French }
144238c8a9a5SSteve French spin_unlock(&server->mid_lock);
144338c8a9a5SSteve French }
144438c8a9a5SSteve French
144538c8a9a5SSteve French rc = cifs_sync_mid_result(midQ, server);
144638c8a9a5SSteve French if (rc != 0) {
144738c8a9a5SSteve French add_credits(server, &credits, 0);
144838c8a9a5SSteve French return rc;
144938c8a9a5SSteve French }
145038c8a9a5SSteve French
145138c8a9a5SSteve French if (!midQ->resp_buf || !out_buf ||
1452d527f513SZhang Xiaoxu midQ->mid_state != MID_RESPONSE_READY) {
145338c8a9a5SSteve French rc = -EIO;
145438c8a9a5SSteve French cifs_server_dbg(VFS, "Bad MID state?\n");
145538c8a9a5SSteve French goto out;
145638c8a9a5SSteve French }
145738c8a9a5SSteve French
145838c8a9a5SSteve French *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
145938c8a9a5SSteve French memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
146038c8a9a5SSteve French rc = cifs_check_receive(midQ, server, 0);
146138c8a9a5SSteve French out:
146238c8a9a5SSteve French delete_mid(midQ);
146338c8a9a5SSteve French add_credits(server, &credits, 0);
146438c8a9a5SSteve French
146538c8a9a5SSteve French return rc;
146638c8a9a5SSteve French }
146738c8a9a5SSteve French
146838c8a9a5SSteve French /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
146938c8a9a5SSteve French blocking lock to return. */
147038c8a9a5SSteve French
147138c8a9a5SSteve French static int
send_lock_cancel(const unsigned int xid,struct cifs_tcon * tcon,struct smb_hdr * in_buf,struct smb_hdr * out_buf)147238c8a9a5SSteve French send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
147338c8a9a5SSteve French struct smb_hdr *in_buf,
147438c8a9a5SSteve French struct smb_hdr *out_buf)
147538c8a9a5SSteve French {
147638c8a9a5SSteve French int bytes_returned;
147738c8a9a5SSteve French struct cifs_ses *ses = tcon->ses;
147838c8a9a5SSteve French LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
147938c8a9a5SSteve French
148038c8a9a5SSteve French /* We just modify the current in_buf to change
148138c8a9a5SSteve French the type of lock from LOCKING_ANDX_SHARED_LOCK
148238c8a9a5SSteve French or LOCKING_ANDX_EXCLUSIVE_LOCK to
148338c8a9a5SSteve French LOCKING_ANDX_CANCEL_LOCK. */
148438c8a9a5SSteve French
148538c8a9a5SSteve French pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
148638c8a9a5SSteve French pSMB->Timeout = 0;
148738c8a9a5SSteve French pSMB->hdr.Mid = get_next_mid(ses->server);
148838c8a9a5SSteve French
148938c8a9a5SSteve French return SendReceive(xid, ses, in_buf, out_buf,
149038c8a9a5SSteve French &bytes_returned, 0);
149138c8a9a5SSteve French }
149238c8a9a5SSteve French
149338c8a9a5SSteve French int
SendReceiveBlockingLock(const unsigned int xid,struct cifs_tcon * tcon,struct smb_hdr * in_buf,struct smb_hdr * out_buf,int * pbytes_returned)149438c8a9a5SSteve French SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
149538c8a9a5SSteve French struct smb_hdr *in_buf, struct smb_hdr *out_buf,
149638c8a9a5SSteve French int *pbytes_returned)
149738c8a9a5SSteve French {
149838c8a9a5SSteve French int rc = 0;
149938c8a9a5SSteve French int rstart = 0;
150038c8a9a5SSteve French struct mid_q_entry *midQ;
150138c8a9a5SSteve French struct cifs_ses *ses;
150238c8a9a5SSteve French unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
150338c8a9a5SSteve French struct kvec iov = { .iov_base = in_buf, .iov_len = len };
150438c8a9a5SSteve French struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
150538c8a9a5SSteve French unsigned int instance;
150638c8a9a5SSteve French struct TCP_Server_Info *server;
150738c8a9a5SSteve French
150838c8a9a5SSteve French if (tcon == NULL || tcon->ses == NULL) {
150938c8a9a5SSteve French cifs_dbg(VFS, "Null smb session\n");
151038c8a9a5SSteve French return -EIO;
151138c8a9a5SSteve French }
151238c8a9a5SSteve French ses = tcon->ses;
151338c8a9a5SSteve French server = ses->server;
151438c8a9a5SSteve French
151538c8a9a5SSteve French if (server == NULL) {
151638c8a9a5SSteve French cifs_dbg(VFS, "Null tcp session\n");
151738c8a9a5SSteve French return -EIO;
151838c8a9a5SSteve French }
151938c8a9a5SSteve French
152038c8a9a5SSteve French spin_lock(&server->srv_lock);
152138c8a9a5SSteve French if (server->tcpStatus == CifsExiting) {
152238c8a9a5SSteve French spin_unlock(&server->srv_lock);
152338c8a9a5SSteve French return -ENOENT;
152438c8a9a5SSteve French }
152538c8a9a5SSteve French spin_unlock(&server->srv_lock);
152638c8a9a5SSteve French
152738c8a9a5SSteve French /* Ensure that we do not send more than 50 overlapping requests
152838c8a9a5SSteve French to the same server. We may make this configurable later or
152938c8a9a5SSteve French use ses->maxReq */
153038c8a9a5SSteve French
153138c8a9a5SSteve French if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
153238c8a9a5SSteve French cifs_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
153338c8a9a5SSteve French len);
153438c8a9a5SSteve French return -EIO;
153538c8a9a5SSteve French }
153638c8a9a5SSteve French
153738c8a9a5SSteve French rc = wait_for_free_request(server, CIFS_BLOCKING_OP, &instance);
153838c8a9a5SSteve French if (rc)
153938c8a9a5SSteve French return rc;
154038c8a9a5SSteve French
154138c8a9a5SSteve French /* make sure that we sign in the same order that we send on this socket
154238c8a9a5SSteve French and avoid races inside tcp sendmsg code that could cause corruption
154338c8a9a5SSteve French of smb data */
154438c8a9a5SSteve French
154538c8a9a5SSteve French cifs_server_lock(server);
154638c8a9a5SSteve French
154738c8a9a5SSteve French rc = allocate_mid(ses, in_buf, &midQ);
154838c8a9a5SSteve French if (rc) {
154938c8a9a5SSteve French cifs_server_unlock(server);
155038c8a9a5SSteve French return rc;
155138c8a9a5SSteve French }
155238c8a9a5SSteve French
155338c8a9a5SSteve French rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
155438c8a9a5SSteve French if (rc) {
155538c8a9a5SSteve French delete_mid(midQ);
155638c8a9a5SSteve French cifs_server_unlock(server);
155738c8a9a5SSteve French return rc;
155838c8a9a5SSteve French }
155938c8a9a5SSteve French
156038c8a9a5SSteve French midQ->mid_state = MID_REQUEST_SUBMITTED;
156138c8a9a5SSteve French rc = smb_send(server, in_buf, len);
156238c8a9a5SSteve French cifs_save_when_sent(midQ);
156338c8a9a5SSteve French
156438c8a9a5SSteve French if (rc < 0)
156538c8a9a5SSteve French server->sequence_number -= 2;
156638c8a9a5SSteve French
156738c8a9a5SSteve French cifs_server_unlock(server);
156838c8a9a5SSteve French
156938c8a9a5SSteve French if (rc < 0) {
157038c8a9a5SSteve French delete_mid(midQ);
157138c8a9a5SSteve French return rc;
157238c8a9a5SSteve French }
157338c8a9a5SSteve French
157438c8a9a5SSteve French /* Wait for a reply - allow signals to interrupt. */
157538c8a9a5SSteve French rc = wait_event_interruptible(server->response_q,
1576d527f513SZhang Xiaoxu (!(midQ->mid_state == MID_REQUEST_SUBMITTED ||
1577d527f513SZhang Xiaoxu midQ->mid_state == MID_RESPONSE_RECEIVED)) ||
157838c8a9a5SSteve French ((server->tcpStatus != CifsGood) &&
157938c8a9a5SSteve French (server->tcpStatus != CifsNew)));
158038c8a9a5SSteve French
158138c8a9a5SSteve French /* Were we interrupted by a signal ? */
158238c8a9a5SSteve French spin_lock(&server->srv_lock);
158338c8a9a5SSteve French if ((rc == -ERESTARTSYS) &&
1584d527f513SZhang Xiaoxu (midQ->mid_state == MID_REQUEST_SUBMITTED ||
1585d527f513SZhang Xiaoxu midQ->mid_state == MID_RESPONSE_RECEIVED) &&
158638c8a9a5SSteve French ((server->tcpStatus == CifsGood) ||
158738c8a9a5SSteve French (server->tcpStatus == CifsNew))) {
158838c8a9a5SSteve French spin_unlock(&server->srv_lock);
158938c8a9a5SSteve French
159038c8a9a5SSteve French if (in_buf->Command == SMB_COM_TRANSACTION2) {
159138c8a9a5SSteve French /* POSIX lock. We send a NT_CANCEL SMB to cause the
159238c8a9a5SSteve French blocking lock to return. */
159338c8a9a5SSteve French rc = send_cancel(server, &rqst, midQ);
159438c8a9a5SSteve French if (rc) {
159538c8a9a5SSteve French delete_mid(midQ);
159638c8a9a5SSteve French return rc;
159738c8a9a5SSteve French }
159838c8a9a5SSteve French } else {
159938c8a9a5SSteve French /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
160038c8a9a5SSteve French to cause the blocking lock to return. */
160138c8a9a5SSteve French
160238c8a9a5SSteve French rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
160338c8a9a5SSteve French
160438c8a9a5SSteve French /* If we get -ENOLCK back the lock may have
160538c8a9a5SSteve French already been removed. Don't exit in this case. */
160638c8a9a5SSteve French if (rc && rc != -ENOLCK) {
160738c8a9a5SSteve French delete_mid(midQ);
160838c8a9a5SSteve French return rc;
160938c8a9a5SSteve French }
161038c8a9a5SSteve French }
161138c8a9a5SSteve French
161238c8a9a5SSteve French rc = wait_for_response(server, midQ);
161338c8a9a5SSteve French if (rc) {
161438c8a9a5SSteve French send_cancel(server, &rqst, midQ);
161538c8a9a5SSteve French spin_lock(&server->mid_lock);
1616d527f513SZhang Xiaoxu if (midQ->mid_state == MID_REQUEST_SUBMITTED ||
1617d527f513SZhang Xiaoxu midQ->mid_state == MID_RESPONSE_RECEIVED) {
161838c8a9a5SSteve French /* no longer considered to be "in-flight" */
161938c8a9a5SSteve French midQ->callback = release_mid;
162038c8a9a5SSteve French spin_unlock(&server->mid_lock);
162138c8a9a5SSteve French return rc;
162238c8a9a5SSteve French }
162338c8a9a5SSteve French spin_unlock(&server->mid_lock);
162438c8a9a5SSteve French }
162538c8a9a5SSteve French
162638c8a9a5SSteve French /* We got the response - restart system call. */
162738c8a9a5SSteve French rstart = 1;
162838c8a9a5SSteve French spin_lock(&server->srv_lock);
162938c8a9a5SSteve French }
163038c8a9a5SSteve French spin_unlock(&server->srv_lock);
163138c8a9a5SSteve French
163238c8a9a5SSteve French rc = cifs_sync_mid_result(midQ, server);
163338c8a9a5SSteve French if (rc != 0)
163438c8a9a5SSteve French return rc;
163538c8a9a5SSteve French
163638c8a9a5SSteve French /* rcvd frame is ok */
1637d527f513SZhang Xiaoxu if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_READY) {
163838c8a9a5SSteve French rc = -EIO;
163938c8a9a5SSteve French cifs_tcon_dbg(VFS, "Bad MID state?\n");
164038c8a9a5SSteve French goto out;
164138c8a9a5SSteve French }
164238c8a9a5SSteve French
164338c8a9a5SSteve French *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
164438c8a9a5SSteve French memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
164538c8a9a5SSteve French rc = cifs_check_receive(midQ, server, 0);
164638c8a9a5SSteve French out:
164738c8a9a5SSteve French delete_mid(midQ);
164838c8a9a5SSteve French if (rstart && rc == -EACCES)
164938c8a9a5SSteve French return -ERESTARTSYS;
165038c8a9a5SSteve French return rc;
165138c8a9a5SSteve French }
165238c8a9a5SSteve French
165338c8a9a5SSteve French /*
165438c8a9a5SSteve French * Discard any remaining data in the current SMB. To do this, we borrow the
165538c8a9a5SSteve French * current bigbuf.
165638c8a9a5SSteve French */
165738c8a9a5SSteve French int
cifs_discard_remaining_data(struct TCP_Server_Info * server)165838c8a9a5SSteve French cifs_discard_remaining_data(struct TCP_Server_Info *server)
165938c8a9a5SSteve French {
166038c8a9a5SSteve French unsigned int rfclen = server->pdu_size;
166138c8a9a5SSteve French size_t remaining = rfclen + HEADER_PREAMBLE_SIZE(server) -
166238c8a9a5SSteve French server->total_read;
166338c8a9a5SSteve French
166438c8a9a5SSteve French while (remaining > 0) {
166538c8a9a5SSteve French ssize_t length;
166638c8a9a5SSteve French
166738c8a9a5SSteve French length = cifs_discard_from_socket(server,
166838c8a9a5SSteve French min_t(size_t, remaining,
166938c8a9a5SSteve French CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
167038c8a9a5SSteve French if (length < 0)
167138c8a9a5SSteve French return length;
167238c8a9a5SSteve French server->total_read += length;
167338c8a9a5SSteve French remaining -= length;
167438c8a9a5SSteve French }
167538c8a9a5SSteve French
167638c8a9a5SSteve French return 0;
167738c8a9a5SSteve French }
167838c8a9a5SSteve French
167938c8a9a5SSteve French static int
__cifs_readv_discard(struct TCP_Server_Info * server,struct mid_q_entry * mid,bool malformed)168038c8a9a5SSteve French __cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
168138c8a9a5SSteve French bool malformed)
168238c8a9a5SSteve French {
168338c8a9a5SSteve French int length;
168438c8a9a5SSteve French
168538c8a9a5SSteve French length = cifs_discard_remaining_data(server);
168638c8a9a5SSteve French dequeue_mid(mid, malformed);
168738c8a9a5SSteve French mid->resp_buf = server->smallbuf;
168838c8a9a5SSteve French server->smallbuf = NULL;
168938c8a9a5SSteve French return length;
169038c8a9a5SSteve French }
169138c8a9a5SSteve French
169238c8a9a5SSteve French static int
cifs_readv_discard(struct TCP_Server_Info * server,struct mid_q_entry * mid)169338c8a9a5SSteve French cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
169438c8a9a5SSteve French {
169538c8a9a5SSteve French struct cifs_readdata *rdata = mid->callback_data;
169638c8a9a5SSteve French
169738c8a9a5SSteve French return __cifs_readv_discard(server, mid, rdata->result);
169838c8a9a5SSteve French }
169938c8a9a5SSteve French
170038c8a9a5SSteve French int
cifs_readv_receive(struct TCP_Server_Info * server,struct mid_q_entry * mid)170138c8a9a5SSteve French cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
170238c8a9a5SSteve French {
170338c8a9a5SSteve French int length, len;
170438c8a9a5SSteve French unsigned int data_offset, data_len;
170538c8a9a5SSteve French struct cifs_readdata *rdata = mid->callback_data;
170638c8a9a5SSteve French char *buf = server->smallbuf;
170738c8a9a5SSteve French unsigned int buflen = server->pdu_size + HEADER_PREAMBLE_SIZE(server);
170838c8a9a5SSteve French bool use_rdma_mr = false;
170938c8a9a5SSteve French
171038c8a9a5SSteve French cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
171138c8a9a5SSteve French __func__, mid->mid, rdata->offset, rdata->bytes);
171238c8a9a5SSteve French
171338c8a9a5SSteve French /*
171438c8a9a5SSteve French * read the rest of READ_RSP header (sans Data array), or whatever we
171538c8a9a5SSteve French * can if there's not enough data. At this point, we've read down to
171638c8a9a5SSteve French * the Mid.
171738c8a9a5SSteve French */
171838c8a9a5SSteve French len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
171938c8a9a5SSteve French HEADER_SIZE(server) + 1;
172038c8a9a5SSteve French
172138c8a9a5SSteve French length = cifs_read_from_socket(server,
172238c8a9a5SSteve French buf + HEADER_SIZE(server) - 1, len);
172338c8a9a5SSteve French if (length < 0)
172438c8a9a5SSteve French return length;
172538c8a9a5SSteve French server->total_read += length;
172638c8a9a5SSteve French
172738c8a9a5SSteve French if (server->ops->is_session_expired &&
172838c8a9a5SSteve French server->ops->is_session_expired(buf)) {
172938c8a9a5SSteve French cifs_reconnect(server, true);
173038c8a9a5SSteve French return -1;
173138c8a9a5SSteve French }
173238c8a9a5SSteve French
173338c8a9a5SSteve French if (server->ops->is_status_pending &&
173438c8a9a5SSteve French server->ops->is_status_pending(buf, server)) {
173538c8a9a5SSteve French cifs_discard_remaining_data(server);
173638c8a9a5SSteve French return -1;
173738c8a9a5SSteve French }
173838c8a9a5SSteve French
173938c8a9a5SSteve French /* set up first two iov for signature check and to get credits */
174038c8a9a5SSteve French rdata->iov[0].iov_base = buf;
174138c8a9a5SSteve French rdata->iov[0].iov_len = HEADER_PREAMBLE_SIZE(server);
174238c8a9a5SSteve French rdata->iov[1].iov_base = buf + HEADER_PREAMBLE_SIZE(server);
174338c8a9a5SSteve French rdata->iov[1].iov_len =
174438c8a9a5SSteve French server->total_read - HEADER_PREAMBLE_SIZE(server);
174538c8a9a5SSteve French cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
174638c8a9a5SSteve French rdata->iov[0].iov_base, rdata->iov[0].iov_len);
174738c8a9a5SSteve French cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
174838c8a9a5SSteve French rdata->iov[1].iov_base, rdata->iov[1].iov_len);
174938c8a9a5SSteve French
175038c8a9a5SSteve French /* Was the SMB read successful? */
175138c8a9a5SSteve French rdata->result = server->ops->map_error(buf, false);
175238c8a9a5SSteve French if (rdata->result != 0) {
175338c8a9a5SSteve French cifs_dbg(FYI, "%s: server returned error %d\n",
175438c8a9a5SSteve French __func__, rdata->result);
175538c8a9a5SSteve French /* normal error on read response */
175638c8a9a5SSteve French return __cifs_readv_discard(server, mid, false);
175738c8a9a5SSteve French }
175838c8a9a5SSteve French
175938c8a9a5SSteve French /* Is there enough to get to the rest of the READ_RSP header? */
176038c8a9a5SSteve French if (server->total_read < server->vals->read_rsp_size) {
176138c8a9a5SSteve French cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
176238c8a9a5SSteve French __func__, server->total_read,
176338c8a9a5SSteve French server->vals->read_rsp_size);
176438c8a9a5SSteve French rdata->result = -EIO;
176538c8a9a5SSteve French return cifs_readv_discard(server, mid);
176638c8a9a5SSteve French }
176738c8a9a5SSteve French
176838c8a9a5SSteve French data_offset = server->ops->read_data_offset(buf) +
176938c8a9a5SSteve French HEADER_PREAMBLE_SIZE(server);
177038c8a9a5SSteve French if (data_offset < server->total_read) {
177138c8a9a5SSteve French /*
177238c8a9a5SSteve French * win2k8 sometimes sends an offset of 0 when the read
177338c8a9a5SSteve French * is beyond the EOF. Treat it as if the data starts just after
177438c8a9a5SSteve French * the header.
177538c8a9a5SSteve French */
177638c8a9a5SSteve French cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
177738c8a9a5SSteve French __func__, data_offset);
177838c8a9a5SSteve French data_offset = server->total_read;
177938c8a9a5SSteve French } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
178038c8a9a5SSteve French /* data_offset is beyond the end of smallbuf */
178138c8a9a5SSteve French cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
178238c8a9a5SSteve French __func__, data_offset);
178338c8a9a5SSteve French rdata->result = -EIO;
178438c8a9a5SSteve French return cifs_readv_discard(server, mid);
178538c8a9a5SSteve French }
178638c8a9a5SSteve French
178738c8a9a5SSteve French cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
178838c8a9a5SSteve French __func__, server->total_read, data_offset);
178938c8a9a5SSteve French
179038c8a9a5SSteve French len = data_offset - server->total_read;
179138c8a9a5SSteve French if (len > 0) {
179238c8a9a5SSteve French /* read any junk before data into the rest of smallbuf */
179338c8a9a5SSteve French length = cifs_read_from_socket(server,
179438c8a9a5SSteve French buf + server->total_read, len);
179538c8a9a5SSteve French if (length < 0)
179638c8a9a5SSteve French return length;
179738c8a9a5SSteve French server->total_read += length;
179838c8a9a5SSteve French }
179938c8a9a5SSteve French
180038c8a9a5SSteve French /* how much data is in the response? */
180138c8a9a5SSteve French #ifdef CONFIG_CIFS_SMB_DIRECT
180238c8a9a5SSteve French use_rdma_mr = rdata->mr;
180338c8a9a5SSteve French #endif
180438c8a9a5SSteve French data_len = server->ops->read_data_length(buf, use_rdma_mr);
180538c8a9a5SSteve French if (!use_rdma_mr && (data_offset + data_len > buflen)) {
180638c8a9a5SSteve French /* data_len is corrupt -- discard frame */
180738c8a9a5SSteve French rdata->result = -EIO;
180838c8a9a5SSteve French return cifs_readv_discard(server, mid);
180938c8a9a5SSteve French }
181038c8a9a5SSteve French
181138c8a9a5SSteve French #ifdef CONFIG_CIFS_SMB_DIRECT
181238c8a9a5SSteve French if (rdata->mr)
181338c8a9a5SSteve French length = data_len; /* An RDMA read is already done. */
181438c8a9a5SSteve French else
181538c8a9a5SSteve French #endif
181638c8a9a5SSteve French length = cifs_read_iter_from_socket(server, &rdata->iter,
181738c8a9a5SSteve French data_len);
181838c8a9a5SSteve French if (length > 0)
181938c8a9a5SSteve French rdata->got_bytes += length;
182038c8a9a5SSteve French server->total_read += length;
182138c8a9a5SSteve French
182238c8a9a5SSteve French cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
182338c8a9a5SSteve French server->total_read, buflen, data_len);
182438c8a9a5SSteve French
182538c8a9a5SSteve French /* discard anything left over */
182638c8a9a5SSteve French if (server->total_read < buflen)
182738c8a9a5SSteve French return cifs_readv_discard(server, mid);
182838c8a9a5SSteve French
182938c8a9a5SSteve French dequeue_mid(mid, false);
183038c8a9a5SSteve French mid->resp_buf = server->smallbuf;
183138c8a9a5SSteve French server->smallbuf = NULL;
183238c8a9a5SSteve French return length;
183338c8a9a5SSteve French }
1834