]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/cifs/transport.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-2.6-omap-h63xx.git] / fs / cifs / transport.c
index 7ed32b3cb781a0011a0560b7fe3898825f5c9e4f..3612d6c0a0bbc1a4c9f64c2ce0f674517ce86d72 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/transport.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2007
+ *   Copyright (C) International Business Machines  Corp., 2002,2008
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *   Jeremy Allison (jra@samba.org) 2006.
  *
@@ -308,7 +308,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
 
 static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
 {
-       if (long_op == -1) {
+       if (long_op == CIFS_ASYNC_OP) {
                /* oplock breaks must not be held up */
                atomic_inc(&ses->server->inFlight);
        } else {
@@ -337,7 +337,7 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
                                   as they are allowed to block on server */
 
                                /* update # of requests on the wire to server */
-                               if (long_op < 3)
+                               if (long_op != CIFS_BLOCKING_OP)
                                        atomic_inc(&ses->server->inFlight);
                                spin_unlock(&GlobalMid_Lock);
                                break;
@@ -358,9 +358,9 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
        } else if (ses->status != CifsGood) {
                /* check if SMB session is bad because we are setting it up */
                if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
-                       (in_buf->Command != SMB_COM_NEGOTIATE)) {
+                       (in_buf->Command != SMB_COM_NEGOTIATE))
                        return -EAGAIN;
-               /* else ok - we are setting up session */
+               /* else ok - we are setting up session */
        }
        *ppmidQ = AllocMidQEntry(in_buf, ses);
        if (*ppmidQ == NULL)
@@ -415,17 +415,47 @@ static int wait_for_response(struct cifsSesInfo *ses,
        }
 }
 
+
+/*
+ *
+ * Send an SMB Request.  No response info (other than return code)
+ * needs to be parsed.
+ *
+ * flags indicate the type of request buffer and how long to wait
+ * and whether to log NT STATUS code (error) before mapping it to POSIX error
+ *
+ */
+int
+SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
+               struct smb_hdr *in_buf, int flags)
+{
+       int rc;
+       struct kvec iov[1];
+       int resp_buf_type;
+
+       iov[0].iov_base = (char *)in_buf;
+       iov[0].iov_len = in_buf->smb_buf_length + 4;
+       flags |= CIFS_NO_RESP;
+       rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
+       cFYI(DBG2, ("SendRcvNoRsp flags %d rc %d", flags, rc));
+
+       return rc;
+}
+
 int
 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
             struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
-            const int long_op, const int logError)
+            const int flags)
 {
        int rc = 0;
+       int long_op;
        unsigned int receive_len;
        unsigned long timeout;
        struct mid_q_entry *midQ;
        struct smb_hdr *in_buf = iov[0].iov_base;
 
+       long_op = flags & CIFS_TIMEOUT_MASK;
+
        *pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
 
        if ((ses == NULL) || (ses->server == NULL)) {
@@ -483,15 +513,22 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
        if (rc < 0)
                goto out;
 
-       if (long_op == -1)
-               goto out;
-       else if (long_op == 2) /* writes past end of file can take loong time */
+       if (long_op == CIFS_STD_OP)
+               timeout = 15 * HZ;
+       else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
                timeout = 180 * HZ;
-       else if (long_op == 1)
+       else if (long_op == CIFS_LONG_OP)
                timeout = 45 * HZ; /* should be greater than
                        servers oplock break timeout (about 43 seconds) */
-       else
-               timeout = 15 * HZ;
+       else if (long_op == CIFS_ASYNC_OP)
+               goto out;
+       else if (long_op == CIFS_BLOCKING_OP)
+               timeout = 0x7FFFFFFF; /*  large, but not so large as to wrap */
+       else {
+               cERROR(1, ("unknown timeout flag %d", long_op));
+               rc = -EIO;
+               goto out;
+       }
 
        /* wait for 15 seconds or until woken up due to response arriving or
           due to last connection to this server being unmounted */
@@ -566,7 +603,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
                        }
 
                        /* BB special case reconnect tid and uid here? */
-                       rc = map_smb_to_linux_error(midQ->resp_buf, logError);
+                       rc = map_smb_to_linux_error(midQ->resp_buf,
+                                               flags & CIFS_LOG_ERROR);
 
                        /* convert ByteCount if necessary */
                        if (receive_len >= sizeof(struct smb_hdr) - 4
@@ -574,8 +612,10 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
                            (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
                                BCC(midQ->resp_buf) =
                                        le16_to_cpu(BCC_LE(midQ->resp_buf));
-                       midQ->resp_buf = NULL;  /* mark it so will not be freed
-                                               by DeleteMidQEntry */
+                       if ((flags & CIFS_NO_RESP) == 0)
+                               midQ->resp_buf = NULL;  /* mark it so buf will
+                                                          not be freed by
+                                                          DeleteMidQEntry */
                } else {
                        rc = -EIO;
                        cFYI(1, ("Bad MID state?"));
@@ -663,17 +703,25 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
        if (rc < 0)
                goto out;
 
-       if (long_op == -1)
+       if (long_op == CIFS_STD_OP)
+               timeout = 15 * HZ;
+       /* wait for 15 seconds or until woken up due to response arriving or
+          due to last connection to this server being unmounted */
+       else if (long_op == CIFS_ASYNC_OP)
                goto out;
-       else if (long_op == 2) /* writes past end of file can take loong time */
+       else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
                timeout = 180 * HZ;
-       else if (long_op == 1)
+       else if (long_op == CIFS_LONG_OP)
                timeout = 45 * HZ; /* should be greater than
                        servers oplock break timeout (about 43 seconds) */
-       else
-               timeout = 15 * HZ;
-       /* wait for 15 seconds or until woken up due to response arriving or
-          due to last connection to this server being unmounted */
+       else if (long_op == CIFS_BLOCKING_OP)
+               timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
+       else {
+               cERROR(1, ("unknown timeout flag %d", long_op));
+               rc = -EIO;
+               goto out;
+       }
+
        if (signal_pending(current)) {
                /* if signal pending do not hold up user for full smb timeout
                but we still give response a chance to complete */
@@ -812,7 +860,7 @@ send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
        pSMB->hdr.Mid = GetNextMid(ses->server);
 
        return SendReceive(xid, ses, in_buf, out_buf,
-                       &bytes_returned, 0);
+                       &bytes_returned, CIFS_STD_OP);
 }
 
 int
@@ -844,7 +892,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
           to the same server. We may make this configurable later or
           use ses->maxReq */
 
-       rc = wait_for_free_request(ses, 3);
+       rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
        if (rc)
                return rc;