[GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch.
[samba.git] / source / smbd / aio.c
index fd886178f606fb2c97d44395307105e2b25767ed..6ee0fe16e1e88e0c0dfa671c72ac9e6482b29853 100644 (file)
@@ -6,7 +6,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -79,7 +78,9 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen,
 *****************************************************************************/
 
 static struct aio_extra *create_aio_ex_write(files_struct *fsp,
-                                            size_t outbuflen, uint16 mid)
+                                            size_t inbuflen,
+                                            size_t outbuflen,
+                                            uint16 mid)
 {
        struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra);
 
@@ -94,18 +95,13 @@ static struct aio_extra *create_aio_ex_write(files_struct *fsp,
                SAFE_FREE(aio_ex);
                return NULL;
        }
-       /* Steal the input buffer containing the write data from the main SMB
-        * call. */
-       /* We must re-allocate a new one here. */
-       if (NewInBuffer(&aio_ex->inbuf) == NULL) {
+
+       if (!(aio_ex->inbuf = SMB_MALLOC_ARRAY(char, inbuflen))) {
                SAFE_FREE(aio_ex->outbuf);
                SAFE_FREE(aio_ex);
                return NULL;
        }
 
-       /* aio_ex->inbuf now contains the stolen old InBuf containing the data
-        * to write. */
-
        DLIST_ADD(aio_list_head, aio_ex);
        aio_ex->fsp = fsp;
        aio_ex->read_req = False;
@@ -120,9 +116,7 @@ static struct aio_extra *create_aio_ex_write(files_struct *fsp,
 static void delete_aio_ex(struct aio_extra *aio_ex)
 {
        DLIST_REMOVE(aio_list_head, aio_ex);
-       /* Safe to do as we've removed ourselves from the in use list first. */
-       free_InBuffer(aio_ex->inbuf);
-
+       SAFE_FREE(aio_ex->inbuf);
        SAFE_FREE(aio_ex->outbuf);
        SAFE_FREE(aio_ex);
 }
@@ -158,7 +152,7 @@ static uint16 aio_pending_array[AIO_PENDING_SIZE];
 
 static void signal_handler(int sig, siginfo_t *info, void *unused)
 {
-       if (signals_received < AIO_PENDING_SIZE - 1) {
+       if (signals_received < AIO_PENDING_SIZE) {
                aio_pending_array[signals_received] = info->si_value.sival_int;
                signals_received++;
        } /* Else signal is lost. */
@@ -199,8 +193,7 @@ void initialize_async_io_handler(void)
 *****************************************************************************/
 
 BOOL schedule_aio_read_and_X(connection_struct *conn,
-                            char *inbuf, char *outbuf,
-                            int length, int len_outbuf,
+                            struct smb_request *req,
                             files_struct *fsp, SMB_OFF_T startpos,
                             size_t smb_maxcnt)
 {
@@ -220,7 +213,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn,
 
        /* Only do this on non-chained and non-chaining reads not using the
         * write cache. */
-        if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF)
+        if (chain_size !=0 || (CVAL(req->inbuf,smb_vwv0) != 0xFF)
            || (lp_write_cache_size(SNUM(conn)) != 0) ) {
                return False;
        }
@@ -232,18 +225,18 @@ BOOL schedule_aio_read_and_X(connection_struct *conn,
                return False;
        }
 
-       /* The following is safe from integer wrap as we've already
-          checked smb_maxcnt is 128k or less. */
-       bufsize = PTR_DIFF(smb_buf(outbuf),outbuf) + smb_maxcnt;
+       /* The following is safe from integer wrap as we've already checked
+          smb_maxcnt is 128k or less. Wct is 12 for read replies */
 
-       if ((aio_ex = create_aio_ex_read(fsp, bufsize,
-                                        SVAL(inbuf,smb_mid))) == NULL) {
+       bufsize = smb_size + 12 * 2 + smb_maxcnt;
+
+       if ((aio_ex = create_aio_ex_read(fsp, bufsize, req->mid)) == NULL) {
                DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n"));
                return False;
        }
 
-       /* Copy the SMB header already setup in outbuf. */
-       memcpy(aio_ex->outbuf, outbuf, smb_buf(outbuf) - outbuf);
+       construct_reply_common((char *)req->inbuf, aio_ex->outbuf);
+       set_message(aio_ex->outbuf, 12, 0, True);
        SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */
 
        a = &aio_ex->acb;
@@ -280,16 +273,15 @@ BOOL schedule_aio_read_and_X(connection_struct *conn,
 *****************************************************************************/
 
 BOOL schedule_aio_write_and_X(connection_struct *conn,
-                               char *inbuf, char *outbuf,
-                               int length, int len_outbuf,
-                               files_struct *fsp, char *data,
-                               SMB_OFF_T startpos,
-                               size_t numtowrite)
+                             struct smb_request *req,
+                             files_struct *fsp, char *data,
+                             SMB_OFF_T startpos,
+                             size_t numtowrite)
 {
        struct aio_extra *aio_ex;
        SMB_STRUCT_AIOCB *a;
-       size_t outbufsize;
-       BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
+       size_t inbufsize, outbufsize;
+       BOOL write_through = BITSETW(req->inbuf+smb_vwv7,0);
        size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
 
        if (!min_aio_write_size || (numtowrite < min_aio_write_size)) {
@@ -303,7 +295,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn,
 
        /* Only do this on non-chained and non-chaining reads not using the
         * write cache. */
-        if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF)
+        if (chain_size !=0 || (CVAL(req->inbuf,smb_vwv0) != 0xFF)
            || (lp_write_cache_size(SNUM(conn)) != 0) ) {
                return False;
        }
@@ -317,22 +309,25 @@ BOOL schedule_aio_write_and_X(connection_struct *conn,
                          "(mid = %u)\n",
                          fsp->fsp_name, (double)startpos,
                          (unsigned int)numtowrite,
-                         (unsigned int)SVAL(inbuf,smb_mid) ));
+                         (unsigned int)req->mid ));
                return False;
        }
 
-       outbufsize = smb_len(outbuf) + 4;
-       if ((aio_ex = create_aio_ex_write(fsp, outbufsize,
-                                         SVAL(inbuf,smb_mid))) == NULL) {
+       inbufsize =  smb_len(req->inbuf) + 4;
+       reply_outbuf(req, 6, 0);
+       outbufsize = smb_len(req->outbuf) + 4;
+       if (!(aio_ex = create_aio_ex_write(fsp, inbufsize, outbufsize,
+                                          req->mid))) {
                DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n"));
                return False;
        }
 
-       /* Paranioa.... */
-       SMB_ASSERT(aio_ex->inbuf == inbuf);
+       /* Copy the SMB header already setup in outbuf. */
+       memcpy(aio_ex->inbuf, req->inbuf, inbufsize);
 
        /* Copy the SMB header already setup in outbuf. */
-       memcpy(aio_ex->outbuf, outbuf, outbufsize);
+       memcpy(aio_ex->outbuf, req->outbuf, outbufsize);
+       TALLOC_FREE(req->outbuf);
        SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */
 
        a = &aio_ex->acb;
@@ -340,8 +335,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn,
        /* Now set up the aio record for the write call. */
        
        a->aio_fildes = fsp->fh->fd;
-       a->aio_buf = data; /* As we've stolen inbuf this points within
-                           * inbuf. */
+       a->aio_buf = aio_ex->inbuf + (PTR_DIFF(data, req->inbuf));
        a->aio_nbytes = numtowrite;
        a->aio_offset = startpos;
        a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
@@ -351,9 +345,6 @@ BOOL schedule_aio_write_and_X(connection_struct *conn,
        if (SMB_VFS_AIO_WRITE(fsp,a) == -1) {
                DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. "
                         "Error %s\n", strerror(errno) ));
-               /* Replace global InBuf as we're going to do a normal write. */
-               set_InBuffer(aio_ex->inbuf);
-               aio_ex->inbuf = NULL;
                delete_aio_ex(aio_ex);
                return False;
        }
@@ -429,7 +420,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
                DEBUG( 3, ( "handle_aio_read_complete file %s max=%d "
                            "nread=%d\n",
                            aio_ex->fsp->fsp_name,
-                           aio_ex->acb.aio_nbytes, (int)nread ) );
+                           (int)aio_ex->acb.aio_nbytes, (int)nread ) );
 
        }
        smb_setlen(outbuf,outsize - 4);
@@ -505,6 +496,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
                ret = errno;
         } else {
                BOOL write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0);
+               NTSTATUS status;
 
                SSVAL(outbuf,smb_vwv2,nwritten);
                SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
@@ -515,7 +507,13 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
 
                DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n",
                         fsp->fnum, (int)numtowrite, (int)nwritten));
-               sync_file(fsp->conn,fsp, write_through);
+               status = sync_file(fsp->conn,fsp, write_through);
+               if (!NT_STATUS_IS_OK(status)) {
+                       UNIXERROR(ERRHRD,ERRdiskfull);
+                       ret = errno;
+                       DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
+                               fsp->fsp_name, nt_errstr(status) ));
+               }
        }
 
        show_msg(outbuf);
@@ -748,21 +746,6 @@ void cancel_aio_by_fsp(files_struct *fsp)
        }
 }
 
-/****************************************************************************
- Check if a buffer was stolen for aio use.
-*****************************************************************************/
-
-BOOL aio_inbuffer_in_use(char *inbuf)
-{
-       struct aio_extra *aio_ex;
-
-       for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
-               if (aio_ex->inbuf == inbuf) {
-                       return True;
-               }
-       }
-       return False;
-}
 #else
 BOOL aio_finished(void)
 {
@@ -779,8 +762,7 @@ int process_aio_queue(void)
 }
 
 BOOL schedule_aio_read_and_X(connection_struct *conn,
-                            char *inbuf, char *outbuf,
-                            int length, int len_outbuf,
+                            struct smb_request *req,
                             files_struct *fsp, SMB_OFF_T startpos,
                             size_t smb_maxcnt)
 {
@@ -788,11 +770,10 @@ BOOL schedule_aio_read_and_X(connection_struct *conn,
 }
 
 BOOL schedule_aio_write_and_X(connection_struct *conn,
-                                char *inbuf, char *outbuf,
-                                int length, int len_outbuf,
-                                files_struct *fsp, char *data,
-                                SMB_OFF_T startpos,
-                                size_t numtowrite)
+                             struct smb_request *req,
+                             files_struct *fsp, char *data,
+                             SMB_OFF_T startpos,
+                             size_t numtowrite)
 {
        return False;
 }
@@ -805,9 +786,4 @@ BOOL wait_for_aio_completion(files_struct *fsp)
 {
        return True;
 }
-
-BOOL aio_inbuffer_in_use(char *ptr)
-{
-       return False;
-}
 #endif