~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/cifs/transport.c

Version: ~ [ linux-5.12-rc1 ] ~ [ linux-5.11.2 ] ~ [ linux-5.10.19 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.101 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.177 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.222 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.258 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.258 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *   fs/cifs/transport.c
  3  *
  4  *   Copyright (C) International Business Machines  Corp., 2002,2008
  5  *   Author(s): Steve French (sfrench@us.ibm.com)
  6  *   Jeremy Allison (jra@samba.org) 2006.
  7  *
  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
 20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 21  */
 22 
 23 #include <linux/fs.h>
 24 #include <linux/list.h>
 25 #include <linux/gfp.h>
 26 #include <linux/wait.h>
 27 #include <linux/net.h>
 28 #include <linux/delay.h>
 29 #include <linux/freezer.h>
 30 #include <linux/tcp.h>
 31 #include <linux/highmem.h>
 32 #include <asm/uaccess.h>
 33 #include <asm/processor.h>
 34 #include <linux/mempool.h>
 35 #include "cifspdu.h"
 36 #include "cifsglob.h"
 37 #include "cifsproto.h"
 38 #include "cifs_debug.h"
 39 
 40 void
 41 cifs_wake_up_task(struct mid_q_entry *mid)
 42 {
 43         wake_up_process(mid->callback_data);
 44 }
 45 
 46 struct mid_q_entry *
 47 AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
 48 {
 49         struct mid_q_entry *temp;
 50 
 51         if (server == NULL) {
 52                 cifs_dbg(VFS, "Null TCP session in AllocMidQEntry\n");
 53                 return NULL;
 54         }
 55 
 56         temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
 57         if (temp == NULL)
 58                 return temp;
 59         else {
 60                 memset(temp, 0, sizeof(struct mid_q_entry));
 61                 temp->mid = get_mid(smb_buffer);
 62                 temp->pid = current->pid;
 63                 temp->command = cpu_to_le16(smb_buffer->Command);
 64                 cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command);
 65         /*      do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
 66                 /* when mid allocated can be before when sent */
 67                 temp->when_alloc = jiffies;
 68                 temp->server = server;
 69 
 70                 /*
 71                  * The default is for the mid to be synchronous, so the
 72                  * default callback just wakes up the current task.
 73                  */
 74                 temp->callback = cifs_wake_up_task;
 75                 temp->callback_data = current;
 76         }
 77 
 78         atomic_inc(&midCount);
 79         temp->mid_state = MID_REQUEST_ALLOCATED;
 80         return temp;
 81 }
 82 
 83 void
 84 DeleteMidQEntry(struct mid_q_entry *midEntry)
 85 {
 86 #ifdef CONFIG_CIFS_STATS2
 87         __le16 command = midEntry->server->vals->lock_cmd;
 88         unsigned long now;
 89 #endif
 90         midEntry->mid_state = MID_FREE;
 91         atomic_dec(&midCount);
 92         if (midEntry->large_buf)
 93                 cifs_buf_release(midEntry->resp_buf);
 94         else
 95                 cifs_small_buf_release(midEntry->resp_buf);
 96 #ifdef CONFIG_CIFS_STATS2
 97         now = jiffies;
 98         /* commands taking longer than one second are indications that
 99            something is wrong, unless it is quite a slow link or server */
100         if ((now - midEntry->when_alloc) > HZ) {
101                 if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
102                         pr_debug(" CIFS slow rsp: cmd %d mid %llu",
103                                midEntry->command, midEntry->mid);
104                         pr_info(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
105                                now - midEntry->when_alloc,
106                                now - midEntry->when_sent,
107                                now - midEntry->when_received);
108                 }
109         }
110 #endif
111         mempool_free(midEntry, cifs_mid_poolp);
112 }
113 
114 void
115 cifs_delete_mid(struct mid_q_entry *mid)
116 {
117         spin_lock(&GlobalMid_Lock);
118         list_del(&mid->qhead);
119         spin_unlock(&GlobalMid_Lock);
120 
121         DeleteMidQEntry(mid);
122 }
123 
124 /*
125  * smb_send_kvec - send an array of kvecs to the server
126  * @server:     Server to send the data to
127  * @smb_msg:    Message to send
128  * @sent:       amount of data sent on socket is stored here
129  *
130  * Our basic "send data to server" function. Should be called with srv_mutex
131  * held. The caller is responsible for handling the results.
132  */
133 static int
134 smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
135               size_t *sent)
136 {
137         int rc = 0;
138         int retries = 0;
139         struct socket *ssocket = server->ssocket;
140 
141         *sent = 0;
142 
143         smb_msg->msg_name = (struct sockaddr *) &server->dstaddr;
144         smb_msg->msg_namelen = sizeof(struct sockaddr);
145         smb_msg->msg_control = NULL;
146         smb_msg->msg_controllen = 0;
147         if (server->noblocksnd)
148                 smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
149         else
150                 smb_msg->msg_flags = MSG_NOSIGNAL;
151 
152         while (msg_data_left(smb_msg)) {
153                 /*
154                  * If blocking send, we try 3 times, since each can block
155                  * for 5 seconds. For nonblocking  we have to try more
156                  * but wait increasing amounts of time allowing time for
157                  * socket to clear.  The overall time we wait in either
158                  * case to send on the socket is about 15 seconds.
159                  * Similarly we wait for 15 seconds for a response from
160                  * the server in SendReceive[2] for the server to send
161                  * a response back for most types of requests (except
162                  * SMB Write past end of file which can be slow, and
163                  * blocking lock operations). NFS waits slightly longer
164                  * than CIFS, but this can make it take longer for
165                  * nonresponsive servers to be detected and 15 seconds
166                  * is more than enough time for modern networks to
167                  * send a packet.  In most cases if we fail to send
168                  * after the retries we will kill the socket and
169                  * reconnect which may clear the network problem.
170                  */
171                 rc = sock_sendmsg(ssocket, smb_msg);
172                 if (rc == -EAGAIN) {
173                         retries++;
174                         if (retries >= 14 ||
175                             (!server->noblocksnd && (retries > 2))) {
176                                 cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
177                                          ssocket);
178                                 return -EAGAIN;
179                         }
180                         msleep(1 << retries);
181                         continue;
182                 }
183 
184                 if (rc < 0)
185                         return rc;
186 
187                 if (rc == 0) {
188                         /* should never happen, letting socket clear before
189                            retrying is our only obvious option here */
190                         cifs_dbg(VFS, "tcp sent no data\n");
191                         msleep(500);
192                         continue;
193                 }
194 
195                 /* send was at least partially successful */
196                 *sent += rc;
197                 retries = 0; /* in case we get ENOSPC on the next send */
198         }
199         return 0;
200 }
201 
202 static unsigned long
203 rqst_len(struct smb_rqst *rqst)
204 {
205         unsigned int i;
206         struct kvec *iov = rqst->rq_iov;
207         unsigned long buflen = 0;
208 
209         /* total up iov array first */
210         for (i = 0; i < rqst->rq_nvec; i++)
211                 buflen += iov[i].iov_len;
212 
213         /* add in the page array if there is one */
214         if (rqst->rq_npages) {
215                 buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
216                 buflen += rqst->rq_tailsz;
217         }
218 
219         return buflen;
220 }
221 
222 static int
223 smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
224 {
225         int rc;
226         struct kvec *iov = rqst->rq_iov;
227         int n_vec = rqst->rq_nvec;
228         unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
229         unsigned long send_length;
230         unsigned int i;
231         size_t total_len = 0, sent, size;
232         struct socket *ssocket = server->ssocket;
233         struct msghdr smb_msg;
234         int val = 1;
235 
236         if (ssocket == NULL)
237                 return -ENOTSOCK;
238 
239         /* sanity check send length */
240         send_length = rqst_len(rqst);
241         if (send_length != smb_buf_length + 4) {
242                 WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n",
243                         send_length, smb_buf_length);
244                 return -EIO;
245         }
246 
247         cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
248         dump_smb(iov[0].iov_base, iov[0].iov_len);
249 
250         /* cork the socket */
251         kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
252                                 (char *)&val, sizeof(val));
253 
254         size = 0;
255         for (i = 0; i < n_vec; i++)
256                 size += iov[i].iov_len;
257 
258         iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, iov, n_vec, size);
259 
260         rc = smb_send_kvec(server, &smb_msg, &sent);
261         if (rc < 0)
262                 goto uncork;
263 
264         total_len += sent;
265 
266         /* now walk the page array and send each page in it */
267         for (i = 0; i < rqst->rq_npages; i++) {
268                 size_t len = i == rqst->rq_npages - 1
269                                 ? rqst->rq_tailsz
270                                 : rqst->rq_pagesz;
271                 struct bio_vec bvec = {
272                         .bv_page = rqst->rq_pages[i],
273                         .bv_len = len
274                 };
275                 iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC,
276                               &bvec, 1, len);
277                 rc = smb_send_kvec(server, &smb_msg, &sent);
278                 if (rc < 0)
279                         break;
280 
281                 total_len += sent;
282         }
283 
284 uncork:
285         /* uncork it */
286         val = 0;
287         kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
288                                 (char *)&val, sizeof(val));
289 
290         if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
291                 cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",
292                          smb_buf_length + 4, total_len);
293                 /*
294                  * If we have only sent part of an SMB then the next SMB could
295                  * be taken as the remainder of this one. We need to kill the
296                  * socket so the server throws away the partial SMB
297                  */
298                 server->tcpStatus = CifsNeedReconnect;
299         }
300 
301         if (rc < 0 && rc != -EINTR)
302                 cifs_dbg(VFS, "Error %d sending data on socket to server\n",
303                          rc);
304         else
305                 rc = 0;
306 
307         return rc;
308 }
309 
310 static int
311 smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
312 {
313         struct smb_rqst rqst = { .rq_iov = iov,
314                                  .rq_nvec = n_vec };
315 
316         return smb_send_rqst(server, &rqst);
317 }
318 
319 int
320 smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
321          unsigned int smb_buf_length)
322 {
323         struct kvec iov;
324 
325         iov.iov_base = smb_buffer;
326         iov.iov_len = smb_buf_length + 4;
327 
328         return smb_sendv(server, &iov, 1);
329 }
330 
331 static int
332 wait_for_free_credits(struct TCP_Server_Info *server, const int timeout,
333                       int *credits)
334 {
335         int rc;
336 
337         spin_lock(&server->req_lock);
338         if (timeout == CIFS_ASYNC_OP) {
339                 /* oplock breaks must not be held up */
340                 server->in_flight++;
341                 *credits -= 1;
342                 spin_unlock(&server->req_lock);
343                 return 0;
344         }
345 
346         while (1) {
347                 if (*credits <= 0) {
348                         spin_unlock(&server->req_lock);
349                         cifs_num_waiters_inc(server);
350                         rc = wait_event_killable(server->request_q,
351                                                  has_credits(server, credits));
352                         cifs_num_waiters_dec(server);
353                         if (rc)
354                                 return rc;
355                         spin_lock(&server->req_lock);
356                 } else {
357                         if (server->tcpStatus == CifsExiting) {
358                                 spin_unlock(&server->req_lock);
359                                 return -ENOENT;
360                         }
361 
362                         /*
363                          * Can not count locking commands against total
364                          * as they are allowed to block on server.
365                          */
366 
367                         /* update # of requests on the wire to server */
368                         if (timeout != CIFS_BLOCKING_OP) {
369                                 *credits -= 1;
370                                 server->in_flight++;
371                         }
372                         spin_unlock(&server->req_lock);
373                         break;
374                 }
375         }
376         return 0;
377 }
378 
379 static int
380 wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
381                       const int optype)
382 {
383         int *val;
384 
385         val = server->ops->get_credits_field(server, optype);
386         /* Since an echo is already inflight, no need to wait to send another */
387         if (*val <= 0 && optype == CIFS_ECHO_OP)
388                 return -EAGAIN;
389         return wait_for_free_credits(server, timeout, val);
390 }
391 
392 int
393 cifs_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
394                       unsigned int *num, unsigned int *credits)
395 {
396         *num = size;
397         *credits = 0;
398         return 0;
399 }
400 
401 static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
402                         struct mid_q_entry **ppmidQ)
403 {
404         if (ses->server->tcpStatus == CifsExiting) {
405                 return -ENOENT;
406         }
407 
408         if (ses->server->tcpStatus == CifsNeedReconnect) {
409                 cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
410                 return -EAGAIN;
411         }
412 
413         if (ses->status == CifsNew) {
414                 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
415                         (in_buf->Command != SMB_COM_NEGOTIATE))
416                         return -EAGAIN;
417                 /* else ok - we are setting up session */
418         }
419 
420         if (ses->status == CifsExiting) {
421                 /* check if SMB session is bad because we are setting it up */
422                 if (in_buf->Command != SMB_COM_LOGOFF_ANDX)
423                         return -EAGAIN;
424                 /* else ok - we are shutting down session */
425         }
426 
427         *ppmidQ = AllocMidQEntry(in_buf, ses->server);
428         if (*ppmidQ == NULL)
429                 return -ENOMEM;
430         spin_lock(&GlobalMid_Lock);
431         list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
432         spin_unlock(&GlobalMid_Lock);
433         return 0;
434 }
435 
436 static int
437 wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
438 {
439         int error;
440 
441         error = wait_event_freezekillable_unsafe(server->response_q,
442                                     midQ->mid_state != MID_REQUEST_SUBMITTED);
443         if (error < 0)
444                 return -ERESTARTSYS;
445 
446         return 0;
447 }
448 
449 struct mid_q_entry *
450 cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
451 {
452         int rc;
453         struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
454         struct mid_q_entry *mid;
455 
456         /* enable signing if server requires it */
457         if (server->sign)
458                 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
459 
460         mid = AllocMidQEntry(hdr, server);
461         if (mid == NULL)
462                 return ERR_PTR(-ENOMEM);
463 
464         rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
465         if (rc) {
466                 DeleteMidQEntry(mid);
467                 return ERR_PTR(rc);
468         }
469 
470         return mid;
471 }
472 
473 /*
474  * Send a SMB request and set the callback function in the mid to handle
475  * the result. Caller is responsible for dealing with timeouts.
476  */
477 int
478 cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
479                 mid_receive_t *receive, mid_callback_t *callback,
480                 void *cbdata, const int flags)
481 {
482         int rc, timeout, optype;
483         struct mid_q_entry *mid;
484         unsigned int credits = 0;
485 
486         timeout = flags & CIFS_TIMEOUT_MASK;
487         optype = flags & CIFS_OP_MASK;
488 
489         if ((flags & CIFS_HAS_CREDITS) == 0) {
490                 rc = wait_for_free_request(server, timeout, optype);
491                 if (rc)
492                         return rc;
493                 credits = 1;
494         }
495 
496         mutex_lock(&server->srv_mutex);
497         mid = server->ops->setup_async_request(server, rqst);
498         if (IS_ERR(mid)) {
499                 mutex_unlock(&server->srv_mutex);
500                 add_credits_and_wake_if(server, credits, optype);
501                 return PTR_ERR(mid);
502         }
503 
504         mid->receive = receive;
505         mid->callback = callback;
506         mid->callback_data = cbdata;
507         mid->mid_state = MID_REQUEST_SUBMITTED;
508 
509         /* put it on the pending_mid_q */
510         spin_lock(&GlobalMid_Lock);
511         list_add_tail(&mid->qhead, &server->pending_mid_q);
512         spin_unlock(&GlobalMid_Lock);
513 
514 
515         cifs_in_send_inc(server);
516         rc = smb_send_rqst(server, rqst);
517         cifs_in_send_dec(server);
518         cifs_save_when_sent(mid);
519 
520         if (rc < 0) {
521                 server->sequence_number -= 2;
522                 cifs_delete_mid(mid);
523         }
524 
525         mutex_unlock(&server->srv_mutex);
526 
527         if (rc == 0)
528                 return 0;
529 
530         add_credits_and_wake_if(server, credits, optype);
531         return rc;
532 }
533 
534 /*
535  *
536  * Send an SMB Request.  No response info (other than return code)
537  * needs to be parsed.
538  *
539  * flags indicate the type of request buffer and how long to wait
540  * and whether to log NT STATUS code (error) before mapping it to POSIX error
541  *
542  */
543 int
544 SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
545                  char *in_buf, int flags)
546 {
547         int rc;
548         struct kvec iov[1];
549         int resp_buf_type;
550 
551         iov[0].iov_base = in_buf;
552         iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
553         flags |= CIFS_NO_RESP;
554         rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
555         cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
556 
557         return rc;
558 }
559 
560 static int
561 cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
562 {
563         int rc = 0;
564 
565         cifs_dbg(FYI, "%s: cmd=%d mid=%llu state=%d\n",
566                  __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state);
567 
568         spin_lock(&GlobalMid_Lock);
569         switch (mid->mid_state) {
570         case MID_RESPONSE_RECEIVED:
571                 spin_unlock(&GlobalMid_Lock);
572                 return rc;
573         case MID_RETRY_NEEDED:
574                 rc = -EAGAIN;
575                 break;
576         case MID_RESPONSE_MALFORMED:
577                 rc = -EIO;
578                 break;
579         case MID_SHUTDOWN:
580                 rc = -EHOSTDOWN;
581                 break;
582         default:
583                 list_del_init(&mid->qhead);
584                 cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
585                          __func__, mid->mid, mid->mid_state);
586                 rc = -EIO;
587         }
588         spin_unlock(&GlobalMid_Lock);
589 
590         mutex_lock(&server->srv_mutex);
591         DeleteMidQEntry(mid);
592         mutex_unlock(&server->srv_mutex);
593         return rc;
594 }
595 
596 static inline int
597 send_cancel(struct TCP_Server_Info *server, void *buf, struct mid_q_entry *mid)
598 {
599         return server->ops->send_cancel ?
600                                 server->ops->send_cancel(server, buf, mid) : 0;
601 }
602 
603 int
604 cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
605                    bool log_error)
606 {
607         unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
608 
609         dump_smb(mid->resp_buf, min_t(u32, 92, len));
610 
611         /* convert the length into a more usable form */
612         if (server->sign) {
613                 struct kvec iov;
614                 int rc = 0;
615                 struct smb_rqst rqst = { .rq_iov = &iov,
616                                          .rq_nvec = 1 };
617 
618                 iov.iov_base = mid->resp_buf;
619                 iov.iov_len = len;
620                 /* FIXME: add code to kill session */
621                 rc = cifs_verify_signature(&rqst, server,
622                                            mid->sequence_number);
623                 if (rc)
624                         cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
625                                  rc);
626         }
627 
628         /* BB special case reconnect tid and uid here? */
629         return map_smb_to_linux_error(mid->resp_buf, log_error);
630 }
631 
632 struct mid_q_entry *
633 cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
634 {
635         int rc;
636         struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
637         struct mid_q_entry *mid;
638 
639         rc = allocate_mid(ses, hdr, &mid);
640         if (rc)
641                 return ERR_PTR(rc);
642         rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
643         if (rc) {
644                 cifs_delete_mid(mid);
645                 return ERR_PTR(rc);
646         }
647         return mid;
648 }
649 
650 int
651 SendReceive2(const unsigned int xid, struct cifs_ses *ses,
652              struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
653              const int flags)
654 {
655         int rc = 0;
656         int timeout, optype;
657         struct mid_q_entry *midQ;
658         char *buf = iov[0].iov_base;
659         unsigned int credits = 1;
660         struct smb_rqst rqst = { .rq_iov = iov,
661                                  .rq_nvec = n_vec };
662 
663         timeout = flags & CIFS_TIMEOUT_MASK;
664         optype = flags & CIFS_OP_MASK;
665 
666         *resp_buf_type = CIFS_NO_BUFFER;  /* no response buf yet */
667 
668         if ((ses == NULL) || (ses->server == NULL)) {
669                 cifs_small_buf_release(buf);
670                 cifs_dbg(VFS, "Null session\n");
671                 return -EIO;
672         }
673 
674         if (ses->server->tcpStatus == CifsExiting) {
675                 cifs_small_buf_release(buf);
676                 return -ENOENT;
677         }
678 
679         /*
680          * Ensure that we do not send more than 50 overlapping requests
681          * to the same server. We may make this configurable later or
682          * use ses->maxReq.
683          */
684 
685         rc = wait_for_free_request(ses->server, timeout, optype);
686         if (rc) {
687                 cifs_small_buf_release(buf);
688                 return rc;
689         }
690 
691         /*
692          * Make sure that we sign in the same order that we send on this socket
693          * and avoid races inside tcp sendmsg code that could cause corruption
694          * of smb data.
695          */
696 
697         mutex_lock(&ses->server->srv_mutex);
698 
699         midQ = ses->server->ops->setup_request(ses, &rqst);
700         if (IS_ERR(midQ)) {
701                 mutex_unlock(&ses->server->srv_mutex);
702                 cifs_small_buf_release(buf);
703                 /* Update # of requests on wire to server */
704                 add_credits(ses->server, 1, optype);
705                 return PTR_ERR(midQ);
706         }
707 
708         midQ->mid_state = MID_REQUEST_SUBMITTED;
709         cifs_in_send_inc(ses->server);
710         rc = smb_sendv(ses->server, iov, n_vec);
711         cifs_in_send_dec(ses->server);
712         cifs_save_when_sent(midQ);
713 
714         if (rc < 0)
715                 ses->server->sequence_number -= 2;
716         mutex_unlock(&ses->server->srv_mutex);
717 
718         if (rc < 0) {
719                 cifs_small_buf_release(buf);
720                 goto out;
721         }
722 
723         if (timeout == CIFS_ASYNC_OP) {
724                 cifs_small_buf_release(buf);
725                 goto out;
726         }
727 
728         rc = wait_for_response(ses->server, midQ);
729         if (rc != 0) {
730                 send_cancel(ses->server, buf, midQ);
731                 spin_lock(&GlobalMid_Lock);
732                 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
733                         midQ->callback = DeleteMidQEntry;
734                         spin_unlock(&GlobalMid_Lock);
735                         cifs_small_buf_release(buf);
736                         add_credits(ses->server, 1, optype);
737                         return rc;
738                 }
739                 spin_unlock(&GlobalMid_Lock);
740         }
741 
742         cifs_small_buf_release(buf);
743 
744         rc = cifs_sync_mid_result(midQ, ses->server);
745         if (rc != 0) {
746                 add_credits(ses->server, 1, optype);
747                 return rc;
748         }
749 
750         if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
751                 rc = -EIO;
752                 cifs_dbg(FYI, "Bad MID state?\n");
753                 goto out;
754         }
755 
756         buf = (char *)midQ->resp_buf;
757         iov[0].iov_base = buf;
758         iov[0].iov_len = get_rfc1002_length(buf) + 4;
759         if (midQ->large_buf)
760                 *resp_buf_type = CIFS_LARGE_BUFFER;
761         else
762                 *resp_buf_type = CIFS_SMALL_BUFFER;
763 
764         credits = ses->server->ops->get_credits(midQ);
765 
766         rc = ses->server->ops->check_receive(midQ, ses->server,
767                                              flags & CIFS_LOG_ERROR);
768 
769         /* mark it so buf will not be freed by cifs_delete_mid */
770         if ((flags & CIFS_NO_RESP) == 0)
771                 midQ->resp_buf = NULL;
772 out:
773         cifs_delete_mid(midQ);
774         add_credits(ses->server, credits, optype);
775 
776         return rc;
777 }
778 
779 int
780 SendReceive(const unsigned int xid, struct cifs_ses *ses,
781             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
782             int *pbytes_returned, const int timeout)
783 {
784         int rc = 0;
785         struct mid_q_entry *midQ;
786 
787         if (ses == NULL) {
788                 cifs_dbg(VFS, "Null smb session\n");
789                 return -EIO;
790         }
791         if (ses->server == NULL) {
792                 cifs_dbg(VFS, "Null tcp session\n");
793                 return -EIO;
794         }
795 
796         if (ses->server->tcpStatus == CifsExiting)
797                 return -ENOENT;
798 
799         /* Ensure that we do not send more than 50 overlapping requests
800            to the same server. We may make this configurable later or
801            use ses->maxReq */
802 
803         if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
804                         MAX_CIFS_HDR_SIZE - 4) {
805                 cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
806                          be32_to_cpu(in_buf->smb_buf_length));
807                 return -EIO;
808         }
809 
810         rc = wait_for_free_request(ses->server, timeout, 0);
811         if (rc)
812                 return rc;
813 
814         /* make sure that we sign in the same order that we send on this socket
815            and avoid races inside tcp sendmsg code that could cause corruption
816            of smb data */
817 
818         mutex_lock(&ses->server->srv_mutex);
819 
820         rc = allocate_mid(ses, in_buf, &midQ);
821         if (rc) {
822                 mutex_unlock(&ses->server->srv_mutex);
823                 /* Update # of requests on wire to server */
824                 add_credits(ses->server, 1, 0);
825                 return rc;
826         }
827 
828         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829         if (rc) {
830                 mutex_unlock(&ses->server->srv_mutex);
831                 goto out;
832         }
833 
834         midQ->mid_state = MID_REQUEST_SUBMITTED;
835 
836         cifs_in_send_inc(ses->server);
837         rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
838         cifs_in_send_dec(ses->server);
839         cifs_save_when_sent(midQ);
840 
841         if (rc < 0)
842                 ses->server->sequence_number -= 2;
843 
844         mutex_unlock(&ses->server->srv_mutex);
845 
846         if (rc < 0)
847                 goto out;
848 
849         if (timeout == CIFS_ASYNC_OP)
850                 goto out;
851 
852         rc = wait_for_response(ses->server, midQ);
853         if (rc != 0) {
854                 send_cancel(ses->server, in_buf, midQ);
855                 spin_lock(&GlobalMid_Lock);
856                 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
857                         /* no longer considered to be "in-flight" */
858                         midQ->callback = DeleteMidQEntry;
859                         spin_unlock(&GlobalMid_Lock);
860                         add_credits(ses->server, 1, 0);
861                         return rc;
862                 }
863                 spin_unlock(&GlobalMid_Lock);
864         }
865 
866         rc = cifs_sync_mid_result(midQ, ses->server);
867         if (rc != 0) {
868                 add_credits(ses->server, 1, 0);
869                 return rc;
870         }
871 
872         if (!midQ->resp_buf || !out_buf ||
873             midQ->mid_state != MID_RESPONSE_RECEIVED) {
874                 rc = -EIO;
875                 cifs_dbg(VFS, "Bad MID state?\n");
876                 goto out;
877         }
878 
879         *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
880         memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
881         rc = cifs_check_receive(midQ, ses->server, 0);
882 out:
883         cifs_delete_mid(midQ);
884         add_credits(ses->server, 1, 0);
885 
886         return rc;
887 }
888 
889 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
890    blocking lock to return. */
891 
892 static int
893 send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
894                         struct smb_hdr *in_buf,
895                         struct smb_hdr *out_buf)
896 {
897         int bytes_returned;
898         struct cifs_ses *ses = tcon->ses;
899         LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
900 
901         /* We just modify the current in_buf to change
902            the type of lock from LOCKING_ANDX_SHARED_LOCK
903            or LOCKING_ANDX_EXCLUSIVE_LOCK to
904            LOCKING_ANDX_CANCEL_LOCK. */
905 
906         pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
907         pSMB->Timeout = 0;
908         pSMB->hdr.Mid = get_next_mid(ses->server);
909 
910         return SendReceive(xid, ses, in_buf, out_buf,
911                         &bytes_returned, 0);
912 }
913 
914 int
915 SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
916             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
917             int *pbytes_returned)
918 {
919         int rc = 0;
920         int rstart = 0;
921         struct mid_q_entry *midQ;
922         struct cifs_ses *ses;
923 
924         if (tcon == NULL || tcon->ses == NULL) {
925                 cifs_dbg(VFS, "Null smb session\n");
926                 return -EIO;
927         }
928         ses = tcon->ses;
929 
930         if (ses->server == NULL) {
931                 cifs_dbg(VFS, "Null tcp session\n");
932                 return -EIO;
933         }
934 
935         if (ses->server->tcpStatus == CifsExiting)
936                 return -ENOENT;
937 
938         /* Ensure that we do not send more than 50 overlapping requests
939            to the same server. We may make this configurable later or
940            use ses->maxReq */
941 
942         if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
943                         MAX_CIFS_HDR_SIZE - 4) {
944                 cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
945                          be32_to_cpu(in_buf->smb_buf_length));
946                 return -EIO;
947         }
948 
949         rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0);
950         if (rc)
951                 return rc;
952 
953         /* make sure that we sign in the same order that we send on this socket
954            and avoid races inside tcp sendmsg code that could cause corruption
955            of smb data */
956 
957         mutex_lock(&ses->server->srv_mutex);
958 
959         rc = allocate_mid(ses, in_buf, &midQ);
960         if (rc) {
961                 mutex_unlock(&ses->server->srv_mutex);
962                 return rc;
963         }
964 
965         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
966         if (rc) {
967                 cifs_delete_mid(midQ);
968                 mutex_unlock(&ses->server->srv_mutex);
969                 return rc;
970         }
971 
972         midQ->mid_state = MID_REQUEST_SUBMITTED;
973         cifs_in_send_inc(ses->server);
974         rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
975         cifs_in_send_dec(ses->server);
976         cifs_save_when_sent(midQ);
977 
978         if (rc < 0)
979                 ses->server->sequence_number -= 2;
980 
981         mutex_unlock(&ses->server->srv_mutex);
982 
983         if (rc < 0) {
984                 cifs_delete_mid(midQ);
985                 return rc;
986         }
987 
988         /* Wait for a reply - allow signals to interrupt. */
989         rc = wait_event_interruptible(ses->server->response_q,
990                 (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
991                 ((ses->server->tcpStatus != CifsGood) &&
992                  (ses->server->tcpStatus != CifsNew)));
993 
994         /* Were we interrupted by a signal ? */
995         if ((rc == -ERESTARTSYS) &&
996                 (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
997                 ((ses->server->tcpStatus == CifsGood) ||
998                  (ses->server->tcpStatus == CifsNew))) {
999 
1000                 if (in_buf->Command == SMB_COM_TRANSACTION2) {
1001                         /* POSIX lock. We send a NT_CANCEL SMB to cause the
1002                            blocking lock to return. */
1003                         rc = send_cancel(ses->server, in_buf, midQ);
1004                         if (rc) {
1005                                 cifs_delete_mid(midQ);
1006                                 return rc;
1007                         }
1008                 } else {
1009                         /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
1010                            to cause the blocking lock to return. */
1011 
1012                         rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
1013 
1014                         /* If we get -ENOLCK back the lock may have
1015                            already been removed. Don't exit in this case. */
1016                         if (rc && rc != -ENOLCK) {
1017                                 cifs_delete_mid(midQ);
1018                                 return rc;
1019                         }
1020                 }
1021 
1022                 rc = wait_for_response(ses->server, midQ);
1023                 if (rc) {
1024                         send_cancel(ses->server, in_buf, midQ);
1025                         spin_lock(&GlobalMid_Lock);
1026                         if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
1027                                 /* no longer considered to be "in-flight" */
1028                                 midQ->callback = DeleteMidQEntry;
1029                                 spin_unlock(&GlobalMid_Lock);
1030                                 return rc;
1031                         }
1032                         spin_unlock(&GlobalMid_Lock);
1033                 }
1034 
1035                 /* We got the response - restart system call. */
1036                 rstart = 1;
1037         }
1038 
1039         rc = cifs_sync_mid_result(midQ, ses->server);
1040         if (rc != 0)
1041                 return rc;
1042 
1043         /* rcvd frame is ok */
1044         if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
1045                 rc = -EIO;
1046                 cifs_dbg(VFS, "Bad MID state?\n");
1047                 goto out;
1048         }
1049 
1050         *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
1051         memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
1052         rc = cifs_check_receive(midQ, ses->server, 0);
1053 out:
1054         cifs_delete_mid(midQ);
1055         if (rstart && rc == -EACCES)
1056                 return -ERESTARTSYS;
1057         return rc;
1058 }
1059 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp