transport.c 26.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *   fs/cifs/transport.c
 *
S
Steve French 已提交
4
 *   Copyright (C) International Business Machines  Corp., 2002,2008
L
Linus Torvalds 已提交
5
 *   Author(s): Steve French (sfrench@us.ibm.com)
6
 *   Jeremy Allison (jra@samba.org) 2006.
S
Steve French 已提交
7
 *
L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15 16 17 18 19
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
S
Steve French 已提交
20
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
L
Linus Torvalds 已提交
21 22 23 24
 */

#include <linux/fs.h>
#include <linux/list.h>
25
#include <linux/gfp.h>
L
Linus Torvalds 已提交
26 27 28
#include <linux/wait.h>
#include <linux/net.h>
#include <linux/delay.h>
29
#include <linux/freezer.h>
30
#include <linux/tcp.h>
31
#include <linux/highmem.h>
L
Linus Torvalds 已提交
32 33 34 35 36 37 38
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <linux/mempool.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"
39

40 41
void
cifs_wake_up_task(struct mid_q_entry *mid)
42 43 44 45
{
	wake_up_process(mid->callback_data);
}

J
Jeff Layton 已提交
46
struct mid_q_entry *
47
AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
48 49 50
{
	struct mid_q_entry *temp;

51
	if (server == NULL) {
52
		cERROR(1, "Null TCP session in AllocMidQEntry");
L
Linus Torvalds 已提交
53 54
		return NULL;
	}
55

56
	temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
L
Linus Torvalds 已提交
57 58 59
	if (temp == NULL)
		return temp;
	else {
60
		memset(temp, 0, sizeof(struct mid_q_entry));
L
Linus Torvalds 已提交
61 62
		temp->mid = smb_buffer->Mid;	/* always LE */
		temp->pid = current->pid;
63 64
		temp->command = cpu_to_le16(smb_buffer->Command);
		cFYI(1, "For smb_command %d", smb_buffer->Command);
S
Steve French 已提交
65 66 67
	/*	do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
		/* when mid allocated can be before when sent */
		temp->when_alloc = jiffies;
68
		temp->server = server;
69 70 71 72 73

		/*
		 * The default is for the mid to be synchronous, so the
		 * default callback just wakes up the current task.
		 */
74
		temp->callback = cifs_wake_up_task;
75
		temp->callback_data = current;
L
Linus Torvalds 已提交
76 77 78
	}

	atomic_inc(&midCount);
79
	temp->mid_state = MID_REQUEST_ALLOCATED;
L
Linus Torvalds 已提交
80 81 82
	return temp;
}

83
void
L
Linus Torvalds 已提交
84 85
DeleteMidQEntry(struct mid_q_entry *midEntry)
{
S
Steve French 已提交
86
#ifdef CONFIG_CIFS_STATS2
87
	__le16 command = midEntry->server->vals->lock_cmd;
S
Steve French 已提交
88 89
	unsigned long now;
#endif
90
	midEntry->mid_state = MID_FREE;
91
	atomic_dec(&midCount);
92
	if (midEntry->large_buf)
93 94 95
		cifs_buf_release(midEntry->resp_buf);
	else
		cifs_small_buf_release(midEntry->resp_buf);
S
Steve French 已提交
96 97 98 99
#ifdef CONFIG_CIFS_STATS2
	now = jiffies;
	/* commands taking longer than one second are indications that
	   something is wrong, unless it is quite a slow link or server */
S
Steve French 已提交
100
	if ((now - midEntry->when_alloc) > HZ) {
101
		if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
102
			printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %llu",
S
Steve French 已提交
103 104 105 106 107 108 109 110
			       midEntry->command, midEntry->mid);
			printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
			       now - midEntry->when_alloc,
			       now - midEntry->when_sent,
			       now - midEntry->when_received);
		}
	}
#endif
L
Linus Torvalds 已提交
111 112 113
	mempool_free(midEntry, cifs_mid_poolp);
}

P
Pavel Shilovsky 已提交
114 115
void
cifs_delete_mid(struct mid_q_entry *mid)
116 117 118 119 120 121 122 123
{
	spin_lock(&GlobalMid_Lock);
	list_del(&mid->qhead);
	spin_unlock(&GlobalMid_Lock);

	DeleteMidQEntry(mid);
}

124 125 126 127 128 129 130 131 132 133
/*
 * smb_send_kvec - send an array of kvecs to the server
 * @server:	Server to send the data to
 * @iov:	Pointer to array of kvecs
 * @n_vec:	length of kvec array
 * @sent:	amount of data sent on socket is stored here
 *
 * Our basic "send data to server" function. Should be called with srv_mutex
 * held. The caller is responsible for handling the results.
 */
134
static int
135 136
smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
		size_t *sent)
L
Linus Torvalds 已提交
137 138 139 140
{
	int rc = 0;
	int i = 0;
	struct msghdr smb_msg;
141 142
	unsigned int remaining;
	size_t first_vec = 0;
143
	struct socket *ssocket = server->ssocket;
144

145 146
	*sent = 0;

S
Steve French 已提交
147
	if (ssocket == NULL)
L
Linus Torvalds 已提交
148
		return -ENOTSOCK; /* BB eventually add reconnect code here */
149

150
	smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
151
	smb_msg.msg_namelen = sizeof(struct sockaddr);
L
Linus Torvalds 已提交
152 153
	smb_msg.msg_control = NULL;
	smb_msg.msg_controllen = 0;
154
	if (server->noblocksnd)
155 156 157
		smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
	else
		smb_msg.msg_flags = MSG_NOSIGNAL;
L
Linus Torvalds 已提交
158

159
	remaining = 0;
160
	for (i = 0; i < n_vec; i++)
161
		remaining += iov[i].iov_len;
L
Linus Torvalds 已提交
162

163
	i = 0;
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
	while (remaining) {
		/*
		 * If blocking send, we try 3 times, since each can block
		 * for 5 seconds. For nonblocking  we have to try more
		 * but wait increasing amounts of time allowing time for
		 * socket to clear.  The overall time we wait in either
		 * case to send on the socket is about 15 seconds.
		 * Similarly we wait for 15 seconds for a response from
		 * the server in SendReceive[2] for the server to send
		 * a response back for most types of requests (except
		 * SMB Write past end of file which can be slow, and
		 * blocking lock operations). NFS waits slightly longer
		 * than CIFS, but this can make it take longer for
		 * nonresponsive servers to be detected and 15 seconds
		 * is more than enough time for modern networks to
		 * send a packet.  In most cases if we fail to send
		 * after the retries we will kill the socket and
		 * reconnect which may clear the network problem.
		 */
183
		rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
184 185
				    n_vec - first_vec, remaining);
		if (rc == -ENOSPC || rc == -EAGAIN) {
L
Linus Torvalds 已提交
186
			i++;
187 188 189
			if (i >= 14 || (!server->noblocksnd && (i > 2))) {
				cERROR(1, "sends on sock %p stuck for 15 "
					  "seconds", ssocket);
L
Linus Torvalds 已提交
190 191 192
				rc = -EAGAIN;
				break;
			}
193
			msleep(1 << i);
L
Linus Torvalds 已提交
194 195
			continue;
		}
196

S
Steve French 已提交
197
		if (rc < 0)
L
Linus Torvalds 已提交
198
			break;
199

200 201 202 203 204
		/* send was at least partially successful */
		*sent += rc;

		if (rc == remaining) {
			remaining = 0;
S
Steve French 已提交
205
			break;
206 207 208 209
		}

		if (rc > remaining) {
			cERROR(1, "sent %d requested %d", rc, remaining);
210 211
			break;
		}
212

S
Steve French 已提交
213
		if (rc == 0) {
214 215
			/* should never happen, letting socket clear before
			   retrying is our only obvious option here */
216
			cERROR(1, "tcp sent no data");
217 218
			msleep(500);
			continue;
219
		}
220 221 222

		remaining -= rc;

223
		/* the line below resets i */
224 225 226 227 228 229 230 231 232 233 234 235
		for (i = first_vec; i < n_vec; i++) {
			if (iov[i].iov_len) {
				if (rc > iov[i].iov_len) {
					rc -= iov[i].iov_len;
					iov[i].iov_len = 0;
				} else {
					iov[i].iov_base += rc;
					iov[i].iov_len -= rc;
					first_vec = i;
					break;
				}
			}
236
		}
237

238
		i = 0; /* in case we get ENOSPC on the next send */
239
		rc = 0;
L
Linus Torvalds 已提交
240
	}
241 242 243
	return rc;
}

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
/**
 * rqst_page_to_kvec - Turn a slot in the smb_rqst page array into a kvec
 * @rqst: pointer to smb_rqst
 * @idx: index into the array of the page
 * @iov: pointer to struct kvec that will hold the result
 *
 * Helper function to convert a slot in the rqst->rq_pages array into a kvec.
 * The page will be kmapped and the address placed into iov_base. The length
 * will then be adjusted according to the ptailoff.
 */
static void
cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
			struct kvec *iov)
{
	/*
	 * FIXME: We could avoid this kmap altogether if we used
	 * kernel_sendpage instead of kernel_sendmsg. That will only
	 * work if signing is disabled though as sendpage inlines the
	 * page directly into the fraglist. If userspace modifies the
	 * page after we calculate the signature, then the server will
	 * reject it and may break the connection. kernel_sendmsg does
	 * an extra copy of the data and avoids that issue.
	 */
	iov->iov_base = kmap(rqst->rq_pages[idx]);

	/* if last page, don't send beyond this offset into page */
	if (idx == (rqst->rq_npages - 1))
		iov->iov_len = rqst->rq_tailsz;
	else
		iov->iov_len = rqst->rq_pagesz;
}

276 277 278 279 280 281 282
static int
smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
{
	int rc;
	struct kvec *iov = rqst->rq_iov;
	int n_vec = rqst->rq_nvec;
	unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
283 284
	unsigned int i;
	size_t total_len = 0, sent;
285 286
	struct socket *ssocket = server->ssocket;
	int val = 1;
287 288 289 290

	cFYI(1, "Sending smb: smb_len=%u", smb_buf_length);
	dump_smb(iov[0].iov_base, iov[0].iov_len);

291 292 293 294
	/* cork the socket */
	kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
				(char *)&val, sizeof(val));

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
	rc = smb_send_kvec(server, iov, n_vec, &sent);
	if (rc < 0)
		goto uncork;

	total_len += sent;

	/* now walk the page array and send each page in it */
	for (i = 0; i < rqst->rq_npages; i++) {
		struct kvec p_iov;

		cifs_rqst_page_to_kvec(rqst, i, &p_iov);
		rc = smb_send_kvec(server, &p_iov, 1, &sent);
		kunmap(rqst->rq_pages[i]);
		if (rc < 0)
			break;

		total_len += sent;
	}
L
Linus Torvalds 已提交
313

314
uncork:
315 316 317 318 319
	/* uncork it */
	val = 0;
	kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
				(char *)&val, sizeof(val));

320
	if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
321 322 323 324 325 326 327
		cFYI(1, "partial send (wanted=%u sent=%zu): terminating "
			"session", smb_buf_length + 4, total_len);
		/*
		 * If we have only sent part of an SMB then the next SMB could
		 * be taken as the remainder of this one. We need to kill the
		 * socket so the server throws away the partial SMB
		 */
328 329 330
		server->tcpStatus = CifsNeedReconnect;
	}

331
	if (rc < 0 && rc != -EINTR)
332
		cERROR(1, "Error %d sending data on socket to server", rc);
333
	else
L
Linus Torvalds 已提交
334 335 336 337 338
		rc = 0;

	return rc;
}

339 340 341 342 343 344 345 346 347
static int
smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
{
	struct smb_rqst rqst = { .rq_iov = iov,
				 .rq_nvec = n_vec };

	return smb_send_rqst(server, &rqst);
}

348 349 350 351 352 353 354 355 356 357 358 359
int
smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
	 unsigned int smb_buf_length)
{
	struct kvec iov;

	iov.iov_base = smb_buffer;
	iov.iov_len = smb_buf_length + 4;

	return smb_sendv(server, &iov, 1);
}

P
Pavel Shilovsky 已提交
360
static int
361
wait_for_free_credits(struct TCP_Server_Info *server, const int timeout,
362
		      int *credits)
L
Linus Torvalds 已提交
363
{
364 365
	int rc;

P
Pavel Shilovsky 已提交
366
	spin_lock(&server->req_lock);
367
	if (timeout == CIFS_ASYNC_OP) {
L
Linus Torvalds 已提交
368
		/* oplock breaks must not be held up */
P
Pavel Shilovsky 已提交
369
		server->in_flight++;
370
		*credits -= 1;
P
Pavel Shilovsky 已提交
371
		spin_unlock(&server->req_lock);
372 373 374 375
		return 0;
	}

	while (1) {
376
		if (*credits <= 0) {
P
Pavel Shilovsky 已提交
377
			spin_unlock(&server->req_lock);
378
			cifs_num_waiters_inc(server);
379
			rc = wait_event_killable(server->request_q,
380
						 has_credits(server, credits));
381
			cifs_num_waiters_dec(server);
382 383
			if (rc)
				return rc;
P
Pavel Shilovsky 已提交
384
			spin_lock(&server->req_lock);
385
		} else {
386
			if (server->tcpStatus == CifsExiting) {
P
Pavel Shilovsky 已提交
387
				spin_unlock(&server->req_lock);
388
				return -ENOENT;
L
Linus Torvalds 已提交
389
			}
390

391 392 393 394
			/*
			 * Can not count locking commands against total
			 * as they are allowed to block on server.
			 */
395 396

			/* update # of requests on the wire to server */
397
			if (timeout != CIFS_BLOCKING_OP) {
398
				*credits -= 1;
P
Pavel Shilovsky 已提交
399
				server->in_flight++;
400
			}
P
Pavel Shilovsky 已提交
401
			spin_unlock(&server->req_lock);
402
			break;
L
Linus Torvalds 已提交
403 404
		}
	}
J
[CIFS]  
Jeremy Allison 已提交
405 406
	return 0;
}
L
Linus Torvalds 已提交
407

408
static int
409 410
wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
		      const int optype)
411
{
412 413
	return wait_for_free_credits(server, timeout,
				server->ops->get_credits_field(server, optype));
414 415
}

416
static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
J
[CIFS]  
Jeremy Allison 已提交
417 418
			struct mid_q_entry **ppmidQ)
{
L
Linus Torvalds 已提交
419
	if (ses->server->tcpStatus == CifsExiting) {
J
[CIFS]  
Jeremy Allison 已提交
420
		return -ENOENT;
421 422 423
	}

	if (ses->server->tcpStatus == CifsNeedReconnect) {
424
		cFYI(1, "tcp session dead - return to caller to retry");
J
[CIFS]  
Jeremy Allison 已提交
425
		return -EAGAIN;
426 427 428
	}

	if (ses->status != CifsGood) {
L
Linus Torvalds 已提交
429
		/* check if SMB session is bad because we are setting it up */
S
Steve French 已提交
430
		if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
S
Steve French 已提交
431
			(in_buf->Command != SMB_COM_NEGOTIATE))
J
[CIFS]  
Jeremy Allison 已提交
432
			return -EAGAIN;
S
Steve French 已提交
433
		/* else ok - we are setting up session */
L
Linus Torvalds 已提交
434
	}
435
	*ppmidQ = AllocMidQEntry(in_buf, ses->server);
436
	if (*ppmidQ == NULL)
J
[CIFS]  
Jeremy Allison 已提交
437
		return -ENOMEM;
438 439 440
	spin_lock(&GlobalMid_Lock);
	list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
	spin_unlock(&GlobalMid_Lock);
J
[CIFS]  
Jeremy Allison 已提交
441 442 443
	return 0;
}

444 445
static int
wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
J
[CIFS]  
Jeremy Allison 已提交
446
{
447
	int error;
J
[CIFS]  
Jeremy Allison 已提交
448

449
	error = wait_event_freezekillable(server->response_q,
450
				    midQ->mid_state != MID_REQUEST_SUBMITTED);
451 452
	if (error < 0)
		return -ERESTARTSYS;
J
[CIFS]  
Jeremy Allison 已提交
453

454
	return 0;
J
[CIFS]  
Jeremy Allison 已提交
455 456
}

457
int
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
			 unsigned int nvec, struct mid_q_entry **ret_mid)
{
	int rc;
	struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
	struct mid_q_entry *mid;

	/* enable signing if server requires it */
	if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
		hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;

	mid = AllocMidQEntry(hdr, server);
	if (mid == NULL)
		return -ENOMEM;

473
	rc = cifs_sign_smbv(iov, nvec, server, &mid->sequence_number);
474 475 476 477 478
	if (rc) {
		DeleteMidQEntry(mid);
		return rc;
	}

479
	*ret_mid = mid;
480
	return 0;
481
}
482

J
Jeff Layton 已提交
483 484 485 486 487
/*
 * Send a SMB request and set the callback function in the mid to handle
 * the result. Caller is responsible for dealing with timeouts.
 */
int
488
cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
489
		unsigned int nvec, mid_receive_t *receive,
490
		mid_callback_t *callback, void *cbdata, const int flags)
J
Jeff Layton 已提交
491
{
492
	int rc, timeout, optype;
J
Jeff Layton 已提交
493 494
	struct mid_q_entry *mid;

495 496 497 498
	timeout = flags & CIFS_TIMEOUT_MASK;
	optype = flags & CIFS_OP_MASK;

	rc = wait_for_free_request(server, timeout, optype);
J
Jeff Layton 已提交
499 500 501 502
	if (rc)
		return rc;

	mutex_lock(&server->srv_mutex);
503
	rc = server->ops->setup_async_request(server, iov, nvec, &mid);
504
	if (rc) {
J
Jeff Layton 已提交
505
		mutex_unlock(&server->srv_mutex);
506
		add_credits(server, 1, optype);
507
		wake_up(&server->request_q);
508
		return rc;
J
Jeff Layton 已提交
509 510
	}

511
	mid->receive = receive;
J
Jeff Layton 已提交
512 513
	mid->callback = callback;
	mid->callback_data = cbdata;
514
	mid->mid_state = MID_REQUEST_SUBMITTED;
515

516 517 518 519 520 521
	/* put it on the pending_mid_q */
	spin_lock(&GlobalMid_Lock);
	list_add_tail(&mid->qhead, &server->pending_mid_q);
	spin_unlock(&GlobalMid_Lock);


522
	cifs_in_send_inc(server);
523
	rc = smb_sendv(server, iov, nvec);
524 525
	cifs_in_send_dec(server);
	cifs_save_when_sent(mid);
J
Jeff Layton 已提交
526
	mutex_unlock(&server->srv_mutex);
527

528 529
	if (rc == 0)
		return 0;
J
Jeff Layton 已提交
530

P
Pavel Shilovsky 已提交
531
	cifs_delete_mid(mid);
532
	add_credits(server, 1, optype);
J
Jeff Layton 已提交
533 534 535 536
	wake_up(&server->request_q);
	return rc;
}

537 538 539 540 541 542 543 544 545 546
/*
 *
 * Send an SMB Request.  No response info (other than return code)
 * needs to be parsed.
 *
 * flags indicate the type of request buffer and how long to wait
 * and whether to log NT STATUS code (error) before mapping it to POSIX error
 *
 */
int
547
SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
548
		 char *in_buf, int flags)
549 550 551 552 553
{
	int rc;
	struct kvec iov[1];
	int resp_buf_type;

554 555
	iov[0].iov_base = in_buf;
	iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
556 557
	flags |= CIFS_NO_RESP;
	rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
558
	cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
559

560 561 562
	return rc;
}

563
static int
564
cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
565 566 567
{
	int rc = 0;

568 569
	cFYI(1, "%s: cmd=%d mid=%llu state=%d", __func__,
	     le16_to_cpu(mid->command), mid->mid, mid->mid_state);
570

J
Jeff Layton 已提交
571
	spin_lock(&GlobalMid_Lock);
572
	switch (mid->mid_state) {
J
Jeff Layton 已提交
573
	case MID_RESPONSE_RECEIVED:
574 575
		spin_unlock(&GlobalMid_Lock);
		return rc;
J
Jeff Layton 已提交
576 577 578
	case MID_RETRY_NEEDED:
		rc = -EAGAIN;
		break;
579 580 581
	case MID_RESPONSE_MALFORMED:
		rc = -EIO;
		break;
582 583 584
	case MID_SHUTDOWN:
		rc = -EHOSTDOWN;
		break;
J
Jeff Layton 已提交
585
	default:
586
		list_del_init(&mid->qhead);
587 588
		cERROR(1, "%s: invalid mid state mid=%llu state=%d", __func__,
		       mid->mid, mid->mid_state);
J
Jeff Layton 已提交
589
		rc = -EIO;
590 591 592
	}
	spin_unlock(&GlobalMid_Lock);

593
	DeleteMidQEntry(mid);
594 595 596
	return rc;
}

597 598
static inline int
send_cancel(struct TCP_Server_Info *server, void *buf, struct mid_q_entry *mid)
599
{
600 601
	return server->ops->send_cancel ?
				server->ops->send_cancel(server, buf, mid) : 0;
602 603
}

604 605 606 607
int
cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
		   bool log_error)
{
608
	unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
609 610

	dump_smb(mid->resp_buf, min_t(u32, 92, len));
611 612

	/* convert the length into a more usable form */
613
	if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
614
		struct kvec iov;
615
		int rc = 0;
616 617
		struct smb_rqst rqst = { .rq_iov = &iov,
					 .rq_nvec = 1 };
618 619 620

		iov.iov_base = mid->resp_buf;
		iov.iov_len = len;
621
		/* FIXME: add code to kill session */
622
		rc = cifs_verify_signature(&rqst, server,
623 624 625 626
					   mid->sequence_number + 1);
		if (rc)
			cERROR(1, "SMB signature verification returned error = "
			       "%d", rc);
627 628 629 630 631 632
	}

	/* BB special case reconnect tid and uid here? */
	return map_smb_to_linux_error(mid->resp_buf, log_error);
}

633
int
634 635 636 637 638 639 640 641 642 643
cifs_setup_request(struct cifs_ses *ses, struct kvec *iov,
		   unsigned int nvec, struct mid_q_entry **ret_mid)
{
	int rc;
	struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
	struct mid_q_entry *mid;

	rc = allocate_mid(ses, hdr, &mid);
	if (rc)
		return rc;
644
	rc = cifs_sign_smbv(iov, nvec, ses->server, &mid->sequence_number);
645
	if (rc)
P
Pavel Shilovsky 已提交
646
		cifs_delete_mid(mid);
647 648 649 650
	*ret_mid = mid;
	return rc;
}

J
[CIFS]  
Jeremy Allison 已提交
651
int
652
SendReceive2(const unsigned int xid, struct cifs_ses *ses,
653
	     struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
654
	     const int flags)
J
[CIFS]  
Jeremy Allison 已提交
655 656
{
	int rc = 0;
657
	int timeout, optype;
J
[CIFS]  
Jeremy Allison 已提交
658
	struct mid_q_entry *midQ;
659
	char *buf = iov[0].iov_base;
660
	unsigned int credits = 1;
661

662 663
	timeout = flags & CIFS_TIMEOUT_MASK;
	optype = flags & CIFS_OP_MASK;
664

665
	*resp_buf_type = CIFS_NO_BUFFER;  /* no response buf yet */
J
[CIFS]  
Jeremy Allison 已提交
666 667

	if ((ses == NULL) || (ses->server == NULL)) {
668
		cifs_small_buf_release(buf);
669
		cERROR(1, "Null session");
J
[CIFS]  
Jeremy Allison 已提交
670 671 672
		return -EIO;
	}

S
Steve French 已提交
673
	if (ses->server->tcpStatus == CifsExiting) {
674
		cifs_small_buf_release(buf);
J
[CIFS]  
Jeremy Allison 已提交
675 676 677
		return -ENOENT;
	}

678 679 680 681 682
	/*
	 * Ensure that we do not send more than 50 overlapping requests
	 * to the same server. We may make this configurable later or
	 * use ses->maxReq.
	 */
J
[CIFS]  
Jeremy Allison 已提交
683

684
	rc = wait_for_free_request(ses->server, timeout, optype);
J
[CIFS]  
Jeremy Allison 已提交
685
	if (rc) {
686
		cifs_small_buf_release(buf);
J
[CIFS]  
Jeremy Allison 已提交
687 688 689
		return rc;
	}

690 691 692 693 694
	/*
	 * Make sure that we sign in the same order that we send on this socket
	 * and avoid races inside tcp sendmsg code that could cause corruption
	 * of smb data.
	 */
J
[CIFS]  
Jeremy Allison 已提交
695

J
Jeff Layton 已提交
696
	mutex_lock(&ses->server->srv_mutex);
J
[CIFS]  
Jeremy Allison 已提交
697

698
	rc = ses->server->ops->setup_request(ses, iov, n_vec, &midQ);
J
[CIFS]  
Jeremy Allison 已提交
699
	if (rc) {
J
Jeff Layton 已提交
700
		mutex_unlock(&ses->server->srv_mutex);
701
		cifs_small_buf_release(buf);
J
[CIFS]  
Jeremy Allison 已提交
702
		/* Update # of requests on wire to server */
703
		add_credits(ses->server, 1, optype);
J
[CIFS]  
Jeremy Allison 已提交
704
		return rc;
L
Linus Torvalds 已提交
705 706
	}

707
	midQ->mid_state = MID_REQUEST_SUBMITTED;
708
	cifs_in_send_inc(ses->server);
709
	rc = smb_sendv(ses->server, iov, n_vec);
710 711
	cifs_in_send_dec(ses->server);
	cifs_save_when_sent(midQ);
J
[CIFS]  
Jeremy Allison 已提交
712

J
Jeff Layton 已提交
713
	mutex_unlock(&ses->server->srv_mutex);
J
[CIFS]  
Jeremy Allison 已提交
714

715
	if (rc < 0) {
716
		cifs_small_buf_release(buf);
J
[CIFS]  
Jeremy Allison 已提交
717
		goto out;
718
	}
719

720
	if (timeout == CIFS_ASYNC_OP) {
721
		cifs_small_buf_release(buf);
722
		goto out;
723
	}
724

725
	rc = wait_for_response(ses->server, midQ);
726
	if (rc != 0) {
727
		send_cancel(ses->server, buf, midQ);
728
		spin_lock(&GlobalMid_Lock);
729
		if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
730 731
			midQ->callback = DeleteMidQEntry;
			spin_unlock(&GlobalMid_Lock);
732
			cifs_small_buf_release(buf);
733
			add_credits(ses->server, 1, optype);
734 735 736 737
			return rc;
		}
		spin_unlock(&GlobalMid_Lock);
	}
738

739
	cifs_small_buf_release(buf);
740

741
	rc = cifs_sync_mid_result(midQ, ses->server);
742
	if (rc != 0) {
743
		add_credits(ses->server, 1, optype);
744 745
		return rc;
	}
746

747
	if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
748
		rc = -EIO;
749
		cFYI(1, "Bad MID state?");
750 751 752
		goto out;
	}

753 754 755
	buf = (char *)midQ->resp_buf;
	iov[0].iov_base = buf;
	iov[0].iov_len = get_rfc1002_length(buf) + 4;
756
	if (midQ->large_buf)
757
		*resp_buf_type = CIFS_LARGE_BUFFER;
758
	else
759 760 761
		*resp_buf_type = CIFS_SMALL_BUFFER;

	credits = ses->server->ops->get_credits(midQ);
762

763 764
	rc = ses->server->ops->check_receive(midQ, ses->server,
					     flags & CIFS_LOG_ERROR);
L
Linus Torvalds 已提交
765

P
Pavel Shilovsky 已提交
766
	/* mark it so buf will not be freed by cifs_delete_mid */
767 768
	if ((flags & CIFS_NO_RESP) == 0)
		midQ->resp_buf = NULL;
J
[CIFS]  
Jeremy Allison 已提交
769
out:
P
Pavel Shilovsky 已提交
770
	cifs_delete_mid(midQ);
771
	add_credits(ses->server, credits, optype);
L
Linus Torvalds 已提交
772

773 774
	return rc;
}
L
Linus Torvalds 已提交
775 776

int
777
SendReceive(const unsigned int xid, struct cifs_ses *ses,
L
Linus Torvalds 已提交
778
	    struct smb_hdr *in_buf, struct smb_hdr *out_buf,
779
	    int *pbytes_returned, const int timeout)
L
Linus Torvalds 已提交
780 781 782 783 784
{
	int rc = 0;
	struct mid_q_entry *midQ;

	if (ses == NULL) {
785
		cERROR(1, "Null smb session");
L
Linus Torvalds 已提交
786 787
		return -EIO;
	}
S
Steve French 已提交
788
	if (ses->server == NULL) {
789
		cERROR(1, "Null tcp session");
L
Linus Torvalds 已提交
790 791 792
		return -EIO;
	}

S
Steve French 已提交
793
	if (ses->server->tcpStatus == CifsExiting)
794 795
		return -ENOENT;

S
Steve French 已提交
796
	/* Ensure that we do not send more than 50 overlapping requests
L
Linus Torvalds 已提交
797 798 799
	   to the same server. We may make this configurable later or
	   use ses->maxReq */

800 801
	if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
			MAX_CIFS_HDR_SIZE - 4) {
802
		cERROR(1, "Illegal length, greater than maximum frame, %d",
803
			   be32_to_cpu(in_buf->smb_buf_length));
804 805 806
		return -EIO;
	}

807
	rc = wait_for_free_request(ses->server, timeout, 0);
J
[CIFS]  
Jeremy Allison 已提交
808 809 810
	if (rc)
		return rc;

S
Steve French 已提交
811
	/* make sure that we sign in the same order that we send on this socket
L
Linus Torvalds 已提交
812 813 814
	   and avoid races inside tcp sendmsg code that could cause corruption
	   of smb data */

J
Jeff Layton 已提交
815
	mutex_lock(&ses->server->srv_mutex);
L
Linus Torvalds 已提交
816

J
[CIFS]  
Jeremy Allison 已提交
817 818
	rc = allocate_mid(ses, in_buf, &midQ);
	if (rc) {
J
Jeff Layton 已提交
819
		mutex_unlock(&ses->server->srv_mutex);
J
[CIFS]  
Jeremy Allison 已提交
820
		/* Update # of requests on wire to server */
821
		add_credits(ses->server, 1, 0);
J
[CIFS]  
Jeremy Allison 已提交
822
		return rc;
L
Linus Torvalds 已提交
823 824
	}

825
	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
826 827 828 829
	if (rc) {
		mutex_unlock(&ses->server->srv_mutex);
		goto out;
	}
L
Linus Torvalds 已提交
830

831
	midQ->mid_state = MID_REQUEST_SUBMITTED;
832 833

	cifs_in_send_inc(ses->server);
834
	rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
835 836
	cifs_in_send_dec(ses->server);
	cifs_save_when_sent(midQ);
J
Jeff Layton 已提交
837
	mutex_unlock(&ses->server->srv_mutex);
J
[CIFS]  
Jeremy Allison 已提交
838

S
Steve French 已提交
839
	if (rc < 0)
J
[CIFS]  
Jeremy Allison 已提交
840 841
		goto out;

842
	if (timeout == CIFS_ASYNC_OP)
J
[CIFS]  
Jeremy Allison 已提交
843
		goto out;
L
Linus Torvalds 已提交
844

845
	rc = wait_for_response(ses->server, midQ);
846
	if (rc != 0) {
847
		send_cancel(ses->server, in_buf, midQ);
848
		spin_lock(&GlobalMid_Lock);
849
		if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
850 851 852
			/* no longer considered to be "in-flight" */
			midQ->callback = DeleteMidQEntry;
			spin_unlock(&GlobalMid_Lock);
853
			add_credits(ses->server, 1, 0);
854 855 856 857
			return rc;
		}
		spin_unlock(&GlobalMid_Lock);
	}
L
Linus Torvalds 已提交
858

859
	rc = cifs_sync_mid_result(midQ, ses->server);
860
	if (rc != 0) {
861
		add_credits(ses->server, 1, 0);
L
Linus Torvalds 已提交
862 863
		return rc;
	}
864

865
	if (!midQ->resp_buf || !out_buf ||
866
	    midQ->mid_state != MID_RESPONSE_RECEIVED) {
867
		rc = -EIO;
868
		cERROR(1, "Bad MID state?");
869
		goto out;
L
Linus Torvalds 已提交
870
	}
J
[CIFS]  
Jeremy Allison 已提交
871

872
	*pbytes_returned = get_rfc1002_length(midQ->resp_buf);
873 874
	memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
	rc = cifs_check_receive(midQ, ses->server, 0);
J
[CIFS]  
Jeremy Allison 已提交
875
out:
P
Pavel Shilovsky 已提交
876
	cifs_delete_mid(midQ);
877
	add_credits(ses->server, 1, 0);
L
Linus Torvalds 已提交
878

J
[CIFS]  
Jeremy Allison 已提交
879 880
	return rc;
}
L
Linus Torvalds 已提交
881

J
[CIFS]  
Jeremy Allison 已提交
882 883 884 885
/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
   blocking lock to return. */

static int
886
send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
J
[CIFS]  
Jeremy Allison 已提交
887 888 889 890
			struct smb_hdr *in_buf,
			struct smb_hdr *out_buf)
{
	int bytes_returned;
891
	struct cifs_ses *ses = tcon->ses;
J
[CIFS]  
Jeremy Allison 已提交
892 893 894 895 896 897 898 899 900
	LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;

	/* We just modify the current in_buf to change
	   the type of lock from LOCKING_ANDX_SHARED_LOCK
	   or LOCKING_ANDX_EXCLUSIVE_LOCK to
	   LOCKING_ANDX_CANCEL_LOCK. */

	pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
	pSMB->Timeout = 0;
901
	pSMB->hdr.Mid = get_next_mid(ses->server);
J
[CIFS]  
Jeremy Allison 已提交
902 903

	return SendReceive(xid, ses, in_buf, out_buf,
904
			&bytes_returned, 0);
J
[CIFS]  
Jeremy Allison 已提交
905 906 907
}

int
908
SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
J
[CIFS]  
Jeremy Allison 已提交
909 910 911 912 913 914
	    struct smb_hdr *in_buf, struct smb_hdr *out_buf,
	    int *pbytes_returned)
{
	int rc = 0;
	int rstart = 0;
	struct mid_q_entry *midQ;
915
	struct cifs_ses *ses;
J
[CIFS]  
Jeremy Allison 已提交
916 917

	if (tcon == NULL || tcon->ses == NULL) {
918
		cERROR(1, "Null smb session");
J
[CIFS]  
Jeremy Allison 已提交
919 920 921 922
		return -EIO;
	}
	ses = tcon->ses;

S
Steve French 已提交
923
	if (ses->server == NULL) {
924
		cERROR(1, "Null tcp session");
J
[CIFS]  
Jeremy Allison 已提交
925 926 927
		return -EIO;
	}

S
Steve French 已提交
928
	if (ses->server->tcpStatus == CifsExiting)
J
[CIFS]  
Jeremy Allison 已提交
929 930
		return -ENOENT;

S
Steve French 已提交
931
	/* Ensure that we do not send more than 50 overlapping requests
J
[CIFS]  
Jeremy Allison 已提交
932 933 934
	   to the same server. We may make this configurable later or
	   use ses->maxReq */

935 936
	if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
			MAX_CIFS_HDR_SIZE - 4) {
937
		cERROR(1, "Illegal length, greater than maximum frame, %d",
938
			   be32_to_cpu(in_buf->smb_buf_length));
939 940 941
		return -EIO;
	}

942
	rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0);
J
[CIFS]  
Jeremy Allison 已提交
943 944 945
	if (rc)
		return rc;

S
Steve French 已提交
946
	/* make sure that we sign in the same order that we send on this socket
J
[CIFS]  
Jeremy Allison 已提交
947 948 949
	   and avoid races inside tcp sendmsg code that could cause corruption
	   of smb data */

J
Jeff Layton 已提交
950
	mutex_lock(&ses->server->srv_mutex);
J
[CIFS]  
Jeremy Allison 已提交
951 952 953

	rc = allocate_mid(ses, in_buf, &midQ);
	if (rc) {
J
Jeff Layton 已提交
954
		mutex_unlock(&ses->server->srv_mutex);
J
[CIFS]  
Jeremy Allison 已提交
955 956 957 958
		return rc;
	}

	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
959
	if (rc) {
P
Pavel Shilovsky 已提交
960
		cifs_delete_mid(midQ);
961 962 963
		mutex_unlock(&ses->server->srv_mutex);
		return rc;
	}
L
Linus Torvalds 已提交
964

965
	midQ->mid_state = MID_REQUEST_SUBMITTED;
966
	cifs_in_send_inc(ses->server);
967
	rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
968 969
	cifs_in_send_dec(ses->server);
	cifs_save_when_sent(midQ);
J
Jeff Layton 已提交
970
	mutex_unlock(&ses->server->srv_mutex);
J
[CIFS]  
Jeremy Allison 已提交
971

S
Steve French 已提交
972
	if (rc < 0) {
P
Pavel Shilovsky 已提交
973
		cifs_delete_mid(midQ);
J
[CIFS]  
Jeremy Allison 已提交
974 975 976 977 978
		return rc;
	}

	/* Wait for a reply - allow signals to interrupt. */
	rc = wait_event_interruptible(ses->server->response_q,
979
		(!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
J
[CIFS]  
Jeremy Allison 已提交
980 981 982 983 984
		((ses->server->tcpStatus != CifsGood) &&
		 (ses->server->tcpStatus != CifsNew)));

	/* Were we interrupted by a signal ? */
	if ((rc == -ERESTARTSYS) &&
985
		(midQ->mid_state == MID_REQUEST_SUBMITTED) &&
J
[CIFS]  
Jeremy Allison 已提交
986 987 988 989 990 991
		((ses->server->tcpStatus == CifsGood) ||
		 (ses->server->tcpStatus == CifsNew))) {

		if (in_buf->Command == SMB_COM_TRANSACTION2) {
			/* POSIX lock. We send a NT_CANCEL SMB to cause the
			   blocking lock to return. */
992
			rc = send_cancel(ses->server, in_buf, midQ);
J
[CIFS]  
Jeremy Allison 已提交
993
			if (rc) {
P
Pavel Shilovsky 已提交
994
				cifs_delete_mid(midQ);
J
[CIFS]  
Jeremy Allison 已提交
995 996 997 998 999 1000 1001 1002 1003 1004 1005
				return rc;
			}
		} else {
			/* Windows lock. We send a LOCKINGX_CANCEL_LOCK
			   to cause the blocking lock to return. */

			rc = send_lock_cancel(xid, tcon, in_buf, out_buf);

			/* If we get -ENOLCK back the lock may have
			   already been removed. Don't exit in this case. */
			if (rc && rc != -ENOLCK) {
P
Pavel Shilovsky 已提交
1006
				cifs_delete_mid(midQ);
J
[CIFS]  
Jeremy Allison 已提交
1007 1008 1009 1010
				return rc;
			}
		}

1011 1012
		rc = wait_for_response(ses->server, midQ);
		if (rc) {
1013
			send_cancel(ses->server, in_buf, midQ);
1014
			spin_lock(&GlobalMid_Lock);
1015
			if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
1016 1017 1018 1019 1020 1021
				/* no longer considered to be "in-flight" */
				midQ->callback = DeleteMidQEntry;
				spin_unlock(&GlobalMid_Lock);
				return rc;
			}
			spin_unlock(&GlobalMid_Lock);
J
[CIFS]  
Jeremy Allison 已提交
1022
		}
1023 1024 1025

		/* We got the response - restart system call. */
		rstart = 1;
J
[CIFS]  
Jeremy Allison 已提交
1026 1027
	}

1028
	rc = cifs_sync_mid_result(midQ, ses->server);
1029
	if (rc != 0)
J
[CIFS]  
Jeremy Allison 已提交
1030
		return rc;
1031

1032
	/* rcvd frame is ok */
1033
	if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
1034
		rc = -EIO;
1035
		cERROR(1, "Bad MID state?");
1036 1037
		goto out;
	}
L
Linus Torvalds 已提交
1038

1039
	*pbytes_returned = get_rfc1002_length(midQ->resp_buf);
1040 1041
	memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
	rc = cifs_check_receive(midQ, ses->server, 0);
1042
out:
P
Pavel Shilovsky 已提交
1043
	cifs_delete_mid(midQ);
J
[CIFS]  
Jeremy Allison 已提交
1044 1045
	if (rstart && rc == -EACCES)
		return -ERESTARTSYS;
L
Linus Torvalds 已提交
1046 1047
	return rc;
}