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