Simplify allocate_mid() slightly: Remove some unnecessary "else" branches
[deliverable/linux.git] / fs / cifs / transport.c
CommitLineData
1da177e4
LT
1/*
2 * fs/cifs/transport.c
3 *
ad7a2926 4 * Copyright (C) International Business Machines Corp., 2002,2008
1da177e4 5 * Author(s): Steve French (sfrench@us.ibm.com)
14a441a2 6 * Jeremy Allison (jra@samba.org) 2006.
79a58d1f 7 *
1da177e4
LT
8 * This library is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published
10 * by the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16 * the GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, write to the Free Software
79a58d1f 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1da177e4
LT
21 */
22
23#include <linux/fs.h>
24#include <linux/list.h>
25#include <linux/wait.h>
26#include <linux/net.h>
27#include <linux/delay.h>
28#include <asm/uaccess.h>
29#include <asm/processor.h>
30#include <linux/mempool.h>
31#include "cifspdu.h"
32#include "cifsglob.h"
33#include "cifsproto.h"
34#include "cifs_debug.h"
50c2f753 35
1da177e4 36extern mempool_t *cifs_mid_poolp;
e18b890b 37extern struct kmem_cache *cifs_oplock_cachep;
1da177e4
LT
38
39static struct mid_q_entry *
24b9b06b 40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
1da177e4
LT
41{
42 struct mid_q_entry *temp;
43
24b9b06b 44 if (server == NULL) {
1da177e4
LT
45 cERROR(1, ("Null TCP session in AllocMidQEntry"));
46 return NULL;
47 }
50c2f753 48
232087cb 49 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
1da177e4
LT
50 if (temp == NULL)
51 return temp;
52 else {
26f57364 53 memset(temp, 0, sizeof(struct mid_q_entry));
1da177e4
LT
54 temp->mid = smb_buffer->Mid; /* always LE */
55 temp->pid = current->pid;
56 temp->command = smb_buffer->Command;
57 cFYI(1, ("For smb_command %d", temp->command));
1047abc1
SF
58 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
59 /* when mid allocated can be before when sent */
60 temp->when_alloc = jiffies;
1da177e4
LT
61 temp->tsk = current;
62 }
63
64 spin_lock(&GlobalMid_Lock);
24b9b06b 65 list_add_tail(&temp->qhead, &server->pending_mid_q);
1da177e4
LT
66 atomic_inc(&midCount);
67 temp->midState = MID_REQUEST_ALLOCATED;
68 spin_unlock(&GlobalMid_Lock);
69 return temp;
70}
71
72static void
73DeleteMidQEntry(struct mid_q_entry *midEntry)
74{
1047abc1
SF
75#ifdef CONFIG_CIFS_STATS2
76 unsigned long now;
77#endif
1da177e4
LT
78 spin_lock(&GlobalMid_Lock);
79 midEntry->midState = MID_FREE;
80 list_del(&midEntry->qhead);
81 atomic_dec(&midCount);
82 spin_unlock(&GlobalMid_Lock);
79a58d1f 83 if (midEntry->largeBuf)
b8643e1b
SF
84 cifs_buf_release(midEntry->resp_buf);
85 else
86 cifs_small_buf_release(midEntry->resp_buf);
1047abc1
SF
87#ifdef CONFIG_CIFS_STATS2
88 now = jiffies;
89 /* commands taking longer than one second are indications that
90 something is wrong, unless it is quite a slow link or server */
79a58d1f
SF
91 if ((now - midEntry->when_alloc) > HZ) {
92 if ((cifsFYI & CIFS_TIMER) &&
1047abc1
SF
93 (midEntry->command != SMB_COM_LOCKING_ANDX)) {
94 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
95 midEntry->command, midEntry->mid);
96 printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
97 now - midEntry->when_alloc,
98 now - midEntry->when_sent,
99 now - midEntry->when_received);
100 }
101 }
102#endif
1da177e4
LT
103 mempool_free(midEntry, cifs_mid_poolp);
104}
105
106struct oplock_q_entry *
79a58d1f 107AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
1da177e4
LT
108{
109 struct oplock_q_entry *temp;
79a58d1f 110 if ((pinode == NULL) || (tcon == NULL)) {
1da177e4
LT
111 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
112 return NULL;
113 }
114 temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
e94b1766 115 GFP_KERNEL);
1da177e4
LT
116 if (temp == NULL)
117 return temp;
118 else {
119 temp->pinode = pinode;
120 temp->tcon = tcon;
121 temp->netfid = fid;
122 spin_lock(&GlobalMid_Lock);
123 list_add_tail(&temp->qhead, &GlobalOplock_Q);
124 spin_unlock(&GlobalMid_Lock);
125 }
126 return temp;
127
128}
129
79a58d1f 130void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
1da177e4 131{
79a58d1f 132 spin_lock(&GlobalMid_Lock);
1da177e4
LT
133 /* should we check if list empty first? */
134 list_del(&oplockEntry->qhead);
135 spin_unlock(&GlobalMid_Lock);
136 kmem_cache_free(cifs_oplock_cachep, oplockEntry);
137}
138
5d941ca6
SF
139
140void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
141{
142 struct oplock_q_entry *temp;
143
144 if (tcon == NULL)
145 return;
146
147 spin_lock(&GlobalMid_Lock);
148 list_for_each_entry(temp, &GlobalOplock_Q, qhead) {
149 if ((temp->tcon) && (temp->tcon == tcon)) {
150 list_del(&temp->qhead);
151 kmem_cache_free(cifs_oplock_cachep, temp);
152 }
153 }
154 spin_unlock(&GlobalMid_Lock);
155}
156
1da177e4
LT
157int
158smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
edf1ae40 159 unsigned int smb_buf_length, struct sockaddr *sin, bool noblocksnd)
1da177e4
LT
160{
161 int rc = 0;
162 int i = 0;
163 struct msghdr smb_msg;
164 struct kvec iov;
165 unsigned len = smb_buf_length + 4;
166
79a58d1f 167 if (ssocket == NULL)
1da177e4
LT
168 return -ENOTSOCK; /* BB eventually add reconnect code here */
169 iov.iov_base = smb_buffer;
170 iov.iov_len = len;
171
172 smb_msg.msg_name = sin;
26f57364 173 smb_msg.msg_namelen = sizeof(struct sockaddr);
1da177e4
LT
174 smb_msg.msg_control = NULL;
175 smb_msg.msg_controllen = 0;
edf1ae40
SF
176 if (noblocksnd)
177 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
178 else
179 smb_msg.msg_flags = MSG_NOSIGNAL;
1da177e4
LT
180
181 /* smb header is converted in header_assemble. bcc and rest of SMB word
79a58d1f
SF
182 area, and byte area if necessary, is converted to littleendian in
183 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
1da177e4
LT
184 Flags2 is converted in SendReceive */
185
186 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
3e84469d 187 cFYI(1, ("Sending smb of length %d", smb_buf_length));
1da177e4
LT
188 dump_smb(smb_buffer, len);
189
190 while (len > 0) {
191 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
192 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
193 i++;
3e84469d 194 /* smaller timeout here than send2 since smaller size */
79a58d1f
SF
195 /* Although it may not be required, this also is smaller
196 oplock break time */
197 if (i > 12) {
1da177e4 198 cERROR(1,
68058e75 199 ("sends on sock %p stuck for 7 seconds",
1da177e4
LT
200 ssocket));
201 rc = -EAGAIN;
202 break;
203 }
68058e75 204 msleep(1 << i);
1da177e4
LT
205 continue;
206 }
79a58d1f 207 if (rc < 0)
1da177e4 208 break;
5e1253b5
SF
209 else
210 i = 0; /* reset i after each successful send */
1da177e4
LT
211 iov.iov_base += rc;
212 iov.iov_len -= rc;
213 len -= rc;
214 }
215
216 if (rc < 0) {
79a58d1f 217 cERROR(1, ("Error %d sending data on socket to server", rc));
1da177e4
LT
218 } else {
219 rc = 0;
220 }
221
7ee1af76
JA
222 /* Don't want to modify the buffer as a
223 side effect of this call. */
224 smb_buffer->smb_buf_length = smb_buf_length;
225
1da177e4
LT
226 return rc;
227}
228
d6e04ae6 229static int
edf1ae40
SF
230smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
231 struct sockaddr *sin, bool noblocksnd)
1da177e4
LT
232{
233 int rc = 0;
234 int i = 0;
235 struct msghdr smb_msg;
3e84469d
SF
236 struct smb_hdr *smb_buffer = iov[0].iov_base;
237 unsigned int len = iov[0].iov_len;
238 unsigned int total_len;
239 int first_vec = 0;
7ee1af76 240 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
edf1ae40 241 struct socket *ssocket = server->ssocket;
50c2f753 242
79a58d1f 243 if (ssocket == NULL)
1da177e4 244 return -ENOTSOCK; /* BB eventually add reconnect code here */
3e84469d 245
1da177e4 246 smb_msg.msg_name = sin;
26f57364 247 smb_msg.msg_namelen = sizeof(struct sockaddr);
1da177e4
LT
248 smb_msg.msg_control = NULL;
249 smb_msg.msg_controllen = 0;
edf1ae40
SF
250 if (noblocksnd)
251 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
252 else
253 smb_msg.msg_flags = MSG_NOSIGNAL;
1da177e4
LT
254
255 /* smb header is converted in header_assemble. bcc and rest of SMB word
79a58d1f
SF
256 area, and byte area if necessary, is converted to littleendian in
257 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
1da177e4
LT
258 Flags2 is converted in SendReceive */
259
3e84469d
SF
260
261 total_len = 0;
262 for (i = 0; i < n_vec; i++)
263 total_len += iov[i].iov_len;
264
1da177e4 265 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
3e84469d 266 cFYI(1, ("Sending smb: total_len %d", total_len));
1da177e4
LT
267 dump_smb(smb_buffer, len);
268
17680356 269 i = 0;
3e84469d
SF
270 while (total_len) {
271 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
272 n_vec - first_vec, total_len);
1da177e4
LT
273 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
274 i++;
79a58d1f 275 if (i >= 14) {
1da177e4 276 cERROR(1,
68058e75 277 ("sends on sock %p stuck for 15 seconds",
1da177e4
LT
278 ssocket));
279 rc = -EAGAIN;
280 break;
281 }
68058e75 282 msleep(1 << i);
1da177e4
LT
283 continue;
284 }
79a58d1f 285 if (rc < 0)
1da177e4 286 break;
3e84469d 287
61de800d
SF
288 if (rc == total_len) {
289 total_len = 0;
290 break;
291 } else if (rc > total_len) {
292 cERROR(1, ("sent %d requested %d", rc, total_len));
3e84469d
SF
293 break;
294 }
79a58d1f 295 if (rc == 0) {
3e84469d
SF
296 /* should never happen, letting socket clear before
297 retrying is our only obvious option here */
79a58d1f 298 cERROR(1, ("tcp sent no data"));
3e84469d
SF
299 msleep(500);
300 continue;
d6e04ae6 301 }
3e84469d 302 total_len -= rc;
68058e75 303 /* the line below resets i */
3e84469d
SF
304 for (i = first_vec; i < n_vec; i++) {
305 if (iov[i].iov_len) {
306 if (rc > iov[i].iov_len) {
307 rc -= iov[i].iov_len;
308 iov[i].iov_len = 0;
309 } else {
310 iov[i].iov_base += rc;
311 iov[i].iov_len -= rc;
312 first_vec = i;
313 break;
314 }
315 }
d6e04ae6 316 }
5e1253b5 317 i = 0; /* in case we get ENOSPC on the next send */
1da177e4
LT
318 }
319
edf1ae40
SF
320 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
321 cFYI(1, ("partial send (%d remaining), terminating session",
322 total_len));
323 /* If we have only sent part of an SMB then the next SMB
324 could be taken as the remainder of this one. We need
325 to kill the socket so the server throws away the partial
326 SMB */
327 server->tcpStatus = CifsNeedReconnect;
328 }
329
1da177e4 330 if (rc < 0) {
79a58d1f 331 cERROR(1, ("Error %d sending data on socket to server", rc));
3e84469d 332 } else
1da177e4 333 rc = 0;
1da177e4 334
7ee1af76
JA
335 /* Don't want to modify the buffer as a
336 side effect of this call. */
337 smb_buffer->smb_buf_length = smb_buf_length;
338
1da177e4
LT
339 return rc;
340}
341
7ee1af76 342static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
1da177e4 343{
133672ef 344 if (long_op == CIFS_ASYNC_OP) {
1da177e4
LT
345 /* oplock breaks must not be held up */
346 atomic_inc(&ses->server->inFlight);
347 } else {
79a58d1f
SF
348 spin_lock(&GlobalMid_Lock);
349 while (1) {
350 if (atomic_read(&ses->server->inFlight) >=
d6e04ae6 351 cifs_max_pending){
1da177e4 352 spin_unlock(&GlobalMid_Lock);
131afd0b
SF
353#ifdef CONFIG_CIFS_STATS2
354 atomic_inc(&ses->server->num_waiters);
355#endif
1da177e4
LT
356 wait_event(ses->server->request_q,
357 atomic_read(&ses->server->inFlight)
358 < cifs_max_pending);
131afd0b
SF
359#ifdef CONFIG_CIFS_STATS2
360 atomic_dec(&ses->server->num_waiters);
361#endif
1da177e4
LT
362 spin_lock(&GlobalMid_Lock);
363 } else {
79a58d1f 364 if (ses->server->tcpStatus == CifsExiting) {
1da177e4
LT
365 spin_unlock(&GlobalMid_Lock);
366 return -ENOENT;
367 }
368
79a58d1f
SF
369 /* can not count locking commands against total
370 as they are allowed to block on server */
50c2f753 371
1da177e4 372 /* update # of requests on the wire to server */
133672ef 373 if (long_op != CIFS_BLOCKING_OP)
1da177e4 374 atomic_inc(&ses->server->inFlight);
1da177e4
LT
375 spin_unlock(&GlobalMid_Lock);
376 break;
377 }
378 }
379 }
7ee1af76
JA
380 return 0;
381}
1da177e4 382
7ee1af76
JA
383static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
384 struct mid_q_entry **ppmidQ)
385{
1da177e4 386 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76 387 return -ENOENT;
8fbbd365
VL
388 }
389
390 if (ses->server->tcpStatus == CifsNeedReconnect) {
79a58d1f 391 cFYI(1, ("tcp session dead - return to caller to retry"));
7ee1af76 392 return -EAGAIN;
8fbbd365
VL
393 }
394
395 if (ses->status != CifsGood) {
1da177e4 396 /* check if SMB session is bad because we are setting it up */
79a58d1f 397 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
ad7a2926 398 (in_buf->Command != SMB_COM_NEGOTIATE))
7ee1af76 399 return -EAGAIN;
ad7a2926 400 /* else ok - we are setting up session */
1da177e4 401 }
24b9b06b 402 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
26f57364 403 if (*ppmidQ == NULL)
7ee1af76 404 return -ENOMEM;
7ee1af76
JA
405 return 0;
406}
407
79a58d1f 408static int wait_for_response(struct cifsSesInfo *ses,
7ee1af76
JA
409 struct mid_q_entry *midQ,
410 unsigned long timeout,
411 unsigned long time_to_wait)
412{
413 unsigned long curr_timeout;
414
415 for (;;) {
416 curr_timeout = timeout + jiffies;
85705524
JL
417 wait_event_timeout(ses->server->response_q,
418 midQ->midState != MID_REQUEST_SUBMITTED, timeout);
7ee1af76
JA
419
420 if (time_after(jiffies, curr_timeout) &&
421 (midQ->midState == MID_REQUEST_SUBMITTED) &&
422 ((ses->server->tcpStatus == CifsGood) ||
423 (ses->server->tcpStatus == CifsNew))) {
424
425 unsigned long lrt;
426
427 /* We timed out. Is the server still
428 sending replies ? */
429 spin_lock(&GlobalMid_Lock);
430 lrt = ses->server->lstrp;
431 spin_unlock(&GlobalMid_Lock);
432
433 /* Calculate time_to_wait past last receive time.
79a58d1f 434 Although we prefer not to time out if the
7ee1af76 435 server is still responding - we will time
79a58d1f 436 out if the server takes more than 15 (or 45
7ee1af76 437 or 180) seconds to respond to this request
79a58d1f 438 and has not responded to any request from
7ee1af76
JA
439 other threads on the client within 10 seconds */
440 lrt += time_to_wait;
441 if (time_after(jiffies, lrt)) {
442 /* No replies for time_to_wait. */
79a58d1f 443 cERROR(1, ("server not responding"));
7ee1af76
JA
444 return -1;
445 }
446 } else {
447 return 0;
448 }
449 }
450}
451
133672ef
SF
452
453/*
454 *
455 * Send an SMB Request. No response info (other than return code)
456 * needs to be parsed.
457 *
458 * flags indicate the type of request buffer and how long to wait
459 * and whether to log NT STATUS code (error) before mapping it to POSIX error
460 *
461 */
462int
463SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
464 struct smb_hdr *in_buf, int flags)
465{
466 int rc;
467 struct kvec iov[1];
468 int resp_buf_type;
469
470 iov[0].iov_base = (char *)in_buf;
471 iov[0].iov_len = in_buf->smb_buf_length + 4;
472 flags |= CIFS_NO_RESP;
473 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
90c81e0b
SF
474 cFYI(DBG2, ("SendRcvNoRsp flags %d rc %d", flags, rc));
475
133672ef
SF
476 return rc;
477}
478
7ee1af76 479int
79a58d1f
SF
480SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
481 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
133672ef 482 const int flags)
7ee1af76
JA
483{
484 int rc = 0;
133672ef 485 int long_op;
7ee1af76
JA
486 unsigned int receive_len;
487 unsigned long timeout;
488 struct mid_q_entry *midQ;
489 struct smb_hdr *in_buf = iov[0].iov_base;
50c2f753 490
133672ef
SF
491 long_op = flags & CIFS_TIMEOUT_MASK;
492
7ee1af76
JA
493 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
494
495 if ((ses == NULL) || (ses->server == NULL)) {
496 cifs_small_buf_release(in_buf);
79a58d1f 497 cERROR(1, ("Null session"));
7ee1af76
JA
498 return -EIO;
499 }
500
79a58d1f 501 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76
JA
502 cifs_small_buf_release(in_buf);
503 return -ENOENT;
504 }
505
79a58d1f 506 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
507 to the same server. We may make this configurable later or
508 use ses->maxReq */
509
510 rc = wait_for_free_request(ses, long_op);
511 if (rc) {
512 cifs_small_buf_release(in_buf);
513 return rc;
514 }
515
79a58d1f 516 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
517 and avoid races inside tcp sendmsg code that could cause corruption
518 of smb data */
519
72ca545b 520 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
521
522 rc = allocate_mid(ses, in_buf, &midQ);
523 if (rc) {
72ca545b 524 mutex_unlock(&ses->server->srv_mutex);
4b8f930f 525 cifs_small_buf_release(in_buf);
7ee1af76 526 /* Update # of requests on wire to server */
79a58d1f 527 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
528 wake_up(&ses->server->request_q);
529 return rc;
1da177e4 530 }
79a58d1f 531 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
1da177e4
LT
532
533 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
534#ifdef CONFIG_CIFS_STATS2
535 atomic_inc(&ses->server->inSend);
536#endif
edf1ae40
SF
537 rc = smb_send2(ses->server, iov, n_vec,
538 (struct sockaddr *) &(ses->server->addr.sockAddr),
539 ses->server->noblocksnd);
131afd0b
SF
540#ifdef CONFIG_CIFS_STATS2
541 atomic_dec(&ses->server->inSend);
1047abc1 542 midQ->when_sent = jiffies;
131afd0b 543#endif
7ee1af76 544
72ca545b 545 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
546 cifs_small_buf_release(in_buf);
547
79a58d1f 548 if (rc < 0)
7ee1af76 549 goto out;
4b8f930f 550
133672ef
SF
551 if (long_op == CIFS_STD_OP)
552 timeout = 15 * HZ;
553 else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
37c0eb46 554 timeout = 180 * HZ;
133672ef 555 else if (long_op == CIFS_LONG_OP)
79a58d1f 556 timeout = 45 * HZ; /* should be greater than
d6e04ae6 557 servers oplock break timeout (about 43 seconds) */
133672ef
SF
558 else if (long_op == CIFS_ASYNC_OP)
559 goto out;
560 else if (long_op == CIFS_BLOCKING_OP)
561 timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
562 else {
563 cERROR(1, ("unknown timeout flag %d", long_op));
564 rc = -EIO;
565 goto out;
566 }
7ee1af76 567
79a58d1f 568 /* wait for 15 seconds or until woken up due to response arriving or
d6e04ae6
SF
569 due to last connection to this server being unmounted */
570 if (signal_pending(current)) {
571 /* if signal pending do not hold up user for full smb timeout
8a236264 572 but we still give response a chance to complete */
d6e04ae6 573 timeout = 2 * HZ;
79a58d1f 574 }
d6e04ae6
SF
575
576 /* No user interrupts in wait - wreaks havoc with performance */
7ee1af76 577 wait_for_response(ses, midQ, timeout, 10 * HZ);
d6e04ae6
SF
578
579 spin_lock(&GlobalMid_Lock);
580 if (midQ->resp_buf) {
581 spin_unlock(&GlobalMid_Lock);
70ca734a 582 receive_len = midQ->resp_buf->smb_buf_length;
d6e04ae6 583 } else {
79a58d1f 584 cERROR(1, ("No response to cmd %d mid %d",
37c0eb46 585 midQ->command, midQ->mid));
79a58d1f
SF
586 if (midQ->midState == MID_REQUEST_SUBMITTED) {
587 if (ses->server->tcpStatus == CifsExiting)
d6e04ae6
SF
588 rc = -EHOSTDOWN;
589 else {
590 ses->server->tcpStatus = CifsNeedReconnect;
591 midQ->midState = MID_RETRY_NEEDED;
592 }
593 }
594
595 if (rc != -EHOSTDOWN) {
79a58d1f 596 if (midQ->midState == MID_RETRY_NEEDED) {
d6e04ae6 597 rc = -EAGAIN;
79a58d1f 598 cFYI(1, ("marking request for retry"));
d6e04ae6
SF
599 } else {
600 rc = -EIO;
601 }
602 }
603 spin_unlock(&GlobalMid_Lock);
604 DeleteMidQEntry(midQ);
7ee1af76 605 /* Update # of requests on wire to server */
79a58d1f 606 atomic_dec(&ses->server->inFlight);
7ee1af76 607 wake_up(&ses->server->request_q);
d6e04ae6
SF
608 return rc;
609 }
50c2f753 610
d6e04ae6
SF
611 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
612 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
613 receive_len, xid));
614 rc = -EIO;
615 } else { /* rcvd frame is ok */
79a58d1f 616 if (midQ->resp_buf &&
d6e04ae6 617 (midQ->midState == MID_RESPONSE_RECEIVED)) {
84afc29b 618
ec637e3f 619 iov[0].iov_base = (char *)midQ->resp_buf;
79a58d1f 620 if (midQ->largeBuf)
ec637e3f
SF
621 *pRespBufType = CIFS_LARGE_BUFFER;
622 else
623 *pRespBufType = CIFS_SMALL_BUFFER;
624 iov[0].iov_len = receive_len + 4;
d6e04ae6 625
ec637e3f 626 dump_smb(midQ->resp_buf, 80);
d6e04ae6 627 /* convert the length into a more usable form */
79a58d1f 628 if ((receive_len > 24) &&
d6e04ae6
SF
629 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
630 SECMODE_SIGN_ENABLED))) {
ec637e3f 631 rc = cifs_verify_signature(midQ->resp_buf,
b609f06a 632 &ses->server->mac_signing_key,
d6e04ae6 633 midQ->sequence_number+1);
79a58d1f
SF
634 if (rc) {
635 cERROR(1, ("Unexpected SMB signature"));
d6e04ae6
SF
636 /* BB FIXME add code to kill session */
637 }
638 }
639
d6e04ae6 640 /* BB special case reconnect tid and uid here? */
133672ef
SF
641 rc = map_smb_to_linux_error(midQ->resp_buf,
642 flags & CIFS_LOG_ERROR);
d6e04ae6
SF
643
644 /* convert ByteCount if necessary */
26f57364
SF
645 if (receive_len >= sizeof(struct smb_hdr) - 4
646 /* do not count RFC1001 header */ +
ec637e3f 647 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
79a58d1f 648 BCC(midQ->resp_buf) =
ec637e3f 649 le16_to_cpu(BCC_LE(midQ->resp_buf));
133672ef
SF
650 if ((flags & CIFS_NO_RESP) == 0)
651 midQ->resp_buf = NULL; /* mark it so buf will
652 not be freed by
653 DeleteMidQEntry */
d6e04ae6
SF
654 } else {
655 rc = -EIO;
79a58d1f 656 cFYI(1, ("Bad MID state?"));
d6e04ae6
SF
657 }
658 }
1da177e4 659
7ee1af76 660out:
7ee1af76 661 DeleteMidQEntry(midQ);
79a58d1f 662 atomic_dec(&ses->server->inFlight);
7ee1af76 663 wake_up(&ses->server->request_q);
1da177e4 664
d6e04ae6
SF
665 return rc;
666}
1da177e4
LT
667
668int
669SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
670 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
671 int *pbytes_returned, const int long_op)
672{
673 int rc = 0;
674 unsigned int receive_len;
675 unsigned long timeout;
676 struct mid_q_entry *midQ;
677
678 if (ses == NULL) {
79a58d1f 679 cERROR(1, ("Null smb session"));
1da177e4
LT
680 return -EIO;
681 }
79a58d1f
SF
682 if (ses->server == NULL) {
683 cERROR(1, ("Null tcp session"));
1da177e4
LT
684 return -EIO;
685 }
686
79a58d1f 687 if (ses->server->tcpStatus == CifsExiting)
31ca3bc3
SF
688 return -ENOENT;
689
79a58d1f 690 /* Ensure that we do not send more than 50 overlapping requests
1da177e4
LT
691 to the same server. We may make this configurable later or
692 use ses->maxReq */
1da177e4 693
6d9c6d54
VL
694 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
695 cERROR(1, ("Illegal length, greater than maximum frame, %d",
696 in_buf->smb_buf_length));
697 return -EIO;
698 }
699
7ee1af76
JA
700 rc = wait_for_free_request(ses, long_op);
701 if (rc)
702 return rc;
703
79a58d1f 704 /* make sure that we sign in the same order that we send on this socket
1da177e4
LT
705 and avoid races inside tcp sendmsg code that could cause corruption
706 of smb data */
707
72ca545b 708 mutex_lock(&ses->server->srv_mutex);
1da177e4 709
7ee1af76
JA
710 rc = allocate_mid(ses, in_buf, &midQ);
711 if (rc) {
72ca545b 712 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 713 /* Update # of requests on wire to server */
79a58d1f 714 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
715 wake_up(&ses->server->request_q);
716 return rc;
1da177e4
LT
717 }
718
ad009ac9 719 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
1da177e4
LT
720
721 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
722#ifdef CONFIG_CIFS_STATS2
723 atomic_inc(&ses->server->inSend);
724#endif
1da177e4 725 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
edf1ae40
SF
726 (struct sockaddr *) &(ses->server->addr.sockAddr),
727 ses->server->noblocksnd);
131afd0b
SF
728#ifdef CONFIG_CIFS_STATS2
729 atomic_dec(&ses->server->inSend);
1047abc1 730 midQ->when_sent = jiffies;
131afd0b 731#endif
72ca545b 732 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 733
79a58d1f 734 if (rc < 0)
7ee1af76
JA
735 goto out;
736
133672ef
SF
737 if (long_op == CIFS_STD_OP)
738 timeout = 15 * HZ;
739 /* wait for 15 seconds or until woken up due to response arriving or
740 due to last connection to this server being unmounted */
741 else if (long_op == CIFS_ASYNC_OP)
7ee1af76 742 goto out;
133672ef 743 else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
37c0eb46 744 timeout = 180 * HZ;
133672ef 745 else if (long_op == CIFS_LONG_OP)
79a58d1f 746 timeout = 45 * HZ; /* should be greater than
1da177e4 747 servers oplock break timeout (about 43 seconds) */
133672ef
SF
748 else if (long_op == CIFS_BLOCKING_OP)
749 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
750 else {
751 cERROR(1, ("unknown timeout flag %d", long_op));
752 rc = -EIO;
753 goto out;
754 }
755
1da177e4
LT
756 if (signal_pending(current)) {
757 /* if signal pending do not hold up user for full smb timeout
8a236264 758 but we still give response a chance to complete */
1da177e4 759 timeout = 2 * HZ;
79a58d1f 760 }
1da177e4
LT
761
762 /* No user interrupts in wait - wreaks havoc with performance */
7ee1af76 763 wait_for_response(ses, midQ, timeout, 10 * HZ);
1da177e4
LT
764
765 spin_lock(&GlobalMid_Lock);
766 if (midQ->resp_buf) {
767 spin_unlock(&GlobalMid_Lock);
70ca734a 768 receive_len = midQ->resp_buf->smb_buf_length;
1da177e4 769 } else {
79a58d1f 770 cERROR(1, ("No response for cmd %d mid %d",
37c0eb46 771 midQ->command, midQ->mid));
79a58d1f
SF
772 if (midQ->midState == MID_REQUEST_SUBMITTED) {
773 if (ses->server->tcpStatus == CifsExiting)
1da177e4
LT
774 rc = -EHOSTDOWN;
775 else {
776 ses->server->tcpStatus = CifsNeedReconnect;
777 midQ->midState = MID_RETRY_NEEDED;
778 }
779 }
780
781 if (rc != -EHOSTDOWN) {
79a58d1f 782 if (midQ->midState == MID_RETRY_NEEDED) {
1da177e4 783 rc = -EAGAIN;
79a58d1f 784 cFYI(1, ("marking request for retry"));
1da177e4
LT
785 } else {
786 rc = -EIO;
787 }
788 }
789 spin_unlock(&GlobalMid_Lock);
790 DeleteMidQEntry(midQ);
7ee1af76 791 /* Update # of requests on wire to server */
79a58d1f 792 atomic_dec(&ses->server->inFlight);
7ee1af76 793 wake_up(&ses->server->request_q);
1da177e4
LT
794 return rc;
795 }
50c2f753 796
1da177e4 797 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
ad009ac9 798 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1da177e4
LT
799 receive_len, xid));
800 rc = -EIO;
801 } else { /* rcvd frame is ok */
802
803 if (midQ->resp_buf && out_buf
804 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
805 out_buf->smb_buf_length = receive_len;
806 memcpy((char *)out_buf + 4,
807 (char *)midQ->resp_buf + 4,
808 receive_len);
809
810 dump_smb(out_buf, 92);
811 /* convert the length into a more usable form */
79a58d1f 812 if ((receive_len > 24) &&
ad009ac9
SF
813 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
814 SECMODE_SIGN_ENABLED))) {
815 rc = cifs_verify_signature(out_buf,
b609f06a 816 &ses->server->mac_signing_key,
ad009ac9 817 midQ->sequence_number+1);
79a58d1f
SF
818 if (rc) {
819 cERROR(1, ("Unexpected SMB signature"));
275cde1a 820 /* BB FIXME add code to kill session */
ad009ac9 821 }
1da177e4
LT
822 }
823
824 *pbytes_returned = out_buf->smb_buf_length;
825
ad009ac9 826 /* BB special case reconnect tid and uid here? */
a761ac57 827 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1da177e4
LT
828
829 /* convert ByteCount if necessary */
26f57364
SF
830 if (receive_len >= sizeof(struct smb_hdr) - 4
831 /* do not count RFC1001 header */ +
1da177e4 832 (2 * out_buf->WordCount) + 2 /* bcc */ )
0f2b27c4 833 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1da177e4
LT
834 } else {
835 rc = -EIO;
79a58d1f 836 cERROR(1, ("Bad MID state?"));
1da177e4
LT
837 }
838 }
7ee1af76
JA
839
840out:
1da177e4 841 DeleteMidQEntry(midQ);
79a58d1f 842 atomic_dec(&ses->server->inFlight);
7ee1af76 843 wake_up(&ses->server->request_q);
1da177e4 844
7ee1af76
JA
845 return rc;
846}
1da177e4 847
7ee1af76
JA
848/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
849
850static int
851send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
852 struct mid_q_entry *midQ)
853{
854 int rc = 0;
855 struct cifsSesInfo *ses = tcon->ses;
856 __u16 mid = in_buf->Mid;
857
858 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
859 in_buf->Mid = mid;
72ca545b 860 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
861 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
862 if (rc) {
72ca545b 863 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
864 return rc;
865 }
866 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
edf1ae40
SF
867 (struct sockaddr *) &(ses->server->addr.sockAddr),
868 ses->server->noblocksnd);
72ca545b 869 mutex_unlock(&ses->server->srv_mutex);
1da177e4 870 return rc;
7ee1af76
JA
871}
872
873/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
874 blocking lock to return. */
875
876static int
877send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
878 struct smb_hdr *in_buf,
879 struct smb_hdr *out_buf)
880{
881 int bytes_returned;
882 struct cifsSesInfo *ses = tcon->ses;
883 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
884
885 /* We just modify the current in_buf to change
886 the type of lock from LOCKING_ANDX_SHARED_LOCK
887 or LOCKING_ANDX_EXCLUSIVE_LOCK to
888 LOCKING_ANDX_CANCEL_LOCK. */
889
890 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
891 pSMB->Timeout = 0;
892 pSMB->hdr.Mid = GetNextMid(ses->server);
893
894 return SendReceive(xid, ses, in_buf, out_buf,
133672ef 895 &bytes_returned, CIFS_STD_OP);
7ee1af76
JA
896}
897
898int
899SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
900 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
901 int *pbytes_returned)
902{
903 int rc = 0;
904 int rstart = 0;
905 unsigned int receive_len;
906 struct mid_q_entry *midQ;
907 struct cifsSesInfo *ses;
908
909 if (tcon == NULL || tcon->ses == NULL) {
79a58d1f 910 cERROR(1, ("Null smb session"));
7ee1af76
JA
911 return -EIO;
912 }
913 ses = tcon->ses;
914
79a58d1f
SF
915 if (ses->server == NULL) {
916 cERROR(1, ("Null tcp session"));
7ee1af76
JA
917 return -EIO;
918 }
919
79a58d1f 920 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
921 return -ENOENT;
922
79a58d1f 923 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
924 to the same server. We may make this configurable later or
925 use ses->maxReq */
926
6d9c6d54
VL
927 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
928 cERROR(1, ("Illegal length, greater than maximum frame, %d",
929 in_buf->smb_buf_length));
930 return -EIO;
931 }
932
133672ef 933 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
7ee1af76
JA
934 if (rc)
935 return rc;
936
79a58d1f 937 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
938 and avoid races inside tcp sendmsg code that could cause corruption
939 of smb data */
940
72ca545b 941 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
942
943 rc = allocate_mid(ses, in_buf, &midQ);
944 if (rc) {
72ca545b 945 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
946 return rc;
947 }
948
7ee1af76 949 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
1da177e4 950
7ee1af76
JA
951 midQ->midState = MID_REQUEST_SUBMITTED;
952#ifdef CONFIG_CIFS_STATS2
953 atomic_inc(&ses->server->inSend);
954#endif
955 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
edf1ae40
SF
956 (struct sockaddr *) &(ses->server->addr.sockAddr),
957 ses->server->noblocksnd);
7ee1af76
JA
958#ifdef CONFIG_CIFS_STATS2
959 atomic_dec(&ses->server->inSend);
960 midQ->when_sent = jiffies;
961#endif
72ca545b 962 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 963
79a58d1f 964 if (rc < 0) {
7ee1af76
JA
965 DeleteMidQEntry(midQ);
966 return rc;
967 }
968
969 /* Wait for a reply - allow signals to interrupt. */
970 rc = wait_event_interruptible(ses->server->response_q,
79a58d1f 971 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
7ee1af76
JA
972 ((ses->server->tcpStatus != CifsGood) &&
973 (ses->server->tcpStatus != CifsNew)));
974
975 /* Were we interrupted by a signal ? */
976 if ((rc == -ERESTARTSYS) &&
977 (midQ->midState == MID_REQUEST_SUBMITTED) &&
978 ((ses->server->tcpStatus == CifsGood) ||
979 (ses->server->tcpStatus == CifsNew))) {
980
981 if (in_buf->Command == SMB_COM_TRANSACTION2) {
982 /* POSIX lock. We send a NT_CANCEL SMB to cause the
983 blocking lock to return. */
984
985 rc = send_nt_cancel(tcon, in_buf, midQ);
986 if (rc) {
987 DeleteMidQEntry(midQ);
988 return rc;
989 }
990 } else {
991 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
992 to cause the blocking lock to return. */
993
994 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
995
996 /* If we get -ENOLCK back the lock may have
997 already been removed. Don't exit in this case. */
998 if (rc && rc != -ENOLCK) {
999 DeleteMidQEntry(midQ);
1000 return rc;
1001 }
1002 }
1003
1004 /* Wait 5 seconds for the response. */
79a58d1f 1005 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
7ee1af76
JA
1006 /* We got the response - restart system call. */
1007 rstart = 1;
1008 }
1009 }
1010
1011 spin_lock(&GlobalMid_Lock);
1012 if (midQ->resp_buf) {
1013 spin_unlock(&GlobalMid_Lock);
1014 receive_len = midQ->resp_buf->smb_buf_length;
1015 } else {
79a58d1f 1016 cERROR(1, ("No response for cmd %d mid %d",
7ee1af76 1017 midQ->command, midQ->mid));
79a58d1f
SF
1018 if (midQ->midState == MID_REQUEST_SUBMITTED) {
1019 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
1020 rc = -EHOSTDOWN;
1021 else {
1022 ses->server->tcpStatus = CifsNeedReconnect;
1023 midQ->midState = MID_RETRY_NEEDED;
1024 }
1025 }
1026
1027 if (rc != -EHOSTDOWN) {
79a58d1f 1028 if (midQ->midState == MID_RETRY_NEEDED) {
7ee1af76 1029 rc = -EAGAIN;
79a58d1f 1030 cFYI(1, ("marking request for retry"));
7ee1af76
JA
1031 } else {
1032 rc = -EIO;
1033 }
1034 }
1035 spin_unlock(&GlobalMid_Lock);
1036 DeleteMidQEntry(midQ);
1037 return rc;
1da177e4 1038 }
50c2f753 1039
7ee1af76
JA
1040 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
1041 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1042 receive_len, xid));
1043 rc = -EIO;
1044 } else { /* rcvd frame is ok */
1045
1046 if (midQ->resp_buf && out_buf
1047 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
1048 out_buf->smb_buf_length = receive_len;
1049 memcpy((char *)out_buf + 4,
1050 (char *)midQ->resp_buf + 4,
1051 receive_len);
1052
1053 dump_smb(out_buf, 92);
1054 /* convert the length into a more usable form */
79a58d1f 1055 if ((receive_len > 24) &&
7ee1af76
JA
1056 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1057 SECMODE_SIGN_ENABLED))) {
1058 rc = cifs_verify_signature(out_buf,
b609f06a 1059 &ses->server->mac_signing_key,
7ee1af76 1060 midQ->sequence_number+1);
79a58d1f
SF
1061 if (rc) {
1062 cERROR(1, ("Unexpected SMB signature"));
7ee1af76
JA
1063 /* BB FIXME add code to kill session */
1064 }
1065 }
1066
1067 *pbytes_returned = out_buf->smb_buf_length;
1068
1069 /* BB special case reconnect tid and uid here? */
a761ac57 1070 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1da177e4 1071
7ee1af76 1072 /* convert ByteCount if necessary */
26f57364
SF
1073 if (receive_len >= sizeof(struct smb_hdr) - 4
1074 /* do not count RFC1001 header */ +
7ee1af76
JA
1075 (2 * out_buf->WordCount) + 2 /* bcc */ )
1076 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1077 } else {
1078 rc = -EIO;
79a58d1f 1079 cERROR(1, ("Bad MID state?"));
7ee1af76
JA
1080 }
1081 }
1082 DeleteMidQEntry(midQ);
1083 if (rstart && rc == -EACCES)
1084 return -ERESTARTSYS;
1da177e4
LT
1085 return rc;
1086}
This page took 0.317309 seconds and 5 git commands to generate.