Blame view

fs/cifs/transport.c 23.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   *   fs/cifs/transport.c
   *
ad7a2926b   Steve French   [CIFS] reduce che...
4
   *   Copyright (C) International Business Machines  Corp., 2002,2008
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
   *   Author(s): Steve French (sfrench@us.ibm.com)
14a441a2b   Steve French   [CIFS] spinlock p...
6
   *   Jeremy Allison (jra@samba.org) 2006.
79a58d1f6   Steve French   [CIFS] whitespace...
7
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
79a58d1f6   Steve French   [CIFS] whitespace...
20
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
   */
  
  #include <linux/fs.h>
  #include <linux/list.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
25
  #include <linux/gfp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
  #include <linux/wait.h>
  #include <linux/net.h>
  #include <linux/delay.h>
f06ac72e9   Jeff Layton   cifs, freezer: ad...
29
  #include <linux/freezer.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
35
36
  #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"
50c2f7538   Steve French   [CIFS] whitespace...
37

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  extern mempool_t *cifs_mid_poolp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39

2b84a36c5   Jeff Layton   cifs: allow for d...
40
41
42
43
44
  static void
  wake_up_task(struct mid_q_entry *mid)
  {
  	wake_up_process(mid->callback_data);
  }
a6827c184   Jeff Layton   cifs: add cifs_ca...
45
  struct mid_q_entry *
24b9b06ba   Jeff Layton   cifs: remove unus...
46
  AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
  {
  	struct mid_q_entry *temp;
24b9b06ba   Jeff Layton   cifs: remove unus...
49
  	if (server == NULL) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
50
  		cERROR(1, "Null TCP session in AllocMidQEntry");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  		return NULL;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
53

232087cb7   Pekka Enberg   cifs: don't use G...
54
  	temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
  	if (temp == NULL)
  		return temp;
  	else {
26f57364d   Steve French   [CIFS] formatting...
58
  		memset(temp, 0, sizeof(struct mid_q_entry));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
  		temp->mid = smb_buffer->Mid;	/* always LE */
  		temp->pid = current->pid;
  		temp->command = smb_buffer->Command;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
62
  		cFYI(1, "For smb_command %d", temp->command);
1047abc15   Steve French   [CIFS] CIFS Stats...
63
64
65
  	/*	do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
  		/* when mid allocated can be before when sent */
  		temp->when_alloc = jiffies;
2b84a36c5   Jeff Layton   cifs: allow for d...
66
67
68
69
70
71
72
  
  		/*
  		 * The default is for the mid to be synchronous, so the
  		 * default callback just wakes up the current task.
  		 */
  		temp->callback = wake_up_task;
  		temp->callback_data = current;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
  	atomic_inc(&midCount);
  	temp->midState = MID_REQUEST_ALLOCATED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
  	return temp;
  }
766fdbb57   Jeff Layton   cifs: add ability...
78
  void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
  DeleteMidQEntry(struct mid_q_entry *midEntry)
  {
1047abc15   Steve French   [CIFS] CIFS Stats...
81
82
83
  #ifdef CONFIG_CIFS_STATS2
  	unsigned long now;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  	midEntry->midState = MID_FREE;
8097531a5   Jeff Layton   cifs: clean up ac...
85
  	atomic_dec(&midCount);
79a58d1f6   Steve French   [CIFS] whitespace...
86
  	if (midEntry->largeBuf)
b8643e1b5   Steve French   [PATCH] cifs: Do ...
87
88
89
  		cifs_buf_release(midEntry->resp_buf);
  	else
  		cifs_small_buf_release(midEntry->resp_buf);
1047abc15   Steve French   [CIFS] CIFS Stats...
90
91
92
93
  #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 */
79a58d1f6   Steve French   [CIFS] whitespace...
94
95
  	if ((now - midEntry->when_alloc) > HZ) {
  		if ((cifsFYI & CIFS_TIMER) &&
1047abc15   Steve French   [CIFS] CIFS Stats...
96
97
98
99
100
101
102
103
104
105
106
  		   (midEntry->command != SMB_COM_LOCKING_ANDX)) {
  			printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
  			       midEntry->command, midEntry->mid);
  			printk(" A: 0x%lx S: 0x%lx R: 0x%lx
  ",
  			       now - midEntry->when_alloc,
  			       now - midEntry->when_sent,
  			       now - midEntry->when_received);
  		}
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
  	mempool_free(midEntry, cifs_mid_poolp);
  }
ddc8cf8fc   Jeff Layton   cifs: move locked...
109
110
111
112
113
114
115
116
117
  static void
  delete_mid(struct mid_q_entry *mid)
  {
  	spin_lock(&GlobalMid_Lock);
  	list_del(&mid->qhead);
  	spin_unlock(&GlobalMid_Lock);
  
  	DeleteMidQEntry(mid);
  }
d6e04ae64   Steve French   [CIFS] CIFS write...
118
  static int
0496e02d8   Jeff Layton   cifs: turn smb_se...
119
  smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
  {
  	int rc = 0;
  	int i = 0;
  	struct msghdr smb_msg;
3e84469d0   Steve French   [CIFS] Add writep...
124
125
126
127
  	struct smb_hdr *smb_buffer = iov[0].iov_base;
  	unsigned int len = iov[0].iov_len;
  	unsigned int total_len;
  	int first_vec = 0;
be8e3b004   Steve French   consistently use ...
128
  	unsigned int smb_buf_length = be32_to_cpu(smb_buffer->smb_buf_length);
edf1ae403   Steve French   [CIFS] Reduce num...
129
  	struct socket *ssocket = server->ssocket;
50c2f7538   Steve French   [CIFS] whitespace...
130

79a58d1f6   Steve French   [CIFS] whitespace...
131
  	if (ssocket == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  		return -ENOTSOCK; /* BB eventually add reconnect code here */
3e84469d0   Steve French   [CIFS] Add writep...
133

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
134
  	smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
26f57364d   Steve French   [CIFS] formatting...
135
  	smb_msg.msg_namelen = sizeof(struct sockaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
  	smb_msg.msg_control = NULL;
  	smb_msg.msg_controllen = 0;
0496e02d8   Jeff Layton   cifs: turn smb_se...
138
  	if (server->noblocksnd)
edf1ae403   Steve French   [CIFS] Reduce num...
139
140
141
  		smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
  	else
  		smb_msg.msg_flags = MSG_NOSIGNAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142

3e84469d0   Steve French   [CIFS] Add writep...
143
144
145
  	total_len = 0;
  	for (i = 0; i < n_vec; i++)
  		total_len += iov[i].iov_len;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
146
  	cFYI(1, "Sending smb:  total_len %d", total_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  	dump_smb(smb_buffer, len);
176803562   Shirish Pargaonkar   [CIFS] cifs send2...
148
  	i = 0;
3e84469d0   Steve French   [CIFS] Add writep...
149
150
151
  	while (total_len) {
  		rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
  				    n_vec - first_vec, total_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
  		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
  			i++;
da505c386   Steve French   [CIFS] Make socke...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  			/* 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.
  			*/
  			if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
173
174
  				cERROR(1, "sends on sock %p stuck for 15 seconds",
  				    ssocket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
  				rc = -EAGAIN;
  				break;
  			}
68058e757   Steve French   [CIFS] Reduce CIF...
178
  			msleep(1 << i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
  			continue;
  		}
79a58d1f6   Steve French   [CIFS] whitespace...
181
  		if (rc < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  			break;
3e84469d0   Steve French   [CIFS] Add writep...
183

61de800d3   Steve French   [CIFS] fix error ...
184
185
186
187
  		if (rc == total_len) {
  			total_len = 0;
  			break;
  		} else if (rc > total_len) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
188
  			cERROR(1, "sent %d requested %d", rc, total_len);
3e84469d0   Steve French   [CIFS] Add writep...
189
190
  			break;
  		}
79a58d1f6   Steve French   [CIFS] whitespace...
191
  		if (rc == 0) {
3e84469d0   Steve French   [CIFS] Add writep...
192
193
  			/* should never happen, letting socket clear before
  			   retrying is our only obvious option here */
b6b38f704   Joe Perches   [CIFS] Neaten cER...
194
  			cERROR(1, "tcp sent no data");
3e84469d0   Steve French   [CIFS] Add writep...
195
196
  			msleep(500);
  			continue;
d6e04ae64   Steve French   [CIFS] CIFS write...
197
  		}
3e84469d0   Steve French   [CIFS] Add writep...
198
  		total_len -= rc;
68058e757   Steve French   [CIFS] Reduce CIF...
199
  		/* the line below resets i */
3e84469d0   Steve French   [CIFS] Add writep...
200
201
202
203
204
205
206
207
208
209
210
211
  		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;
  				}
  			}
d6e04ae64   Steve French   [CIFS] CIFS write...
212
  		}
5e1253b50   Steve French   [CIFS] Correct ci...
213
  		i = 0; /* in case we get ENOSPC on the next send */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  	}
edf1ae403   Steve French   [CIFS] Reduce num...
215
  	if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
216
217
  		cFYI(1, "partial send (%d remaining), terminating session",
  			total_len);
edf1ae403   Steve French   [CIFS] Reduce num...
218
219
220
221
222
223
  		/* 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 */
  		server->tcpStatus = CifsNeedReconnect;
  	}
d804d41d1   Jeff Layton   cifs: don't pop a...
224
  	if (rc < 0 && rc != -EINTR)
b6b38f704   Joe Perches   [CIFS] Neaten cER...
225
  		cERROR(1, "Error %d sending data on socket to server", rc);
d804d41d1   Jeff Layton   cifs: don't pop a...
226
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
  		rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228

7ee1af765   Jeremy Allison   [CIFS]
229
230
  	/* Don't want to modify the buffer as a
  	   side effect of this call. */
be8e3b004   Steve French   consistently use ...
231
  	smb_buffer->smb_buf_length = cpu_to_be32(smb_buf_length);
7ee1af765   Jeremy Allison   [CIFS]
232

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
  	return rc;
  }
0496e02d8   Jeff Layton   cifs: turn smb_se...
235
236
237
238
239
240
241
242
243
244
245
  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);
  }
c5797a945   Jeff Layton   cifs: make wait_f...
246
247
  static int wait_for_free_request(struct TCP_Server_Info *server,
  				 const int long_op)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  {
133672efb   Steve French   [CIFS] Fix buffer...
249
  	if (long_op == CIFS_ASYNC_OP) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  		/* oplock breaks must not be held up */
c5797a945   Jeff Layton   cifs: make wait_f...
251
  		atomic_inc(&server->inFlight);
27a97a613   Volker Lendecke   [CIFS] Slightly s...
252
253
254
255
256
  		return 0;
  	}
  
  	spin_lock(&GlobalMid_Lock);
  	while (1) {
c5797a945   Jeff Layton   cifs: make wait_f...
257
  		if (atomic_read(&server->inFlight) >= cifs_max_pending) {
27a97a613   Volker Lendecke   [CIFS] Slightly s...
258
  			spin_unlock(&GlobalMid_Lock);
789e66612   Steve French   [CIFS] Cleanup us...
259
  			cifs_num_waiters_inc(server);
c5797a945   Jeff Layton   cifs: make wait_f...
260
261
  			wait_event(server->request_q,
  				   atomic_read(&server->inFlight)
27a97a613   Volker Lendecke   [CIFS] Slightly s...
262
  				     < cifs_max_pending);
789e66612   Steve French   [CIFS] Cleanup us...
263
  			cifs_num_waiters_dec(server);
27a97a613   Volker Lendecke   [CIFS] Slightly s...
264
265
  			spin_lock(&GlobalMid_Lock);
  		} else {
c5797a945   Jeff Layton   cifs: make wait_f...
266
  			if (server->tcpStatus == CifsExiting) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  				spin_unlock(&GlobalMid_Lock);
27a97a613   Volker Lendecke   [CIFS] Slightly s...
268
  				return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  			}
27a97a613   Volker Lendecke   [CIFS] Slightly s...
270
271
272
273
274
275
  
  			/* can not count locking commands against total
  			   as they are allowed to block on server */
  
  			/* update # of requests on the wire to server */
  			if (long_op != CIFS_BLOCKING_OP)
c5797a945   Jeff Layton   cifs: make wait_f...
276
  				atomic_inc(&server->inFlight);
27a97a613   Volker Lendecke   [CIFS] Slightly s...
277
278
  			spin_unlock(&GlobalMid_Lock);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
  		}
  	}
7ee1af765   Jeremy Allison   [CIFS]
281
282
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283

96daf2b09   Steve French   [CIFS] Rename thr...
284
  static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
7ee1af765   Jeremy Allison   [CIFS]
285
286
  			struct mid_q_entry **ppmidQ)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  	if (ses->server->tcpStatus == CifsExiting) {
7ee1af765   Jeremy Allison   [CIFS]
288
  		return -ENOENT;
8fbbd365c   Volker Lendecke   Simplify allocate...
289
290
291
  	}
  
  	if (ses->server->tcpStatus == CifsNeedReconnect) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
292
  		cFYI(1, "tcp session dead - return to caller to retry");
7ee1af765   Jeremy Allison   [CIFS]
293
  		return -EAGAIN;
8fbbd365c   Volker Lendecke   Simplify allocate...
294
295
296
  	}
  
  	if (ses->status != CifsGood) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
  		/* check if SMB session is bad because we are setting it up */
79a58d1f6   Steve French   [CIFS] whitespace...
298
  		if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
ad7a2926b   Steve French   [CIFS] reduce che...
299
  			(in_buf->Command != SMB_COM_NEGOTIATE))
7ee1af765   Jeremy Allison   [CIFS]
300
  			return -EAGAIN;
ad7a2926b   Steve French   [CIFS] reduce che...
301
  		/* else ok - we are setting up session */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
  	}
24b9b06ba   Jeff Layton   cifs: remove unus...
303
  	*ppmidQ = AllocMidQEntry(in_buf, ses->server);
26f57364d   Steve French   [CIFS] formatting...
304
  	if (*ppmidQ == NULL)
7ee1af765   Jeremy Allison   [CIFS]
305
  		return -ENOMEM;
ddc8cf8fc   Jeff Layton   cifs: move locked...
306
307
308
  	spin_lock(&GlobalMid_Lock);
  	list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
  	spin_unlock(&GlobalMid_Lock);
7ee1af765   Jeremy Allison   [CIFS]
309
310
  	return 0;
  }
0ade640e9   Jeff Layton   cifs: wait indefi...
311
312
  static int
  wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
7ee1af765   Jeremy Allison   [CIFS]
313
  {
0ade640e9   Jeff Layton   cifs: wait indefi...
314
  	int error;
7ee1af765   Jeremy Allison   [CIFS]
315

f06ac72e9   Jeff Layton   cifs, freezer: ad...
316
  	error = wait_event_freezekillable(server->response_q,
0ade640e9   Jeff Layton   cifs: wait indefi...
317
318
319
  				    midQ->midState != MID_REQUEST_SUBMITTED);
  	if (error < 0)
  		return -ERESTARTSYS;
7ee1af765   Jeremy Allison   [CIFS]
320

0ade640e9   Jeff Layton   cifs: wait indefi...
321
  	return 0;
7ee1af765   Jeremy Allison   [CIFS]
322
  }
133672efb   Steve French   [CIFS] Fix buffer...
323
324
  
  /*
a6827c184   Jeff Layton   cifs: add cifs_ca...
325
326
327
328
   * Send a SMB request and set the callback function in the mid to handle
   * the result. Caller is responsible for dealing with timeouts.
   */
  int
fcc31cb6f   Jeff Layton   cifs: make cifs_s...
329
  cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
44d22d846   Jeff Layton   cifs: add a callb...
330
331
  		unsigned int nvec, mid_receive_t *receive,
  		mid_callback_t *callback, void *cbdata, bool ignore_pend)
a6827c184   Jeff Layton   cifs: add cifs_ca...
332
333
334
  {
  	int rc;
  	struct mid_q_entry *mid;
fcc31cb6f   Jeff Layton   cifs: make cifs_s...
335
  	struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
a6827c184   Jeff Layton   cifs: add cifs_ca...
336

59ffd8414   Jeff Layton   cifs: add ignore_...
337
  	rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0);
a6827c184   Jeff Layton   cifs: add cifs_ca...
338
339
  	if (rc)
  		return rc;
e3f0dadb2   Jeff Layton   cifs: enable sign...
340
  	/* enable signing if server requires it */
96daf2b09   Steve French   [CIFS] Rename thr...
341
  	if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
fcc31cb6f   Jeff Layton   cifs: make cifs_s...
342
  		hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
e3f0dadb2   Jeff Layton   cifs: enable sign...
343

a6827c184   Jeff Layton   cifs: add cifs_ca...
344
  	mutex_lock(&server->srv_mutex);
fcc31cb6f   Jeff Layton   cifs: make cifs_s...
345
  	mid = AllocMidQEntry(hdr, server);
a6827c184   Jeff Layton   cifs: add cifs_ca...
346
347
  	if (mid == NULL) {
  		mutex_unlock(&server->srv_mutex);
0193e0722   Pavel Shilovsky   CIFS: Fix missing...
348
349
  		atomic_dec(&server->inFlight);
  		wake_up(&server->request_q);
a6827c184   Jeff Layton   cifs: add cifs_ca...
350
351
352
353
354
355
356
  		return -ENOMEM;
  	}
  
  	/* put it on the pending_mid_q */
  	spin_lock(&GlobalMid_Lock);
  	list_add_tail(&mid->qhead, &server->pending_mid_q);
  	spin_unlock(&GlobalMid_Lock);
fcc31cb6f   Jeff Layton   cifs: make cifs_s...
357
  	rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
a6827c184   Jeff Layton   cifs: add cifs_ca...
358
359
360
361
  	if (rc) {
  		mutex_unlock(&server->srv_mutex);
  		goto out_err;
  	}
44d22d846   Jeff Layton   cifs: add a callb...
362
  	mid->receive = receive;
a6827c184   Jeff Layton   cifs: add cifs_ca...
363
364
365
  	mid->callback = callback;
  	mid->callback_data = cbdata;
  	mid->midState = MID_REQUEST_SUBMITTED;
789e66612   Steve French   [CIFS] Cleanup us...
366
367
  
  	cifs_in_send_inc(server);
fcc31cb6f   Jeff Layton   cifs: make cifs_s...
368
  	rc = smb_sendv(server, iov, nvec);
789e66612   Steve French   [CIFS] Cleanup us...
369
370
  	cifs_in_send_dec(server);
  	cifs_save_when_sent(mid);
a6827c184   Jeff Layton   cifs: add cifs_ca...
371
  	mutex_unlock(&server->srv_mutex);
789e66612   Steve French   [CIFS] Cleanup us...
372

a6827c184   Jeff Layton   cifs: add cifs_ca...
373
374
375
376
377
378
379
380
381
382
383
384
  	if (rc)
  		goto out_err;
  
  	return rc;
  out_err:
  	delete_mid(mid);
  	atomic_dec(&server->inFlight);
  	wake_up(&server->request_q);
  	return rc;
  }
  
  /*
133672efb   Steve French   [CIFS] Fix buffer...
385
386
387
388
389
390
391
392
393
   *
   * 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
96daf2b09   Steve French   [CIFS] Rename thr...
394
  SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
133672efb   Steve French   [CIFS] Fix buffer...
395
396
397
398
399
400
401
  		struct smb_hdr *in_buf, int flags)
  {
  	int rc;
  	struct kvec iov[1];
  	int resp_buf_type;
  
  	iov[0].iov_base = (char *)in_buf;
be8e3b004   Steve French   consistently use ...
402
  	iov[0].iov_len = be32_to_cpu(in_buf->smb_buf_length) + 4;
133672efb   Steve French   [CIFS] Fix buffer...
403
404
  	flags |= CIFS_NO_RESP;
  	rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
405
  	cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
90c81e0b0   Steve French   [CIFS] clean up s...
406

133672efb   Steve French   [CIFS] Fix buffer...
407
408
  	return rc;
  }
053d50344   Jeff Layton   cifs: move mid re...
409
  static int
3c1105df6   Jeff Layton   cifs: don't call ...
410
  cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
053d50344   Jeff Layton   cifs: move mid re...
411
412
  {
  	int rc = 0;
74dd92a88   Jeff Layton   cifs: clean up sy...
413
414
  	cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command,
  		mid->mid, mid->midState);
053d50344   Jeff Layton   cifs: move mid re...
415

74dd92a88   Jeff Layton   cifs: clean up sy...
416
417
418
  	spin_lock(&GlobalMid_Lock);
  	switch (mid->midState) {
  	case MID_RESPONSE_RECEIVED:
053d50344   Jeff Layton   cifs: move mid re...
419
420
  		spin_unlock(&GlobalMid_Lock);
  		return rc;
74dd92a88   Jeff Layton   cifs: clean up sy...
421
422
423
  	case MID_RETRY_NEEDED:
  		rc = -EAGAIN;
  		break;
71823baff   Jeff Layton   cifs: don't alway...
424
425
426
  	case MID_RESPONSE_MALFORMED:
  		rc = -EIO;
  		break;
3c1105df6   Jeff Layton   cifs: don't call ...
427
428
429
  	case MID_SHUTDOWN:
  		rc = -EHOSTDOWN;
  		break;
74dd92a88   Jeff Layton   cifs: clean up sy...
430
  	default:
3c1105df6   Jeff Layton   cifs: don't call ...
431
  		list_del_init(&mid->qhead);
74dd92a88   Jeff Layton   cifs: clean up sy...
432
433
434
  		cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
  			mid->mid, mid->midState);
  		rc = -EIO;
053d50344   Jeff Layton   cifs: move mid re...
435
436
  	}
  	spin_unlock(&GlobalMid_Lock);
2b84a36c5   Jeff Layton   cifs: allow for d...
437
  	DeleteMidQEntry(mid);
053d50344   Jeff Layton   cifs: move mid re...
438
439
  	return rc;
  }
76dcc26f1   Jeff Layton   cifs: mangle exis...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
  /*
   * An NT cancel request header looks just like the original request except:
   *
   * The Command is SMB_COM_NT_CANCEL
   * The WordCount is zeroed out
   * The ByteCount is zeroed out
   *
   * This function mangles an existing request buffer into a
   * SMB_COM_NT_CANCEL request and then sends it.
   */
  static int
  send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
  		struct mid_q_entry *mid)
  {
  	int rc = 0;
  
  	/* -4 for RFC1001 length and +2 for BCC field */
be8e3b004   Steve French   consistently use ...
457
  	in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4  + 2);
76dcc26f1   Jeff Layton   cifs: mangle exis...
458
459
  	in_buf->Command = SMB_COM_NT_CANCEL;
  	in_buf->WordCount = 0;
820a803ff   Jeff Layton   cifs: keep BCC in...
460
  	put_bcc(0, in_buf);
76dcc26f1   Jeff Layton   cifs: mangle exis...
461
462
463
464
465
466
467
  
  	mutex_lock(&server->srv_mutex);
  	rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
  	if (rc) {
  		mutex_unlock(&server->srv_mutex);
  		return rc;
  	}
be8e3b004   Steve French   consistently use ...
468
  	rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
76dcc26f1   Jeff Layton   cifs: mangle exis...
469
470
471
472
473
474
475
  	mutex_unlock(&server->srv_mutex);
  
  	cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
  		in_buf->Mid, rc);
  
  	return rc;
  }
7ee1af765   Jeremy Allison   [CIFS]
476
  int
2c8f981d9   Jeff Layton   cifs: consolidate...
477
478
479
  cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
  		   bool log_error)
  {
826a95e4a   Jeff Layton   cifs: consolidate...
480
481
482
  	unsigned int len = be32_to_cpu(mid->resp_buf->smb_buf_length) + 4;
  
  	dump_smb(mid->resp_buf, min_t(u32, 92, len));
2c8f981d9   Jeff Layton   cifs: consolidate...
483
484
  
  	/* convert the length into a more usable form */
96daf2b09   Steve French   [CIFS] Rename thr...
485
  	if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
826a95e4a   Jeff Layton   cifs: consolidate...
486
487
488
489
  		struct kvec iov;
  
  		iov.iov_base = mid->resp_buf;
  		iov.iov_len = len;
2c8f981d9   Jeff Layton   cifs: consolidate...
490
  		/* FIXME: add code to kill session */
826a95e4a   Jeff Layton   cifs: consolidate...
491
  		if (cifs_verify_signature(&iov, 1, server,
2c8f981d9   Jeff Layton   cifs: consolidate...
492
493
494
495
496
497
498
499
500
  					  mid->sequence_number + 1) != 0)
  			cERROR(1, "Unexpected SMB signature");
  	}
  
  	/* BB special case reconnect tid and uid here? */
  	return map_smb_to_linux_error(mid->resp_buf, log_error);
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
501
  SendReceive2(const unsigned int xid, struct cifs_ses *ses,
79a58d1f6   Steve French   [CIFS] whitespace...
502
  	     struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
133672efb   Steve French   [CIFS] Fix buffer...
503
  	     const int flags)
7ee1af765   Jeremy Allison   [CIFS]
504
505
  {
  	int rc = 0;
133672efb   Steve French   [CIFS] Fix buffer...
506
  	int long_op;
7ee1af765   Jeremy Allison   [CIFS]
507
508
  	struct mid_q_entry *midQ;
  	struct smb_hdr *in_buf = iov[0].iov_base;
50c2f7538   Steve French   [CIFS] whitespace...
509

133672efb   Steve French   [CIFS] Fix buffer...
510
  	long_op = flags & CIFS_TIMEOUT_MASK;
7ee1af765   Jeremy Allison   [CIFS]
511
512
513
514
  	*pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
  
  	if ((ses == NULL) || (ses->server == NULL)) {
  		cifs_small_buf_release(in_buf);
b6b38f704   Joe Perches   [CIFS] Neaten cER...
515
  		cERROR(1, "Null session");
7ee1af765   Jeremy Allison   [CIFS]
516
517
  		return -EIO;
  	}
79a58d1f6   Steve French   [CIFS] whitespace...
518
  	if (ses->server->tcpStatus == CifsExiting) {
7ee1af765   Jeremy Allison   [CIFS]
519
520
521
  		cifs_small_buf_release(in_buf);
  		return -ENOENT;
  	}
79a58d1f6   Steve French   [CIFS] whitespace...
522
  	/* Ensure that we do not send more than 50 overlapping requests
7ee1af765   Jeremy Allison   [CIFS]
523
524
  	   to the same server. We may make this configurable later or
  	   use ses->maxReq */
c5797a945   Jeff Layton   cifs: make wait_f...
525
  	rc = wait_for_free_request(ses->server, long_op);
7ee1af765   Jeremy Allison   [CIFS]
526
527
528
529
  	if (rc) {
  		cifs_small_buf_release(in_buf);
  		return rc;
  	}
79a58d1f6   Steve French   [CIFS] whitespace...
530
  	/* make sure that we sign in the same order that we send on this socket
7ee1af765   Jeremy Allison   [CIFS]
531
532
  	   and avoid races inside tcp sendmsg code that could cause corruption
  	   of smb data */
72ca545b2   Jeff Layton   cifs: convert tcp...
533
  	mutex_lock(&ses->server->srv_mutex);
7ee1af765   Jeremy Allison   [CIFS]
534
535
536
  
  	rc = allocate_mid(ses, in_buf, &midQ);
  	if (rc) {
72ca545b2   Jeff Layton   cifs: convert tcp...
537
  		mutex_unlock(&ses->server->srv_mutex);
4b8f930ff   Steve French   [CIFS] Free small...
538
  		cifs_small_buf_release(in_buf);
7ee1af765   Jeremy Allison   [CIFS]
539
  		/* Update # of requests on wire to server */
79a58d1f6   Steve French   [CIFS] whitespace...
540
  		atomic_dec(&ses->server->inFlight);
7ee1af765   Jeremy Allison   [CIFS]
541
542
  		wake_up(&ses->server->request_q);
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
  	}
79a58d1f6   Steve French   [CIFS] whitespace...
544
  	rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
829049cbb   Volker Lendecke   Check the return ...
545
546
547
548
549
  	if (rc) {
  		mutex_unlock(&ses->server->srv_mutex);
  		cifs_small_buf_release(in_buf);
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
  
  	midQ->midState = MID_REQUEST_SUBMITTED;
789e66612   Steve French   [CIFS] Cleanup us...
552
  	cifs_in_send_inc(ses->server);
0496e02d8   Jeff Layton   cifs: turn smb_se...
553
  	rc = smb_sendv(ses->server, iov, n_vec);
789e66612   Steve French   [CIFS] Cleanup us...
554
555
  	cifs_in_send_dec(ses->server);
  	cifs_save_when_sent(midQ);
7ee1af765   Jeremy Allison   [CIFS]
556

72ca545b2   Jeff Layton   cifs: convert tcp...
557
  	mutex_unlock(&ses->server->srv_mutex);
7ee1af765   Jeremy Allison   [CIFS]
558

2db7c5815   Jeff Layton   cifs: send an NT_...
559
560
  	if (rc < 0) {
  		cifs_small_buf_release(in_buf);
7ee1af765   Jeremy Allison   [CIFS]
561
  		goto out;
2db7c5815   Jeff Layton   cifs: send an NT_...
562
  	}
4b8f930ff   Steve French   [CIFS] Free small...
563

2db7c5815   Jeff Layton   cifs: send an NT_...
564
565
  	if (long_op == CIFS_ASYNC_OP) {
  		cifs_small_buf_release(in_buf);
133672efb   Steve French   [CIFS] Fix buffer...
566
  		goto out;
2db7c5815   Jeff Layton   cifs: send an NT_...
567
  	}
d6e04ae64   Steve French   [CIFS] CIFS write...
568

0ade640e9   Jeff Layton   cifs: wait indefi...
569
  	rc = wait_for_response(ses->server, midQ);
1be912dde   Jeff Layton   cifs: handle canc...
570
  	if (rc != 0) {
2db7c5815   Jeff Layton   cifs: send an NT_...
571
  		send_nt_cancel(ses->server, in_buf, midQ);
1be912dde   Jeff Layton   cifs: handle canc...
572
573
574
575
  		spin_lock(&GlobalMid_Lock);
  		if (midQ->midState == MID_REQUEST_SUBMITTED) {
  			midQ->callback = DeleteMidQEntry;
  			spin_unlock(&GlobalMid_Lock);
2db7c5815   Jeff Layton   cifs: send an NT_...
576
  			cifs_small_buf_release(in_buf);
1be912dde   Jeff Layton   cifs: handle canc...
577
578
579
580
581
582
  			atomic_dec(&ses->server->inFlight);
  			wake_up(&ses->server->request_q);
  			return rc;
  		}
  		spin_unlock(&GlobalMid_Lock);
  	}
d6e04ae64   Steve French   [CIFS] CIFS write...
583

2db7c5815   Jeff Layton   cifs: send an NT_...
584
  	cifs_small_buf_release(in_buf);
3c1105df6   Jeff Layton   cifs: don't call ...
585
  	rc = cifs_sync_mid_result(midQ, ses->server);
053d50344   Jeff Layton   cifs: move mid re...
586
  	if (rc != 0) {
79a58d1f6   Steve French   [CIFS] whitespace...
587
  		atomic_dec(&ses->server->inFlight);
7ee1af765   Jeremy Allison   [CIFS]
588
  		wake_up(&ses->server->request_q);
d6e04ae64   Steve French   [CIFS] CIFS write...
589
590
  		return rc;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
591

2c8f981d9   Jeff Layton   cifs: consolidate...
592
  	if (!midQ->resp_buf || midQ->midState != MID_RESPONSE_RECEIVED) {
d6e04ae64   Steve French   [CIFS] CIFS write...
593
  		rc = -EIO;
2c8f981d9   Jeff Layton   cifs: consolidate...
594
  		cFYI(1, "Bad MID state?");
2b2bdfba7   Steve French   [CIFS] Streamline...
595
596
  		goto out;
  	}
2c8f981d9   Jeff Layton   cifs: consolidate...
597
598
599
600
601
602
  	iov[0].iov_base = (char *)midQ->resp_buf;
  	iov[0].iov_len = be32_to_cpu(midQ->resp_buf->smb_buf_length) + 4;
  	if (midQ->largeBuf)
  		*pRespBufType = CIFS_LARGE_BUFFER;
  	else
  		*pRespBufType = CIFS_SMALL_BUFFER;
2b2bdfba7   Steve French   [CIFS] Streamline...
603

2c8f981d9   Jeff Layton   cifs: consolidate...
604
  	rc = cifs_check_receive(midQ, ses->server, flags & CIFS_LOG_ERROR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605

2c8f981d9   Jeff Layton   cifs: consolidate...
606
607
608
  	/* mark it so buf will not be freed by delete_mid */
  	if ((flags & CIFS_NO_RESP) == 0)
  		midQ->resp_buf = NULL;
7ee1af765   Jeremy Allison   [CIFS]
609
  out:
ddc8cf8fc   Jeff Layton   cifs: move locked...
610
  	delete_mid(midQ);
79a58d1f6   Steve French   [CIFS] whitespace...
611
  	atomic_dec(&ses->server->inFlight);
7ee1af765   Jeremy Allison   [CIFS]
612
  	wake_up(&ses->server->request_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613

d6e04ae64   Steve French   [CIFS] CIFS write...
614
615
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
617
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
618
  SendReceive(const unsigned int xid, struct cifs_ses *ses,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
620
621
622
  	    struct smb_hdr *in_buf, struct smb_hdr *out_buf,
  	    int *pbytes_returned, const int long_op)
  {
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
624
625
  	struct mid_q_entry *midQ;
  
  	if (ses == NULL) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
626
  		cERROR(1, "Null smb session");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
628
  		return -EIO;
  	}
79a58d1f6   Steve French   [CIFS] whitespace...
629
  	if (ses->server == NULL) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
630
  		cERROR(1, "Null tcp session");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
632
  		return -EIO;
  	}
79a58d1f6   Steve French   [CIFS] whitespace...
633
  	if (ses->server->tcpStatus == CifsExiting)
31ca3bc3c   Steve French   [PATCH] cifs: Do ...
634
  		return -ENOENT;
79a58d1f6   Steve French   [CIFS] whitespace...
635
  	/* Ensure that we do not send more than 50 overlapping requests
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
637
  	   to the same server. We may make this configurable later or
  	   use ses->maxReq */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638

be8e3b004   Steve French   consistently use ...
639
640
  	if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
  			MAX_CIFS_HDR_SIZE - 4) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
641
  		cERROR(1, "Illegal length, greater than maximum frame, %d",
be8e3b004   Steve French   consistently use ...
642
  			   be32_to_cpu(in_buf->smb_buf_length));
6d9c6d543   Volker Lendecke   [CIFS] In SendRec...
643
644
  		return -EIO;
  	}
c5797a945   Jeff Layton   cifs: make wait_f...
645
  	rc = wait_for_free_request(ses->server, long_op);
7ee1af765   Jeremy Allison   [CIFS]
646
647
  	if (rc)
  		return rc;
79a58d1f6   Steve French   [CIFS] whitespace...
648
  	/* make sure that we sign in the same order that we send on this socket
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
650
  	   and avoid races inside tcp sendmsg code that could cause corruption
  	   of smb data */
72ca545b2   Jeff Layton   cifs: convert tcp...
651
  	mutex_lock(&ses->server->srv_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652

7ee1af765   Jeremy Allison   [CIFS]
653
654
  	rc = allocate_mid(ses, in_buf, &midQ);
  	if (rc) {
72ca545b2   Jeff Layton   cifs: convert tcp...
655
  		mutex_unlock(&ses->server->srv_mutex);
7ee1af765   Jeremy Allison   [CIFS]
656
  		/* Update # of requests on wire to server */
79a58d1f6   Steve French   [CIFS] whitespace...
657
  		atomic_dec(&ses->server->inFlight);
7ee1af765   Jeremy Allison   [CIFS]
658
659
  		wake_up(&ses->server->request_q);
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
  	}
ad009ac96   Steve French   [PATCH] cifs: Fix...
661
  	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cbb   Volker Lendecke   Check the return ...
662
663
664
665
  	if (rc) {
  		mutex_unlock(&ses->server->srv_mutex);
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
  
  	midQ->midState = MID_REQUEST_SUBMITTED;
789e66612   Steve French   [CIFS] Cleanup us...
668
669
  
  	cifs_in_send_inc(ses->server);
be8e3b004   Steve French   consistently use ...
670
  	rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
789e66612   Steve French   [CIFS] Cleanup us...
671
672
  	cifs_in_send_dec(ses->server);
  	cifs_save_when_sent(midQ);
72ca545b2   Jeff Layton   cifs: convert tcp...
673
  	mutex_unlock(&ses->server->srv_mutex);
7ee1af765   Jeremy Allison   [CIFS]
674

79a58d1f6   Steve French   [CIFS] whitespace...
675
  	if (rc < 0)
7ee1af765   Jeremy Allison   [CIFS]
676
  		goto out;
0ade640e9   Jeff Layton   cifs: wait indefi...
677
  	if (long_op == CIFS_ASYNC_OP)
7ee1af765   Jeremy Allison   [CIFS]
678
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679

0ade640e9   Jeff Layton   cifs: wait indefi...
680
  	rc = wait_for_response(ses->server, midQ);
1be912dde   Jeff Layton   cifs: handle canc...
681
  	if (rc != 0) {
2db7c5815   Jeff Layton   cifs: send an NT_...
682
  		send_nt_cancel(ses->server, in_buf, midQ);
1be912dde   Jeff Layton   cifs: handle canc...
683
684
685
686
687
688
689
690
691
692
693
  		spin_lock(&GlobalMid_Lock);
  		if (midQ->midState == MID_REQUEST_SUBMITTED) {
  			/* no longer considered to be "in-flight" */
  			midQ->callback = DeleteMidQEntry;
  			spin_unlock(&GlobalMid_Lock);
  			atomic_dec(&ses->server->inFlight);
  			wake_up(&ses->server->request_q);
  			return rc;
  		}
  		spin_unlock(&GlobalMid_Lock);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694

3c1105df6   Jeff Layton   cifs: don't call ...
695
  	rc = cifs_sync_mid_result(midQ, ses->server);
053d50344   Jeff Layton   cifs: move mid re...
696
  	if (rc != 0) {
79a58d1f6   Steve French   [CIFS] whitespace...
697
  		atomic_dec(&ses->server->inFlight);
7ee1af765   Jeremy Allison   [CIFS]
698
  		wake_up(&ses->server->request_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
700
  		return rc;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
701

2c8f981d9   Jeff Layton   cifs: consolidate...
702
703
  	if (!midQ->resp_buf || !out_buf ||
  	    midQ->midState != MID_RESPONSE_RECEIVED) {
2b2bdfba7   Steve French   [CIFS] Streamline...
704
  		rc = -EIO;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
705
  		cERROR(1, "Bad MID state?");
2c8f981d9   Jeff Layton   cifs: consolidate...
706
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
  	}
7ee1af765   Jeremy Allison   [CIFS]
708

2c8f981d9   Jeff Layton   cifs: consolidate...
709
710
711
  	*pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length);
  	memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
  	rc = cifs_check_receive(midQ, ses->server, 0);
7ee1af765   Jeremy Allison   [CIFS]
712
  out:
ddc8cf8fc   Jeff Layton   cifs: move locked...
713
  	delete_mid(midQ);
79a58d1f6   Steve French   [CIFS] whitespace...
714
  	atomic_dec(&ses->server->inFlight);
7ee1af765   Jeremy Allison   [CIFS]
715
  	wake_up(&ses->server->request_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716

7ee1af765   Jeremy Allison   [CIFS]
717
718
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719

7ee1af765   Jeremy Allison   [CIFS]
720
721
722
723
  /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
     blocking lock to return. */
  
  static int
96daf2b09   Steve French   [CIFS] Rename thr...
724
  send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
7ee1af765   Jeremy Allison   [CIFS]
725
726
727
728
  			struct smb_hdr *in_buf,
  			struct smb_hdr *out_buf)
  {
  	int bytes_returned;
96daf2b09   Steve French   [CIFS] Rename thr...
729
  	struct cifs_ses *ses = tcon->ses;
7ee1af765   Jeremy Allison   [CIFS]
730
731
732
733
734
735
736
737
738
739
740
741
  	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;
  	pSMB->hdr.Mid = GetNextMid(ses->server);
  
  	return SendReceive(xid, ses, in_buf, out_buf,
7749981ec   Jeff Layton   cifs: remove code...
742
  			&bytes_returned, 0);
7ee1af765   Jeremy Allison   [CIFS]
743
744
745
  }
  
  int
96daf2b09   Steve French   [CIFS] Rename thr...
746
  SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
7ee1af765   Jeremy Allison   [CIFS]
747
748
749
750
751
  	    struct smb_hdr *in_buf, struct smb_hdr *out_buf,
  	    int *pbytes_returned)
  {
  	int rc = 0;
  	int rstart = 0;
7ee1af765   Jeremy Allison   [CIFS]
752
  	struct mid_q_entry *midQ;
96daf2b09   Steve French   [CIFS] Rename thr...
753
  	struct cifs_ses *ses;
7ee1af765   Jeremy Allison   [CIFS]
754
755
  
  	if (tcon == NULL || tcon->ses == NULL) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
756
  		cERROR(1, "Null smb session");
7ee1af765   Jeremy Allison   [CIFS]
757
758
759
  		return -EIO;
  	}
  	ses = tcon->ses;
79a58d1f6   Steve French   [CIFS] whitespace...
760
  	if (ses->server == NULL) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
761
  		cERROR(1, "Null tcp session");
7ee1af765   Jeremy Allison   [CIFS]
762
763
  		return -EIO;
  	}
79a58d1f6   Steve French   [CIFS] whitespace...
764
  	if (ses->server->tcpStatus == CifsExiting)
7ee1af765   Jeremy Allison   [CIFS]
765
  		return -ENOENT;
79a58d1f6   Steve French   [CIFS] whitespace...
766
  	/* Ensure that we do not send more than 50 overlapping requests
7ee1af765   Jeremy Allison   [CIFS]
767
768
  	   to the same server. We may make this configurable later or
  	   use ses->maxReq */
be8e3b004   Steve French   consistently use ...
769
770
  	if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
  			MAX_CIFS_HDR_SIZE - 4) {
b6b38f704   Joe Perches   [CIFS] Neaten cER...
771
  		cERROR(1, "Illegal length, greater than maximum frame, %d",
be8e3b004   Steve French   consistently use ...
772
  			   be32_to_cpu(in_buf->smb_buf_length));
6d9c6d543   Volker Lendecke   [CIFS] In SendRec...
773
774
  		return -EIO;
  	}
c5797a945   Jeff Layton   cifs: make wait_f...
775
  	rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
7ee1af765   Jeremy Allison   [CIFS]
776
777
  	if (rc)
  		return rc;
79a58d1f6   Steve French   [CIFS] whitespace...
778
  	/* make sure that we sign in the same order that we send on this socket
7ee1af765   Jeremy Allison   [CIFS]
779
780
  	   and avoid races inside tcp sendmsg code that could cause corruption
  	   of smb data */
72ca545b2   Jeff Layton   cifs: convert tcp...
781
  	mutex_lock(&ses->server->srv_mutex);
7ee1af765   Jeremy Allison   [CIFS]
782
783
784
  
  	rc = allocate_mid(ses, in_buf, &midQ);
  	if (rc) {
72ca545b2   Jeff Layton   cifs: convert tcp...
785
  		mutex_unlock(&ses->server->srv_mutex);
7ee1af765   Jeremy Allison   [CIFS]
786
787
  		return rc;
  	}
7ee1af765   Jeremy Allison   [CIFS]
788
  	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cbb   Volker Lendecke   Check the return ...
789
  	if (rc) {
ddc8cf8fc   Jeff Layton   cifs: move locked...
790
  		delete_mid(midQ);
829049cbb   Volker Lendecke   Check the return ...
791
792
793
  		mutex_unlock(&ses->server->srv_mutex);
  		return rc;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794

7ee1af765   Jeremy Allison   [CIFS]
795
  	midQ->midState = MID_REQUEST_SUBMITTED;
789e66612   Steve French   [CIFS] Cleanup us...
796
  	cifs_in_send_inc(ses->server);
be8e3b004   Steve French   consistently use ...
797
  	rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
789e66612   Steve French   [CIFS] Cleanup us...
798
799
  	cifs_in_send_dec(ses->server);
  	cifs_save_when_sent(midQ);
72ca545b2   Jeff Layton   cifs: convert tcp...
800
  	mutex_unlock(&ses->server->srv_mutex);
7ee1af765   Jeremy Allison   [CIFS]
801

79a58d1f6   Steve French   [CIFS] whitespace...
802
  	if (rc < 0) {
ddc8cf8fc   Jeff Layton   cifs: move locked...
803
  		delete_mid(midQ);
7ee1af765   Jeremy Allison   [CIFS]
804
805
806
807
808
  		return rc;
  	}
  
  	/* Wait for a reply - allow signals to interrupt. */
  	rc = wait_event_interruptible(ses->server->response_q,
79a58d1f6   Steve French   [CIFS] whitespace...
809
  		(!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
7ee1af765   Jeremy Allison   [CIFS]
810
811
812
813
814
815
816
817
818
819
820
821
  		((ses->server->tcpStatus != CifsGood) &&
  		 (ses->server->tcpStatus != CifsNew)));
  
  	/* Were we interrupted by a signal ? */
  	if ((rc == -ERESTARTSYS) &&
  		(midQ->midState == MID_REQUEST_SUBMITTED) &&
  		((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. */
76dcc26f1   Jeff Layton   cifs: mangle exis...
822
  			rc = send_nt_cancel(ses->server, in_buf, midQ);
7ee1af765   Jeremy Allison   [CIFS]
823
  			if (rc) {
ddc8cf8fc   Jeff Layton   cifs: move locked...
824
  				delete_mid(midQ);
7ee1af765   Jeremy Allison   [CIFS]
825
826
827
828
829
830
831
832
833
834
835
  				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) {
ddc8cf8fc   Jeff Layton   cifs: move locked...
836
  				delete_mid(midQ);
7ee1af765   Jeremy Allison   [CIFS]
837
838
839
  				return rc;
  			}
  		}
1be912dde   Jeff Layton   cifs: handle canc...
840
841
  		rc = wait_for_response(ses->server, midQ);
  		if (rc) {
2db7c5815   Jeff Layton   cifs: send an NT_...
842
  			send_nt_cancel(ses->server, in_buf, midQ);
1be912dde   Jeff Layton   cifs: handle canc...
843
844
845
846
847
848
849
850
  			spin_lock(&GlobalMid_Lock);
  			if (midQ->midState == MID_REQUEST_SUBMITTED) {
  				/* no longer considered to be "in-flight" */
  				midQ->callback = DeleteMidQEntry;
  				spin_unlock(&GlobalMid_Lock);
  				return rc;
  			}
  			spin_unlock(&GlobalMid_Lock);
7ee1af765   Jeremy Allison   [CIFS]
851
  		}
1be912dde   Jeff Layton   cifs: handle canc...
852
853
854
  
  		/* We got the response - restart system call. */
  		rstart = 1;
7ee1af765   Jeremy Allison   [CIFS]
855
  	}
3c1105df6   Jeff Layton   cifs: don't call ...
856
  	rc = cifs_sync_mid_result(midQ, ses->server);
053d50344   Jeff Layton   cifs: move mid re...
857
  	if (rc != 0)
7ee1af765   Jeremy Allison   [CIFS]
858
  		return rc;
50c2f7538   Steve French   [CIFS] whitespace...
859

17c8bfed8   Volker Lendecke   Streamline SendRe...
860
  	/* rcvd frame is ok */
2c8f981d9   Jeff Layton   cifs: consolidate...
861
  	if (out_buf == NULL || midQ->midState != MID_RESPONSE_RECEIVED) {
698e96a82   Volker Lendecke   Streamline SendRe...
862
  		rc = -EIO;
b6b38f704   Joe Perches   [CIFS] Neaten cER...
863
  		cERROR(1, "Bad MID state?");
698e96a82   Volker Lendecke   Streamline SendRe...
864
865
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866

2c8f981d9   Jeff Layton   cifs: consolidate...
867
868
869
  	*pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length);
  	memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
  	rc = cifs_check_receive(midQ, ses->server, 0);
17c8bfed8   Volker Lendecke   Streamline SendRe...
870
  out:
ddc8cf8fc   Jeff Layton   cifs: move locked...
871
  	delete_mid(midQ);
7ee1af765   Jeremy Allison   [CIFS]
872
873
  	if (rstart && rc == -EACCES)
  		return -ERESTARTSYS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
875
  	return rc;
  }