From f2f55d703d0dd549a83809d3e5cc5151569b48d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Jun 2005 22:53:56 +0000 Subject: r7963: Add aio support to 3.0. Jeremy. (This used to be commit 1de27da47051af08790317f5b48b02719d6b9934) --- source3/smbd/aio.c | 748 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 748 insertions(+) create mode 100644 source3/smbd/aio.c (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c new file mode 100644 index 0000000000..7910ee5a7a --- /dev/null +++ b/source3/smbd/aio.c @@ -0,0 +1,748 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + async_io read handling using POSIX async io. + Copyright (C) Jeremy Allison 2005. + + 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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. +*/ + +#include "includes.h" + +#if defined(WITH_AIO) + +/* The signal we'll use to signify aio done. */ +#ifndef RT_SIGNAL_AIO +#define RT_SIGNAL_AIO (SIGRTMIN+3) +#endif + +/**************************************************************************** + The buffer we keep around whilst an aio request is in process. +*****************************************************************************/ + +struct aio_extra { + struct aio_extra *next, *prev; + SMB_STRUCT_AIOCB acb; + files_struct *fsp; + BOOL read_req; + uint16 mid; + char *inbuf; + char *outbuf; +}; + +static struct aio_extra *aio_list_head; + +/**************************************************************************** + Create the extended aio struct we must keep around for the lifetime + of the aio_read call. +*****************************************************************************/ + +static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, uint16 mid) +{ + struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); + + if (!aio_ex) { + return NULL; + } + ZERO_STRUCTP(aio_ex); + /* The output buffer stored in the aio_ex is the start of + the smb return buffer. The buffer used in the acb + is the start of the reply data portion of that buffer. */ + aio_ex->outbuf = SMB_MALLOC_ARRAY(char, buflen); + if (!aio_ex->outbuf) { + SAFE_FREE(aio_ex); + return NULL; + } + DLIST_ADD(aio_list_head, aio_ex); + aio_ex->fsp = fsp; + aio_ex->read_req = True; + aio_ex->mid = mid; + return aio_ex; +} + +/**************************************************************************** + Create the extended aio struct we must keep around for the lifetime + of the aio_write call. +*****************************************************************************/ + +static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen, uint16 mid) +{ + struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); + + if (!aio_ex) { + return NULL; + } + ZERO_STRUCTP(aio_ex); + + /* We need space for an output reply of outbuflen bytes. */ + aio_ex->outbuf = SMB_MALLOC_ARRAY(char, outbuflen); + if (!aio_ex->outbuf) { + 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) { + 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; + aio_ex->mid = mid; + return aio_ex; +} + +/**************************************************************************** + Delete the extended aio struct. +*****************************************************************************/ + +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->outbuf); + SAFE_FREE(aio_ex); +} + +/**************************************************************************** + Given the aiocb struct find the extended aio struct containing it. +*****************************************************************************/ + +static struct aio_extra *find_aio_ex(uint16 mid) +{ + struct aio_extra *p; + + for( p = aio_list_head; p; p = p->next) { + if (mid == p->mid) { + return p; + } + } + return NULL; +} + +/**************************************************************************** + We can have these many aio buffers in flight. +*****************************************************************************/ + +#define AIO_PENDING_SIZE 10 +static sig_atomic_t signals_received; +static int outstanding_aio_calls; +static uint16 aio_pending_array[AIO_PENDING_SIZE]; + +/**************************************************************************** + Signal handler when an aio request completes. +*****************************************************************************/ + +static void signal_handler(int sig, siginfo_t *info, void *unused) +{ + if (signals_received < AIO_PENDING_SIZE - 1) { + aio_pending_array[signals_received] = *(uint16 *)(info->si_value.sival_ptr); + signals_received++; + } /* Else signal is lost. */ + sys_select_signal(RT_SIGNAL_AIO); +} + +/**************************************************************************** + Is there a signal waiting ? +*****************************************************************************/ + +BOOL aio_finished(void) +{ + return (signals_received != 0); +} + +/**************************************************************************** + Initialize the signal handler for aio read/write. +*****************************************************************************/ + +void initialize_async_io_handler(void) +{ + struct sigaction act; + + ZERO_STRUCT(act); + act.sa_sigaction = signal_handler; + act.sa_flags = SA_SIGINFO; + sigemptyset( &act.sa_mask ); + if (sigaction(RT_SIGNAL_AIO, &act, NULL) != 0) { + DEBUG(0,("Failed to setup RT_SIGNAL_AIO handler\n")); + } + + /* the signal can start off blocked due to a bug in bash */ + BlockSignals(False, RT_SIGNAL_AIO); +} + +/**************************************************************************** + Set up an aio request from a SMBreadX call. +*****************************************************************************/ + +BOOL schedule_aio_read_and_X(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int len_outbuf, + files_struct *fsp, SMB_OFF_T startpos, + size_t smb_maxcnt) +{ + struct aio_extra *aio_ex; + SMB_STRUCT_AIOCB *a; + size_t bufsize; + size_t min_aio_read_size = lp_aio_read_size(SNUM(conn)); + + if (!min_aio_read_size || (smb_maxcnt < min_aio_read_size)) { + /* Too small a read for aio request. */ + DEBUG(10,("schedule_aio_read_and_X: read size (%u) too small " + "for minimum aio_read of %u\n", + (unsigned int)smb_maxcnt, + (unsigned int)min_aio_read_size )); + return False; + } + + /* Only do this on non-chained and non-chaining reads not using the write cache. */ + if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { + return False; + } + + if (outstanding_aio_calls >= AIO_PENDING_SIZE) { + DEBUG(10,("schedule_aio_read_and_X: Already have %d aio activities outstanding.\n", + outstanding_aio_calls )); + 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; + + if ((aio_ex = create_aio_ex_read(fsp, bufsize, SVAL(inbuf,smb_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); + SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ + + a = &aio_ex->acb; + + /* Now set up the aio record for the read call. */ + + a->aio_fildes = fsp->fd; + a->aio_buf = smb_buf(aio_ex->outbuf); + a->aio_nbytes = smb_maxcnt; + a->aio_offset = startpos; + a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; + a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; + a->aio_sigevent.sigev_value.sival_ptr = (void *)&aio_ex->mid; + + if (SMB_VFS_AIO_READ(fsp,a) == -1) { + DEBUG(0,("schedule_aio_read_and_X: aio_read failed. Error %s\n", + strerror(errno) )); + delete_aio_ex(aio_ex); + return False; + } + + DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, offset %.0f, len = %u (mid = %u)\n", + fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt, (unsigned int)aio_ex->mid )); + + srv_defer_sign_response(aio_ex->mid); + outstanding_aio_calls++; + return True; +} + +/**************************************************************************** + Set up an aio request from a SMBwriteX call. +*****************************************************************************/ + +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 aio_extra *aio_ex; + SMB_STRUCT_AIOCB *a; + size_t outbufsize; + BOOL write_through = BITSETW(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)) { + /* Too small a write for aio request. */ + DEBUG(10,("schedule_aio_write_and_X: write size (%u) too small " + "for minimum aio_write of %u\n", + (unsigned int)numtowrite, + (unsigned int)min_aio_write_size )); + return False; + } + + /* Only do this on non-chained and non-chaining reads not using the write cache. */ + if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { + return False; + } + + if (outstanding_aio_calls >= AIO_PENDING_SIZE) { + DEBUG(3,("schedule_aio_write_and_X: Already have %d aio activities outstanding.\n", + outstanding_aio_calls )); + DEBUG(10,("schedule_aio_write_and_X: failed to schedule aio_write for file %s, offset %.0f, len = %u (mid = %u)\n", + fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, (unsigned int)SVAL(inbuf,smb_mid) )); + return False; + } + + outbufsize = smb_len(outbuf) + 4; + if ((aio_ex = create_aio_ex_write(fsp, outbufsize, SVAL(inbuf,smb_mid))) == NULL) { + 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->outbuf, outbuf, outbufsize); + SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ + + a = &aio_ex->acb; + + /* Now set up the aio record for the write call. */ + + a->aio_fildes = fsp->fd; + a->aio_buf = data; /* As we've stolen inbuf this points within inbuf. */ + a->aio_nbytes = numtowrite; + a->aio_offset = startpos; + a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; + a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; + a->aio_sigevent.sigev_value.sival_ptr = (void *)&aio_ex->mid; + + 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; + } + + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) && fsp->aio_write_behind) { + /* Lie to the client and immediately claim we finished the write. */ + SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); + SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); + show_msg(aio_ex->outbuf); + if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { + exit_server("handle_aio_write: send_smb failed."); + } + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write behind for file %s\n", + fsp->fsp_name )); + } else { + srv_defer_sign_response(aio_ex->mid); + } + outstanding_aio_calls++; + + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file %s, \ +offset %.0f, len = %u (mid = %u) outstanding_aio_calls = %d\n", + fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, (unsigned int)aio_ex->mid, outstanding_aio_calls )); + + return True; +} + + +/**************************************************************************** + Complete the read and return the data or error back to the client. + Returns errno or zero if all ok. +*****************************************************************************/ + +static int handle_aio_read_complete(struct aio_extra *aio_ex) +{ + int ret = 0; + int outsize; + char *outbuf = aio_ex->outbuf; + char *data = smb_buf(outbuf); + ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); + + if (nread < 0) { + /* We're relying here on the fact that if the fd is + closed then the aio will complete and aio_return + will return an error. Hopefully this is + true.... JRA. */ + + /* If errno is ECANCELED then don't return anything to the client. */ + if (errno == ECANCELED) { + srv_cancel_sign_response(aio_ex->mid); + return 0; + } + + DEBUG( 3,( "handle_aio_read_complete: file %s nread == -1. Error = %s\n", + aio_ex->fsp->fsp_name, strerror(errno) )); + + outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); + ret = errno; + } else { + outsize = set_message(outbuf,12,nread,False); + SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ + SSVAL(outbuf,smb_vwv5,nread); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); + SSVAL(smb_buf(outbuf),-2,nread); + + 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 ) ); + + } + smb_setlen(outbuf,outsize - 4); + show_msg(outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) { + exit_server("handle_aio_read_complete: send_smb failed."); + } + + DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed for file %s, offset %.0f, len = %u\n", + aio_ex->fsp->fsp_name, (double)aio_ex->acb.aio_offset, (unsigned int)nread )); + + return ret; +} + +/**************************************************************************** + Complete the write and return the data or error back to the client. + Returns errno or zero if all ok. +*****************************************************************************/ + +static int handle_aio_write_complete(struct aio_extra *aio_ex) +{ + int ret = 0; + files_struct *fsp = aio_ex->fsp; + char *outbuf = aio_ex->outbuf; + ssize_t numtowrite = aio_ex->acb.aio_nbytes; + ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); + + if (fsp->aio_write_behind) { + if (nwritten != numtowrite) { + if (nwritten == -1) { + DEBUG(5,("handle_aio_write_complete: aio_write_behind failed ! File %s is corrupt ! Error %s\n", + fsp->fsp_name, strerror(errno) )); + ret = errno; + } else { + DEBUG(0,("handle_aio_write_complete: aio_write_behind failed ! File %s is corrupt ! \ +Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, (int)nwritten )); + ret = EIO; + } + } else { + DEBUG(10,("handle_aio_write_complete: aio_write_behind completed for file %s\n", + fsp->fsp_name )); + } + return 0; + } + + /* We don't need outsize or set_message here as we've already set the + fixed size length when we set up the aio call. */ + + if(nwritten == -1) { + DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. nwritten == %d. Error = %s\n", + fsp->fsp_name, (unsigned int)numtowrite, + (int)nwritten, strerror(errno) )); + + /* If errno is ECANCELED then don't return anything to the client. */ + if (errno == ECANCELED) { + srv_cancel_sign_response(aio_ex->mid); + return 0; + } + + UNIXERROR(ERRHRD,ERRdiskfull); + ret = errno; + } else { + BOOL write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); + + SSVAL(outbuf,smb_vwv2,nwritten); + SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1); + if (nwritten < (ssize_t)numtowrite) { + SCVAL(outbuf,smb_rcls,ERRHRD); + SSVAL(outbuf,smb_err,ERRdiskfull); + } + + DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); + if (lp_syncalways(SNUM(fsp->conn)) || write_through) { + sync_file(fsp->conn,fsp); + } + } + + show_msg(outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) { + exit_server("handle_aio_write: send_smb failed."); + } + + DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed for file %s, offset %.0f, requested %u, written = %u\n", + fsp->fsp_name, (double)aio_ex->acb.aio_offset, (unsigned int)numtowrite, (unsigned int)nwritten )); + + return ret; +} + +/**************************************************************************** + Handle any aio completion. Returns True if finished (and sets *perr if err was non-zero), + False if not. +*****************************************************************************/ + +static BOOL handle_aio_completed(struct aio_extra *aio_ex, int *perr) +{ + int err; + + /* Ensure the operation has really completed. */ + if (SMB_VFS_AIO_ERROR(aio_ex->fsp, &aio_ex->acb) == EINPROGRESS) { + DEBUG(10,( "handle_aio_completed: operation mid %u still in process for file %s\n", + aio_ex->mid, aio_ex->fsp->fsp_name )); + return False; + } + + if (aio_ex->read_req) { + err = handle_aio_read_complete(aio_ex); + } else { + err = handle_aio_write_complete(aio_ex); + } + + if (err) { + *perr = err; /* Only save non-zero errors. */ + } + + return True; +} + +/**************************************************************************** + Handle any aio completion inline. + Returns non-zero errno if fail or zero if all ok. +*****************************************************************************/ + +int process_aio_queue(void) +{ + int i; + int ret = 0; + + BlockSignals(True, RT_SIGNAL_AIO); + + DEBUG(10,("process_aio_queue: signals_received = %d\n", (int)signals_received)); + DEBUG(10,("process_aio_queue: outstanding_aio_calls = %d\n", outstanding_aio_calls)); + + if (!signals_received) { + BlockSignals(False, RT_SIGNAL_AIO); + return 0; + } + + /* Drain all the complete aio_reads. */ + for (i = 0; i < signals_received; i++) { + uint16 mid = aio_pending_array[i]; + files_struct *fsp = NULL; + struct aio_extra *aio_ex = find_aio_ex(mid); + + if (!aio_ex) { + DEBUG(3,("process_aio_queue: Can't find record to match mid %u.\n", + (unsigned int)mid)); + srv_cancel_sign_response(mid); + continue; + } + + fsp = aio_ex->fsp; + if (fsp == NULL) { + /* file was closed whilst I/O was outstanding. Just ignore. */ + DEBUG( 3,( "process_aio_queue: file closed whilst aio outstanding.\n")); + srv_cancel_sign_response(mid); + continue; + } + + if (!handle_aio_completed(aio_ex, &ret)) { + continue; + } + + delete_aio_ex(aio_ex); + } + + outstanding_aio_calls -= signals_received; + signals_received = 0; + BlockSignals(False, RT_SIGNAL_AIO); + return ret; +} + +/**************************************************************************** + We're doing write behind and the client closed the file. Wait up to 30 seconds + (my arbitrary choice) for the aio to complete. Return 0 if all writes completed, + errno to return if not. +*****************************************************************************/ + +#define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 + +BOOL wait_for_aio_completion(files_struct *fsp) +{ + struct aio_extra *aio_ex; + const SMB_STRUCT_AIOCB **aiocb_list; + int aio_completion_count = 0; + time_t start_time = time(NULL); + int seconds_left; + int ret = 0; + + for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; seconds_left >= 0;) { + int err = 0; + int i; + struct timespec ts; + + aio_completion_count = 0; + for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aio_completion_count++; + } + } + + if (!aio_completion_count) { + return ret; + } + + DEBUG(3,("wait_for_aio_completion: waiting for %d aio events to complete.\n", + aio_completion_count )); + + aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, aio_completion_count); + if (!aiocb_list) { + return False; + } + + for( i = 0, aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aiocb_list[i++] = &aio_ex->acb; + } + } + + /* Now wait up to seconds_left for completion. */ + ts.tv_sec = seconds_left; + ts.tv_nsec = 0; + + DEBUG(10,("wait_for_aio_completion: %d events, doing a wait of %d seconds.\n", + aio_completion_count, seconds_left )); + + err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, aio_completion_count, &ts); + + DEBUG(10,("wait_for_aio_completion: returned err = %d, errno = %s\n", + err, strerror(errno) )); + + if (err == -1 && errno == EAGAIN) { + DEBUG(0,("wait_for_aio_completion: aio_suspend timed out waiting for %d events after a wait of %d seconds\n", + aio_completion_count, seconds_left)); + /* Timeout. */ + cancel_aio_by_fsp(fsp); + SAFE_FREE(aiocb_list); + return ret ? ret : EIO; + } + + /* One or more events might have completed - process them if so. */ + for( i = 0; i < aio_completion_count; i++) { + uint16 mid = *(uint16 *)aiocb_list[i]->aio_sigevent.sigev_value.sival_ptr; + + aio_ex = find_aio_ex(mid); + + if (!handle_aio_completed(aio_ex, &err)) { + continue; + } + delete_aio_ex(aio_ex); + } + + SAFE_FREE(aiocb_list); + seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT - (time(NULL) - start_time); + } + + /* We timed out - we don't know why. Return ret if already an error, else EIO. */ + DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting for %d events\n", + aio_completion_count)); + + return ret ? ret : EIO; +} + +/**************************************************************************** + Cancel any outstanding aio requests. The client doesn't care about the reply. +*****************************************************************************/ + +void cancel_aio_by_fsp(files_struct *fsp) +{ + struct aio_extra *aio_ex; + + for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + /* Don't delete the aio_extra record as we may have completed + and don't yet know it. Just do the aio_cancel call and return. */ + SMB_VFS_AIO_CANCEL(fsp,fsp->fd, &aio_ex->acb); + aio_ex->fsp = NULL; /* fsp will be closed when we return. */ + } + } +} + +/**************************************************************************** + 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) +{ + return False; +} + +void initialize_async_io_handler(void) +{ +} + +int process_aio_queue(void) +{ + return False; +} + +BOOL schedule_aio_read_and_X(connection_struct *conn, + char *inbuf, char *outbuf, + int length, int len_outbuf, + files_struct *fsp, SMB_OFF_T startpos, + size_t smb_maxcnt) +{ + return False; +} + +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) +{ + return False; +} + +void cancel_aio_by_fsp(files_struct *fsp) +{ +} + +BOOL wait_for_aio_completion(files_struct *fsp) +{ + return True; +} + +BOOL aio_inbuffer_in_use(char *ptr) +{ + return False; +} +#endif -- cgit From 60e18904e676c1360950cc8342778f5dee4cd8e2 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 13 Jul 2005 00:26:52 +0000 Subject: r8402: allow to build with --enable-aio-support. Guenther (This used to be commit 49351d91c59b2e96ebddb2d721e660dcd90ec815) --- source3/smbd/aio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 7910ee5a7a..d19706ff61 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -242,7 +242,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, /* Now set up the aio record for the read call. */ - a->aio_fildes = fsp->fd; + a->aio_fildes = fsp->fh->fd; a->aio_buf = smb_buf(aio_ex->outbuf); a->aio_nbytes = smb_maxcnt; a->aio_offset = startpos; @@ -321,7 +321,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, /* Now set up the aio record for the write call. */ - a->aio_fildes = fsp->fd; + a->aio_fildes = fsp->fh->fd; a->aio_buf = data; /* As we've stolen inbuf this points within inbuf. */ a->aio_nbytes = numtowrite; a->aio_offset = startpos; @@ -677,7 +677,7 @@ void cancel_aio_by_fsp(files_struct *fsp) if (aio_ex->fsp == fsp) { /* Don't delete the aio_extra record as we may have completed and don't yet know it. Just do the aio_cancel call and return. */ - SMB_VFS_AIO_CANCEL(fsp,fsp->fd, &aio_ex->acb); + SMB_VFS_AIO_CANCEL(fsp,fsp->fh->fd, &aio_ex->acb); aio_ex->fsp = NULL; /* fsp will be closed when we return. */ } } -- cgit From 93954d6390370331731bda5fcf251dc0a796c744 Mon Sep 17 00:00:00 2001 From: James Peach Date: Sat, 3 Sep 2005 07:19:28 +0000 Subject: r9985: Move the all the strict sync logic into file_sync(). (This used to be commit cc680bbe22b8bfc5a1900f11c2cbaeca3a9f9922) --- source3/smbd/aio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index d19706ff61..af1f172b92 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -475,9 +475,7 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, ( } DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); - if (lp_syncalways(SNUM(fsp->conn)) || write_through) { - sync_file(fsp->conn,fsp); - } + sync_file(fsp->conn,fsp, write_through); } show_msg(outbuf); -- cgit From bd9b6a249a6d58f37d2536de998c5b5719c3a85f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Oct 2005 05:26:53 +0000 Subject: r11283: Move to using sival_int from sival_ptr. Part of bug #2922. Jeremy. (This used to be commit f68ff32630ee3b06b69bac59674ecc1496880a47) --- source3/smbd/aio.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index af1f172b92..c71c374043 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -155,7 +155,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) { - aio_pending_array[signals_received] = *(uint16 *)(info->si_value.sival_ptr); + aio_pending_array[signals_received] = info->si_value.sival_int; signals_received++; } /* Else signal is lost. */ sys_select_signal(RT_SIGNAL_AIO); @@ -248,7 +248,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; - a->aio_sigevent.sigev_value.sival_ptr = (void *)&aio_ex->mid; + a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; if (SMB_VFS_AIO_READ(fsp,a) == -1) { DEBUG(0,("schedule_aio_read_and_X: aio_read failed. Error %s\n", @@ -327,7 +327,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; - a->aio_sigevent.sigev_value.sival_ptr = (void *)&aio_ex->mid; + a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; if (SMB_VFS_AIO_WRITE(fsp,a) == -1) { DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. Error %s\n", @@ -642,10 +642,16 @@ BOOL wait_for_aio_completion(files_struct *fsp) /* One or more events might have completed - process them if so. */ for( i = 0; i < aio_completion_count; i++) { - uint16 mid = *(uint16 *)aiocb_list[i]->aio_sigevent.sigev_value.sival_ptr; + uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int; aio_ex = find_aio_ex(mid); + if (!aio_ex) { + DEBUG(0, ("wait_for_aio_completion: mid %u doesn't match an aio record\n", + (unsigned int)mid )); + continue; + } + if (!handle_aio_completed(aio_ex, &err)) { continue; } -- cgit From 5bb49b08f3d79ef9ee17dbbd64ce90dc438d96df Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 18 Dec 2006 04:25:21 +0000 Subject: r20237: Replace exit_server with exit_server_cleanly where appropriate. All send_smb failures should be clean exits. All times when we exit as a matter of policy should also be clean exits. (This used to be commit d6382092e72120a3c89ffe81975e8898d454bf06) --- source3/smbd/aio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index c71c374043..ad25242060 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -345,7 +345,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); show_msg(aio_ex->outbuf); if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { - exit_server("handle_aio_write: send_smb failed."); + exit_server_cleanly("handle_aio_write: send_smb failed."); } DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write behind for file %s\n", fsp->fsp_name )); @@ -408,7 +408,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server("handle_aio_read_complete: send_smb failed."); + exit_server_cleanly("handle_aio_read_complete: send_smb failed."); } DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed for file %s, offset %.0f, len = %u\n", @@ -480,7 +480,7 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, ( show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server("handle_aio_write: send_smb failed."); + exit_server_cleanly("handle_aio_write: send_smb failed."); } DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed for file %s, offset %.0f, requested %u, written = %u\n", -- cgit From f933a9abc2ea9d2dc417b9ba500bbe730be3c1aa Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 5 Jan 2007 11:18:59 +0000 Subject: r20541: Fix some obvious glitches in wait_for_aio_completion. Hmmm. It seems reply_close() at its heart is going to be an async call :-) Volker (This used to be commit 36f60407ae9b430dc5d7f67dd3e7ed8b1dbc93a8) --- source3/smbd/aio.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index ad25242060..0abc20ab7d 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -580,14 +580,13 @@ int process_aio_queue(void) #define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 -BOOL wait_for_aio_completion(files_struct *fsp) +int wait_for_aio_completion(files_struct *fsp) { struct aio_extra *aio_ex; const SMB_STRUCT_AIOCB **aiocb_list; int aio_completion_count = 0; time_t start_time = time(NULL); int seconds_left; - int ret = 0; for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; seconds_left >= 0;) { int err = 0; @@ -602,7 +601,7 @@ BOOL wait_for_aio_completion(files_struct *fsp) } if (!aio_completion_count) { - return ret; + return 0; } DEBUG(3,("wait_for_aio_completion: waiting for %d aio events to complete.\n", @@ -610,7 +609,7 @@ BOOL wait_for_aio_completion(files_struct *fsp) aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, aio_completion_count); if (!aiocb_list) { - return False; + return ENOMEM; } for( i = 0, aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { @@ -637,7 +636,7 @@ BOOL wait_for_aio_completion(files_struct *fsp) /* Timeout. */ cancel_aio_by_fsp(fsp); SAFE_FREE(aiocb_list); - return ret ? ret : EIO; + return EIO; } /* One or more events might have completed - process them if so. */ @@ -666,7 +665,7 @@ BOOL wait_for_aio_completion(files_struct *fsp) DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting for %d events\n", aio_completion_count)); - return ret ? ret : EIO; + return EIO; } /**************************************************************************** -- cgit From bea1025b1aff1b4531f624524e409e601118aa8e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 10 Feb 2007 13:15:58 +0000 Subject: r21269: Reformatting (This used to be commit b2eaa733c52113f53b6ff8aea9fce20ede1e3b1f) --- source3/smbd/aio.c | 240 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 151 insertions(+), 89 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 0abc20ab7d..fd886178f6 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -49,7 +49,8 @@ static struct aio_extra *aio_list_head; of the aio_read call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, uint16 mid) +static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, + uint16 mid) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -77,7 +78,8 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, ui of the aio_write call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen, uint16 mid) +static struct aio_extra *create_aio_ex_write(files_struct *fsp, + size_t outbuflen, uint16 mid) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -92,7 +94,8 @@ static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen SAFE_FREE(aio_ex); return NULL; } - /* Steal the input buffer containing the write data from the main SMB call. */ + /* 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) { SAFE_FREE(aio_ex->outbuf); @@ -100,7 +103,8 @@ static struct aio_extra *create_aio_ex_write(files_struct *fsp, size_t outbuflen return NULL; } - /* aio_ex->inbuf now contains the stolen old InBuf containing the data to write. */ + /* 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; @@ -214,13 +218,16 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, return False; } - /* Only do this on non-chained and non-chaining reads not using the write cache. */ - if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { + /* Only do this on non-chained and non-chaining reads not using the + * write cache. */ + if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) + || (lp_write_cache_size(SNUM(conn)) != 0) ) { return False; } if (outstanding_aio_calls >= AIO_PENDING_SIZE) { - DEBUG(10,("schedule_aio_read_and_X: Already have %d aio activities outstanding.\n", + DEBUG(10,("schedule_aio_read_and_X: Already have %d aio " + "activities outstanding.\n", outstanding_aio_calls )); return False; } @@ -229,7 +236,8 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, checked smb_maxcnt is 128k or less. */ bufsize = PTR_DIFF(smb_buf(outbuf),outbuf) + smb_maxcnt; - if ((aio_ex = create_aio_ex_read(fsp, bufsize, SVAL(inbuf,smb_mid))) == NULL) { + if ((aio_ex = create_aio_ex_read(fsp, bufsize, + SVAL(inbuf,smb_mid))) == NULL) { DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); return False; } @@ -251,14 +259,16 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; if (SMB_VFS_AIO_READ(fsp,a) == -1) { - DEBUG(0,("schedule_aio_read_and_X: aio_read failed. Error %s\n", - strerror(errno) )); + DEBUG(0,("schedule_aio_read_and_X: aio_read failed. " + "Error %s\n", strerror(errno) )); delete_aio_ex(aio_ex); return False; } - DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, offset %.0f, len = %u (mid = %u)\n", - fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt, (unsigned int)aio_ex->mid )); + DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, " + "offset %.0f, len = %u (mid = %u)\n", + fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt, + (unsigned int)aio_ex->mid )); srv_defer_sign_response(aio_ex->mid); outstanding_aio_calls++; @@ -284,28 +294,36 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, if (!min_aio_write_size || (numtowrite < min_aio_write_size)) { /* Too small a write for aio request. */ - DEBUG(10,("schedule_aio_write_and_X: write size (%u) too small " - "for minimum aio_write of %u\n", + DEBUG(10,("schedule_aio_write_and_X: write size (%u) too " + "small for minimum aio_write of %u\n", (unsigned int)numtowrite, (unsigned int)min_aio_write_size )); return False; } - /* Only do this on non-chained and non-chaining reads not using the write cache. */ - if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { + /* Only do this on non-chained and non-chaining reads not using the + * write cache. */ + if (chain_size !=0 || (CVAL(inbuf,smb_vwv0) != 0xFF) + || (lp_write_cache_size(SNUM(conn)) != 0) ) { return False; } if (outstanding_aio_calls >= AIO_PENDING_SIZE) { - DEBUG(3,("schedule_aio_write_and_X: Already have %d aio activities outstanding.\n", + DEBUG(3,("schedule_aio_write_and_X: Already have %d aio " + "activities outstanding.\n", outstanding_aio_calls )); - DEBUG(10,("schedule_aio_write_and_X: failed to schedule aio_write for file %s, offset %.0f, len = %u (mid = %u)\n", - fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, (unsigned int)SVAL(inbuf,smb_mid) )); + DEBUG(10,("schedule_aio_write_and_X: failed to schedule " + "aio_write for file %s, offset %.0f, len = %u " + "(mid = %u)\n", + fsp->fsp_name, (double)startpos, + (unsigned int)numtowrite, + (unsigned int)SVAL(inbuf,smb_mid) )); return False; } outbufsize = smb_len(outbuf) + 4; - if ((aio_ex = create_aio_ex_write(fsp, outbufsize, SVAL(inbuf,smb_mid))) == NULL) { + if ((aio_ex = create_aio_ex_write(fsp, outbufsize, + SVAL(inbuf,smb_mid))) == NULL) { DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n")); return False; } @@ -322,7 +340,8 @@ 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 = data; /* As we've stolen inbuf this points within + * inbuf. */ a->aio_nbytes = numtowrite; a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; @@ -330,8 +349,8 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; if (SMB_VFS_AIO_WRITE(fsp,a) == -1) { - DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. Error %s\n", - strerror(errno) )); + 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; @@ -339,24 +358,29 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, return False; } - if (!write_through && !lp_syncalways(SNUM(fsp->conn)) && fsp->aio_write_behind) { - /* Lie to the client and immediately claim we finished the write. */ + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) + && fsp->aio_write_behind) { + /* Lie to the client and immediately claim we finished the + * write. */ SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); show_msg(aio_ex->outbuf); if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { - exit_server_cleanly("handle_aio_write: send_smb failed."); + exit_server_cleanly("handle_aio_write: send_smb " + "failed."); } - DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write behind for file %s\n", - fsp->fsp_name )); + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " + "behind for file %s\n", fsp->fsp_name )); } else { srv_defer_sign_response(aio_ex->mid); } outstanding_aio_calls++; - DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file %s, \ -offset %.0f, len = %u (mid = %u) outstanding_aio_calls = %d\n", - fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, (unsigned int)aio_ex->mid, outstanding_aio_calls )); + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file " + "%s, offset %.0f, len = %u (mid = %u) " + "outstanding_aio_calls = %d\n", + fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, + (unsigned int)aio_ex->mid, outstanding_aio_calls )); return True; } @@ -381,14 +405,16 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) will return an error. Hopefully this is true.... JRA. */ - /* If errno is ECANCELED then don't return anything to the client. */ + /* If errno is ECANCELED then don't return anything to the + * client. */ if (errno == ECANCELED) { srv_cancel_sign_response(aio_ex->mid); return 0; } - DEBUG( 3,( "handle_aio_read_complete: file %s nread == -1. Error = %s\n", - aio_ex->fsp->fsp_name, strerror(errno) )); + DEBUG( 3,( "handle_aio_read_complete: file %s nread == -1. " + "Error = %s\n", + aio_ex->fsp->fsp_name, strerror(errno) )); outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); ret = errno; @@ -400,19 +426,23 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); SSVAL(smb_buf(outbuf),-2,nread); - 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 ) ); + 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 ) ); } smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("handle_aio_read_complete: send_smb failed."); + exit_server_cleanly("handle_aio_read_complete: send_smb " + "failed."); } - DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed for file %s, offset %.0f, len = %u\n", - aio_ex->fsp->fsp_name, (double)aio_ex->acb.aio_offset, (unsigned int)nread )); + DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed " + "for file %s, offset %.0f, len = %u\n", + aio_ex->fsp->fsp_name, (double)aio_ex->acb.aio_offset, + (unsigned int)nread )); return ret; } @@ -433,17 +463,24 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) if (fsp->aio_write_behind) { if (nwritten != numtowrite) { if (nwritten == -1) { - DEBUG(5,("handle_aio_write_complete: aio_write_behind failed ! File %s is corrupt ! Error %s\n", - fsp->fsp_name, strerror(errno) )); + DEBUG(5,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Error %s\n", + fsp->fsp_name, strerror(errno) )); ret = errno; } else { - DEBUG(0,("handle_aio_write_complete: aio_write_behind failed ! File %s is corrupt ! \ -Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, (int)nwritten )); + DEBUG(0,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Wanted %u bytes but " + "only wrote %d\n", fsp->fsp_name, + (unsigned int)numtowrite, + (int)nwritten )); ret = EIO; } } else { - DEBUG(10,("handle_aio_write_complete: aio_write_behind completed for file %s\n", - fsp->fsp_name )); + DEBUG(10,("handle_aio_write_complete: " + "aio_write_behind completed for file %s\n", + fsp->fsp_name )); } return 0; } @@ -452,11 +489,13 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, ( fixed size length when we set up the aio call. */ if(nwritten == -1) { - DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. nwritten == %d. Error = %s\n", - fsp->fsp_name, (unsigned int)numtowrite, - (int)nwritten, strerror(errno) )); + DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. " + "nwritten == %d. Error = %s\n", + fsp->fsp_name, (unsigned int)numtowrite, + (int)nwritten, strerror(errno) )); - /* If errno is ECANCELED then don't return anything to the client. */ + /* If errno is ECANCELED then don't return anything to the + * client. */ if (errno == ECANCELED) { srv_cancel_sign_response(aio_ex->mid); return 0; @@ -473,8 +512,9 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, ( SCVAL(outbuf,smb_rcls,ERRHRD); SSVAL(outbuf,smb_err,ERRdiskfull); } - - DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten)); + + 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); } @@ -483,15 +523,17 @@ Wanted %u bytes but only wrote %d\n", fsp->fsp_name, (unsigned int)numtowrite, ( exit_server_cleanly("handle_aio_write: send_smb failed."); } - DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed for file %s, offset %.0f, requested %u, written = %u\n", - fsp->fsp_name, (double)aio_ex->acb.aio_offset, (unsigned int)numtowrite, (unsigned int)nwritten )); + DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed " + "for file %s, offset %.0f, requested %u, written = %u\n", + fsp->fsp_name, (double)aio_ex->acb.aio_offset, + (unsigned int)numtowrite, (unsigned int)nwritten )); return ret; } /**************************************************************************** - Handle any aio completion. Returns True if finished (and sets *perr if err was non-zero), - False if not. + Handle any aio completion. Returns True if finished (and sets *perr if err + was non-zero), False if not. *****************************************************************************/ static BOOL handle_aio_completed(struct aio_extra *aio_ex, int *perr) @@ -500,8 +542,9 @@ static BOOL handle_aio_completed(struct aio_extra *aio_ex, int *perr) /* Ensure the operation has really completed. */ if (SMB_VFS_AIO_ERROR(aio_ex->fsp, &aio_ex->acb) == EINPROGRESS) { - DEBUG(10,( "handle_aio_completed: operation mid %u still in process for file %s\n", - aio_ex->mid, aio_ex->fsp->fsp_name )); + DEBUG(10,( "handle_aio_completed: operation mid %u still in " + "process for file %s\n", + aio_ex->mid, aio_ex->fsp->fsp_name )); return False; } @@ -530,8 +573,10 @@ int process_aio_queue(void) BlockSignals(True, RT_SIGNAL_AIO); - DEBUG(10,("process_aio_queue: signals_received = %d\n", (int)signals_received)); - DEBUG(10,("process_aio_queue: outstanding_aio_calls = %d\n", outstanding_aio_calls)); + DEBUG(10,("process_aio_queue: signals_received = %d\n", + (int)signals_received)); + DEBUG(10,("process_aio_queue: outstanding_aio_calls = %d\n", + outstanding_aio_calls)); if (!signals_received) { BlockSignals(False, RT_SIGNAL_AIO); @@ -545,16 +590,18 @@ int process_aio_queue(void) struct aio_extra *aio_ex = find_aio_ex(mid); if (!aio_ex) { - DEBUG(3,("process_aio_queue: Can't find record to match mid %u.\n", - (unsigned int)mid)); + DEBUG(3,("process_aio_queue: Can't find record to " + "match mid %u.\n", (unsigned int)mid)); srv_cancel_sign_response(mid); continue; } fsp = aio_ex->fsp; if (fsp == NULL) { - /* file was closed whilst I/O was outstanding. Just ignore. */ - DEBUG( 3,( "process_aio_queue: file closed whilst aio outstanding.\n")); + /* file was closed whilst I/O was outstanding. Just + * ignore. */ + DEBUG( 3,( "process_aio_queue: file closed whilst " + "aio outstanding.\n")); srv_cancel_sign_response(mid); continue; } @@ -573,9 +620,9 @@ int process_aio_queue(void) } /**************************************************************************** - We're doing write behind and the client closed the file. Wait up to 30 seconds - (my arbitrary choice) for the aio to complete. Return 0 if all writes completed, - errno to return if not. + We're doing write behind and the client closed the file. Wait up to 30 + seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes + completed, errno to return if not. *****************************************************************************/ #define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 @@ -588,7 +635,8 @@ int wait_for_aio_completion(files_struct *fsp) time_t start_time = time(NULL); int seconds_left; - for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; seconds_left >= 0;) { + for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; + seconds_left >= 0;) { int err = 0; int i; struct timespec ts; @@ -604,15 +652,18 @@ int wait_for_aio_completion(files_struct *fsp) return 0; } - DEBUG(3,("wait_for_aio_completion: waiting for %d aio events to complete.\n", - aio_completion_count )); + DEBUG(3,("wait_for_aio_completion: waiting for %d aio events " + "to complete.\n", aio_completion_count )); - aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, aio_completion_count); + aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, + aio_completion_count); if (!aiocb_list) { return ENOMEM; } - for( i = 0, aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + for( i = 0, aio_ex = aio_list_head; + aio_ex; + aio_ex = aio_ex->next) { if (aio_ex->fsp == fsp) { aiocb_list[i++] = &aio_ex->acb; } @@ -622,32 +673,38 @@ int wait_for_aio_completion(files_struct *fsp) ts.tv_sec = seconds_left; ts.tv_nsec = 0; - DEBUG(10,("wait_for_aio_completion: %d events, doing a wait of %d seconds.\n", - aio_completion_count, seconds_left )); + DEBUG(10,("wait_for_aio_completion: %d events, doing a wait " + "of %d seconds.\n", + aio_completion_count, seconds_left )); - err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, aio_completion_count, &ts); + err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, + aio_completion_count, &ts); - DEBUG(10,("wait_for_aio_completion: returned err = %d, errno = %s\n", - err, strerror(errno) )); + DEBUG(10,("wait_for_aio_completion: returned err = %d, " + "errno = %s\n", err, strerror(errno) )); if (err == -1 && errno == EAGAIN) { - DEBUG(0,("wait_for_aio_completion: aio_suspend timed out waiting for %d events after a wait of %d seconds\n", - aio_completion_count, seconds_left)); + DEBUG(0,("wait_for_aio_completion: aio_suspend timed " + "out waiting for %d events after a wait of " + "%d seconds\n", aio_completion_count, + seconds_left)); /* Timeout. */ cancel_aio_by_fsp(fsp); SAFE_FREE(aiocb_list); return EIO; } - /* One or more events might have completed - process them if so. */ + /* One or more events might have completed - process them if + * so. */ for( i = 0; i < aio_completion_count; i++) { uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int; aio_ex = find_aio_ex(mid); if (!aio_ex) { - DEBUG(0, ("wait_for_aio_completion: mid %u doesn't match an aio record\n", - (unsigned int)mid )); + DEBUG(0, ("wait_for_aio_completion: mid %u " + "doesn't match an aio record\n", + (unsigned int)mid )); continue; } @@ -658,12 +715,15 @@ int wait_for_aio_completion(files_struct *fsp) } SAFE_FREE(aiocb_list); - seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT - (time(NULL) - start_time); + seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT + - (time(NULL) - start_time); } - /* We timed out - we don't know why. Return ret if already an error, else EIO. */ - DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting for %d events\n", - aio_completion_count)); + /* We timed out - we don't know why. Return ret if already an error, + * else EIO. */ + DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting " + "for %d events\n", + aio_completion_count)); return EIO; } @@ -678,10 +738,12 @@ void cancel_aio_by_fsp(files_struct *fsp) for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { if (aio_ex->fsp == fsp) { - /* Don't delete the aio_extra record as we may have completed - and don't yet know it. Just do the aio_cancel call and return. */ + /* Don't delete the aio_extra record as we may have + completed and don't yet know it. Just do the + aio_cancel call and return. */ SMB_VFS_AIO_CANCEL(fsp,fsp->fh->fd, &aio_ex->acb); - aio_ex->fsp = NULL; /* fsp will be closed when we return. */ + aio_ex->fsp = NULL; /* fsp will be closed when we + * return. */ } } } -- cgit From 4f5cfc9899295a5c14f734a6c92b3c902ff738d6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 Feb 2007 13:42:48 +0000 Subject: r21277: Fix an off by one error in the signal handler for aio: We can actually receive AIO_PENDING_SIZE signals, not one less. Jeremy I'm not merging this to 3_0_25, I want you to look at it first! Volker (This used to be commit 8fd0ec58360a349826508fc361a943650fdd6694) --- source3/smbd/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index fd886178f6..9425348474 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -158,7 +158,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. */ -- cgit From fe881c3e38bb25a6716d94df362a5580afbdfd8b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 Feb 2007 14:07:50 +0000 Subject: r21278: The main goal of this was to get rid of the NetInBuffer / set_InBuffer. But it turns out that this patch actually speeds up the async writes considerably. I tested writing 100.000 times 65535 bytes with the allowed 10 ops in parallel. Without this patch it took about 32 seconds on my dual-core 1.6GHz laptop. With this patch it dropped to about 26 seconds. I can only explain it by better cache locality, NewInBuffer allocates more than 128k, so we jump around in memory more. Jeremy, please check! Volker (This used to be commit 452d51bc6fd41771b9c41ba6391664513d7cf2cd) --- source3/smbd/aio.c | 54 +++++++++++++----------------------------------------- 1 file changed, 13 insertions(+), 41 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 9425348474..8a9fabf228 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -79,7 +79,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 +96,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 +117,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); } @@ -288,7 +283,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, { struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; - size_t outbufsize; + size_t inbufsize, outbufsize; BOOL write_through = BITSETW(inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); @@ -321,15 +316,16 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, return False; } + inbufsize = smb_len(inbuf) + 4; outbufsize = smb_len(outbuf) + 4; - if ((aio_ex = create_aio_ex_write(fsp, outbufsize, - SVAL(inbuf,smb_mid))) == NULL) { + if (!(aio_ex = create_aio_ex_write(fsp, inbufsize, outbufsize, + SVAL(inbuf,smb_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, inbuf, inbufsize); /* Copy the SMB header already setup in outbuf. */ memcpy(aio_ex->outbuf, outbuf, outbufsize); @@ -340,8 +336,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, inbuf)); a->aio_nbytes = numtowrite; a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; @@ -351,9 +346,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; } @@ -748,21 +740,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) { @@ -805,9 +782,4 @@ BOOL wait_for_aio_completion(files_struct *fsp) { return True; } - -BOOL aio_inbuffer_in_use(char *ptr) -{ - return False; -} #endif -- cgit From d9a29aade0f01df1fa00ccdb8691b02b39bc1d14 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 Feb 2007 14:39:21 +0000 Subject: r21279: Get rid of 'aio write behind', this is broken. It should probably better be integrated with our write cache. Volker (This used to be commit 58bfd168b046a97a895aaa3384fd7af8d077a1d5) --- source3/smbd/aio.c | 156 +---------------------------------------------------- 1 file changed, 1 insertion(+), 155 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 8a9fabf228..a85cf901ae 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -284,7 +284,6 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; size_t inbufsize, outbufsize; - BOOL write_through = BITSETW(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)) { @@ -350,22 +349,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, return False; } - if (!write_through && !lp_syncalways(SNUM(fsp->conn)) - && fsp->aio_write_behind) { - /* Lie to the client and immediately claim we finished the - * write. */ - SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); - SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); - show_msg(aio_ex->outbuf); - if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { - exit_server_cleanly("handle_aio_write: send_smb " - "failed."); - } - DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " - "behind for file %s\n", fsp->fsp_name )); - } else { - srv_defer_sign_response(aio_ex->mid); - } + srv_defer_sign_response(aio_ex->mid); outstanding_aio_calls++; DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file " @@ -452,31 +436,6 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); - if (fsp->aio_write_behind) { - if (nwritten != numtowrite) { - if (nwritten == -1) { - DEBUG(5,("handle_aio_write_complete: " - "aio_write_behind failed ! File %s " - "is corrupt ! Error %s\n", - fsp->fsp_name, strerror(errno) )); - ret = errno; - } else { - DEBUG(0,("handle_aio_write_complete: " - "aio_write_behind failed ! File %s " - "is corrupt ! Wanted %u bytes but " - "only wrote %d\n", fsp->fsp_name, - (unsigned int)numtowrite, - (int)nwritten )); - ret = EIO; - } - } else { - DEBUG(10,("handle_aio_write_complete: " - "aio_write_behind completed for file %s\n", - fsp->fsp_name )); - } - return 0; - } - /* We don't need outsize or set_message here as we've already set the fixed size length when we set up the aio call. */ @@ -611,115 +570,6 @@ int process_aio_queue(void) return ret; } -/**************************************************************************** - We're doing write behind and the client closed the file. Wait up to 30 - seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes - completed, errno to return if not. -*****************************************************************************/ - -#define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 - -int wait_for_aio_completion(files_struct *fsp) -{ - struct aio_extra *aio_ex; - const SMB_STRUCT_AIOCB **aiocb_list; - int aio_completion_count = 0; - time_t start_time = time(NULL); - int seconds_left; - - for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; - seconds_left >= 0;) { - int err = 0; - int i; - struct timespec ts; - - aio_completion_count = 0; - for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { - if (aio_ex->fsp == fsp) { - aio_completion_count++; - } - } - - if (!aio_completion_count) { - return 0; - } - - DEBUG(3,("wait_for_aio_completion: waiting for %d aio events " - "to complete.\n", aio_completion_count )); - - aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, - aio_completion_count); - if (!aiocb_list) { - return ENOMEM; - } - - for( i = 0, aio_ex = aio_list_head; - aio_ex; - aio_ex = aio_ex->next) { - if (aio_ex->fsp == fsp) { - aiocb_list[i++] = &aio_ex->acb; - } - } - - /* Now wait up to seconds_left for completion. */ - ts.tv_sec = seconds_left; - ts.tv_nsec = 0; - - DEBUG(10,("wait_for_aio_completion: %d events, doing a wait " - "of %d seconds.\n", - aio_completion_count, seconds_left )); - - err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, - aio_completion_count, &ts); - - DEBUG(10,("wait_for_aio_completion: returned err = %d, " - "errno = %s\n", err, strerror(errno) )); - - if (err == -1 && errno == EAGAIN) { - DEBUG(0,("wait_for_aio_completion: aio_suspend timed " - "out waiting for %d events after a wait of " - "%d seconds\n", aio_completion_count, - seconds_left)); - /* Timeout. */ - cancel_aio_by_fsp(fsp); - SAFE_FREE(aiocb_list); - return EIO; - } - - /* One or more events might have completed - process them if - * so. */ - for( i = 0; i < aio_completion_count; i++) { - uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int; - - aio_ex = find_aio_ex(mid); - - if (!aio_ex) { - DEBUG(0, ("wait_for_aio_completion: mid %u " - "doesn't match an aio record\n", - (unsigned int)mid )); - continue; - } - - if (!handle_aio_completed(aio_ex, &err)) { - continue; - } - delete_aio_ex(aio_ex); - } - - SAFE_FREE(aiocb_list); - seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT - - (time(NULL) - start_time); - } - - /* We timed out - we don't know why. Return ret if already an error, - * else EIO. */ - DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting " - "for %d events\n", - aio_completion_count)); - - return EIO; -} - /**************************************************************************** Cancel any outstanding aio requests. The client doesn't care about the reply. *****************************************************************************/ @@ -778,8 +628,4 @@ void cancel_aio_by_fsp(files_struct *fsp) { } -BOOL wait_for_aio_completion(files_struct *fsp) -{ - return True; -} #endif -- cgit From dc90cd89a7fef3b0a744ef1873193cf2c9d75cad Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 20:50:49 +0000 Subject: r22389: Start preparing for multiple encryption contexts in the server. Allow server to reflect back to calling client the encryption context that was sent. Jeremy. (This used to be commit b49e90335d1e589916b5ab4992e3c4a2d221ca7e) --- source3/smbd/aio.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index a85cf901ae..6b403e1e36 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -49,8 +49,10 @@ static struct aio_extra *aio_list_head; of the aio_read call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, - uint16 mid) +static struct aio_extra *create_aio_ex_read(files_struct *fsp, + size_t buflen, + uint16 mid, + const char *inbuf) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -66,6 +68,14 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, SAFE_FREE(aio_ex); return NULL; } + /* Save the first 8 bytes of inbuf for possible enc data. */ + aio_ex->inbuf = SMB_MALLOC_ARRAY(char, 8); + if (!aio_ex->inbuf) { + SAFE_FREE(aio_ex->outbuf); + SAFE_FREE(aio_ex); + return NULL; + } + memcpy(aio_ex->inbuf, inbuf, 8); DLIST_ADD(aio_list_head, aio_ex); aio_ex->fsp = fsp; aio_ex->read_req = True; @@ -408,7 +418,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4,aio_ex->inbuf); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " -- cgit From 0829e1ad1c3646efecf50729f493b9ee72ef0517 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 22:40:32 +0000 Subject: r22391: Looks bigger than it is. Make "inbuf" available to all callers of smb_setlen (via set_message() calls). This will allow the server to reflect back the correct encryption context. Jeremy. (This used to be commit 2d80a96120a5fe2fe726f00746d36d85044c4bdb) --- source3/smbd/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 6b403e1e36..0d4760a266 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -418,7 +418,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(outbuf,outsize - 4,aio_ex->inbuf); + smb_setlen(aio_ex->inbuf,outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " -- cgit From e95c34dc6bbfd16f2f0a0cafa3c89ce0c20b8b06 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 20 Apr 2007 12:06:38 +0000 Subject: r22411: Fix the build: Prototype of create_aio_ex_read, set_message and definition of UNIXERROR have changed in r22389 and r22391? to require an additional "inbuf" argument. Some places in smbd/aio.c had not been adapted. This patch fixes the build. Michael (This used to be commit 9de1af6dc835fa12a75bae00935cd605f61217a3) --- source3/smbd/aio.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 0d4760a266..bee6ebc89a 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -242,7 +242,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, bufsize = PTR_DIFF(smb_buf(outbuf),outbuf) + smb_maxcnt; if ((aio_ex = create_aio_ex_read(fsp, bufsize, - SVAL(inbuf,smb_mid))) == NULL) { + SVAL(inbuf,smb_mid), inbuf)) == NULL) { DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); return False; } @@ -382,6 +382,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; + char *inbuf = aio_ex->inbuf; char *data = smb_buf(outbuf); ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); @@ -405,7 +406,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); ret = errno; } else { - outsize = set_message(outbuf,12,nread,False); + outsize = set_message(inbuf,outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -418,7 +419,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(aio_ex->inbuf,outbuf,outsize - 4); + smb_setlen(inbuf,outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " @@ -443,6 +444,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; + char *inbuf = aio_ex->inbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); -- cgit From cc35d1300d487c65f1dc8a275140701ba276adaf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 15 Jun 2007 19:24:04 +0000 Subject: r23508: Fix sync_file() to return NTSTATUS and return this on failure in the write path. Jeremy. (This used to be commit cd3f7dbee809fb40194af0e7509142166e02b252) --- source3/smbd/aio.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index bee6ebc89a..f747cf5c06 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -468,6 +468,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); @@ -478,7 +479,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); -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/smbd/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index f747cf5c06..7a91306fb2 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -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, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/smbd/aio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 7a91306fb2..afef36f61e 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -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 . */ #include "includes.h" -- cgit From 115062e7cea8c265b9f910360ae3e8b9af4c95a8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 25 Jul 2007 18:53:16 +0000 Subject: r24049: Some more 64-bit warnings (This used to be commit eabe796e464e5fe10d0f4cca1362985c529f5a5b) --- source3/smbd/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index afef36f61e..f4c4aaec41 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -415,7 +415,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(inbuf,outbuf,outsize - 4); -- cgit From 12d94f77f919851989da8dbcc12eb632258a2084 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 8 Aug 2007 19:05:30 +0000 Subject: r24279: Remove reply_prep_legacy from reply_write_and_X (This used to be commit f18b7a9a282ebb5c31a89a601798f9a0db51867e) --- source3/smbd/aio.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index f4c4aaec41..0ba857e2e5 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -284,11 +284,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) { struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; @@ -306,7 +305,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; } @@ -320,23 +319,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; } - inbufsize = smb_len(inbuf) + 4; - outbufsize = smb_len(outbuf) + 4; + 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, - SVAL(inbuf,smb_mid)))) { + req->mid))) { DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n")); return False; } /* Copy the SMB header already setup in outbuf. */ - memcpy(aio_ex->inbuf, inbuf, inbufsize); + 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; @@ -344,7 +345,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 = aio_ex->inbuf + (PTR_DIFF(data, 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; @@ -633,11 +634,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; } -- cgit From 921fbb25eb4a6097a1e960abadc4dc4b11d32cf6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 11 Aug 2007 16:28:10 +0000 Subject: r24332: schedule_aio_read_and_X does not need InBuf/OutBuf (This used to be commit 9ad91bd20592850d7b6393e1ac7f0e0919d69668) --- source3/smbd/aio.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 0ba857e2e5..49855796b7 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -51,7 +51,7 @@ static struct aio_extra *aio_list_head; static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, uint16 mid, - const char *inbuf) + const uint8 *inbuf) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -203,8 +203,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) { @@ -224,7 +223,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; } @@ -236,18 +235,19 @@ 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 */ + + bufsize = smb_size + 12 * 2 + smb_maxcnt; - if ((aio_ex = create_aio_ex_read(fsp, bufsize, - SVAL(inbuf,smb_mid), inbuf)) == NULL) { + if (!(aio_ex = create_aio_ex_read(fsp, bufsize, req->mid, + req->inbuf))) { 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((char *)req->inbuf, aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -625,8 +625,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) { -- cgit From e5a951325a6cac8567af3a66de6d2df577508ae4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 15:34:30 -0500 Subject: [GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch. (This used to be commit 5c6c8e1fe93f340005110a7833946191659d88ab) --- source3/smbd/aio.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 161 insertions(+), 20 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 49855796b7..6ee0fe16e1 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -48,10 +48,8 @@ static struct aio_extra *aio_list_head; of the aio_read call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_read(files_struct *fsp, - size_t buflen, - uint16 mid, - const uint8 *inbuf) +static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, + uint16 mid) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -67,14 +65,6 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, SAFE_FREE(aio_ex); return NULL; } - /* Save the first 8 bytes of inbuf for possible enc data. */ - aio_ex->inbuf = SMB_MALLOC_ARRAY(char, 8); - if (!aio_ex->inbuf) { - SAFE_FREE(aio_ex->outbuf); - SAFE_FREE(aio_ex); - return NULL; - } - memcpy(aio_ex->inbuf, inbuf, 8); DLIST_ADD(aio_list_head, aio_ex); aio_ex->fsp = fsp; aio_ex->read_req = True; @@ -240,14 +230,13 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, bufsize = smb_size + 12 * 2 + smb_maxcnt; - if (!(aio_ex = create_aio_ex_read(fsp, bufsize, req->mid, - req->inbuf))) { + if ((aio_ex = create_aio_ex_read(fsp, bufsize, req->mid)) == NULL) { DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); return False; } construct_reply_common((char *)req->inbuf, aio_ex->outbuf); - set_message((char *)req->inbuf, aio_ex->outbuf, 12, 0, True); + set_message(aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -292,6 +281,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; 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)) { @@ -359,7 +349,22 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, return False; } - srv_defer_sign_response(aio_ex->mid); + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) + && fsp->aio_write_behind) { + /* Lie to the client and immediately claim we finished the + * write. */ + SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); + SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); + show_msg(aio_ex->outbuf); + if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { + exit_server_cleanly("handle_aio_write: send_smb " + "failed."); + } + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " + "behind for file %s\n", fsp->fsp_name )); + } else { + srv_defer_sign_response(aio_ex->mid); + } outstanding_aio_calls++; DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file " @@ -382,7 +387,6 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; - char *inbuf = aio_ex->inbuf; char *data = smb_buf(outbuf); ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); @@ -406,7 +410,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); ret = errno; } else { - outsize = set_message(inbuf,outbuf,12,nread,False); + outsize = set_message(outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -419,7 +423,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) (int)aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(inbuf,outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " @@ -444,10 +448,34 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; - char *inbuf = aio_ex->inbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); + if (fsp->aio_write_behind) { + if (nwritten != numtowrite) { + if (nwritten == -1) { + DEBUG(5,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Error %s\n", + fsp->fsp_name, strerror(errno) )); + ret = errno; + } else { + DEBUG(0,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Wanted %u bytes but " + "only wrote %d\n", fsp->fsp_name, + (unsigned int)numtowrite, + (int)nwritten )); + ret = EIO; + } + } else { + DEBUG(10,("handle_aio_write_complete: " + "aio_write_behind completed for file %s\n", + fsp->fsp_name )); + } + return 0; + } + /* We don't need outsize or set_message here as we've already set the fixed size length when we set up the aio call. */ @@ -589,6 +617,115 @@ int process_aio_queue(void) return ret; } +/**************************************************************************** + We're doing write behind and the client closed the file. Wait up to 30 + seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes + completed, errno to return if not. +*****************************************************************************/ + +#define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 + +int wait_for_aio_completion(files_struct *fsp) +{ + struct aio_extra *aio_ex; + const SMB_STRUCT_AIOCB **aiocb_list; + int aio_completion_count = 0; + time_t start_time = time(NULL); + int seconds_left; + + for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; + seconds_left >= 0;) { + int err = 0; + int i; + struct timespec ts; + + aio_completion_count = 0; + for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aio_completion_count++; + } + } + + if (!aio_completion_count) { + return 0; + } + + DEBUG(3,("wait_for_aio_completion: waiting for %d aio events " + "to complete.\n", aio_completion_count )); + + aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, + aio_completion_count); + if (!aiocb_list) { + return ENOMEM; + } + + for( i = 0, aio_ex = aio_list_head; + aio_ex; + aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aiocb_list[i++] = &aio_ex->acb; + } + } + + /* Now wait up to seconds_left for completion. */ + ts.tv_sec = seconds_left; + ts.tv_nsec = 0; + + DEBUG(10,("wait_for_aio_completion: %d events, doing a wait " + "of %d seconds.\n", + aio_completion_count, seconds_left )); + + err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, + aio_completion_count, &ts); + + DEBUG(10,("wait_for_aio_completion: returned err = %d, " + "errno = %s\n", err, strerror(errno) )); + + if (err == -1 && errno == EAGAIN) { + DEBUG(0,("wait_for_aio_completion: aio_suspend timed " + "out waiting for %d events after a wait of " + "%d seconds\n", aio_completion_count, + seconds_left)); + /* Timeout. */ + cancel_aio_by_fsp(fsp); + SAFE_FREE(aiocb_list); + return EIO; + } + + /* One or more events might have completed - process them if + * so. */ + for( i = 0; i < aio_completion_count; i++) { + uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int; + + aio_ex = find_aio_ex(mid); + + if (!aio_ex) { + DEBUG(0, ("wait_for_aio_completion: mid %u " + "doesn't match an aio record\n", + (unsigned int)mid )); + continue; + } + + if (!handle_aio_completed(aio_ex, &err)) { + continue; + } + delete_aio_ex(aio_ex); + } + + SAFE_FREE(aiocb_list); + seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT + - (time(NULL) - start_time); + } + + /* We timed out - we don't know why. Return ret if already an error, + * else EIO. */ + DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting " + "for %d events\n", + aio_completion_count)); + + return EIO; +} + /**************************************************************************** Cancel any outstanding aio requests. The client doesn't care about the reply. *****************************************************************************/ @@ -645,4 +782,8 @@ void cancel_aio_by_fsp(files_struct *fsp) { } +BOOL wait_for_aio_completion(files_struct *fsp) +{ + return True; +} #endif -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/smbd/aio.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 6ee0fe16e1..994b10d6a8 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -35,7 +35,7 @@ struct aio_extra { struct aio_extra *next, *prev; SMB_STRUCT_AIOCB acb; files_struct *fsp; - BOOL read_req; + bool read_req; uint16 mid; char *inbuf; char *outbuf; @@ -163,7 +163,7 @@ static void signal_handler(int sig, siginfo_t *info, void *unused) Is there a signal waiting ? *****************************************************************************/ -BOOL aio_finished(void) +bool aio_finished(void) { return (signals_received != 0); } @@ -192,7 +192,7 @@ void initialize_async_io_handler(void) Set up an aio request from a SMBreadX call. *****************************************************************************/ -BOOL schedule_aio_read_and_X(connection_struct *conn, +bool schedule_aio_read_and_X(connection_struct *conn, struct smb_request *req, files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) @@ -272,7 +272,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, Set up an aio request from a SMBwriteX call. *****************************************************************************/ -BOOL schedule_aio_write_and_X(connection_struct *conn, +bool schedule_aio_write_and_X(connection_struct *conn, struct smb_request *req, files_struct *fsp, char *data, SMB_OFF_T startpos, @@ -281,7 +281,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; size_t inbufsize, outbufsize; - BOOL write_through = BITSETW(req->inbuf+smb_vwv7,0); + 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)) { @@ -495,7 +495,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) UNIXERROR(ERRHRD,ERRdiskfull); ret = errno; } else { - BOOL write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); + bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); NTSTATUS status; SSVAL(outbuf,smb_vwv2,nwritten); @@ -534,7 +534,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) was non-zero), False if not. *****************************************************************************/ -static BOOL handle_aio_completed(struct aio_extra *aio_ex, int *perr) +static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr) { int err; @@ -747,7 +747,7 @@ void cancel_aio_by_fsp(files_struct *fsp) } #else -BOOL aio_finished(void) +bool aio_finished(void) { return False; } @@ -761,7 +761,7 @@ int process_aio_queue(void) return False; } -BOOL schedule_aio_read_and_X(connection_struct *conn, +bool schedule_aio_read_and_X(connection_struct *conn, struct smb_request *req, files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt) @@ -769,7 +769,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, return False; } -BOOL schedule_aio_write_and_X(connection_struct *conn, +bool schedule_aio_write_and_X(connection_struct *conn, struct smb_request *req, files_struct *fsp, char *data, SMB_OFF_T startpos, @@ -782,8 +782,8 @@ void cancel_aio_by_fsp(files_struct *fsp) { } -BOOL wait_for_aio_completion(files_struct *fsp) +int wait_for_aio_completion(files_struct *fsp) { - return True; + return ENOSYS; } #endif -- cgit From afc93255d183eefb68e45b8ec6275f6a62cf9795 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Dec 2007 17:12:36 -0800 Subject: Add SMB encryption. Still fixing client decrypt but negotiation works. Jeremy. (This used to be commit d78045601af787731f0737b8627450018902b104) --- source3/smbd/aio.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 994b10d6a8..f13393b764 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -236,7 +236,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, } construct_reply_common((char *)req->inbuf, aio_ex->outbuf); - set_message(aio_ex->outbuf, 12, 0, True); + srv_set_message((const char *)req->inbuf, aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -387,6 +387,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; + const char *inbuf = aio_ex->inbuf; char *data = smb_buf(outbuf); ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); @@ -407,10 +408,11 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) "Error = %s\n", aio_ex->fsp->fsp_name, strerror(errno) )); - outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); ret = errno; + ERROR_NT(map_nt_error_from_unix(ret)); + outsize = srv_set_message(inbuf,outbuf,0,0,true); } else { - outsize = set_message(outbuf,12,nread,False); + outsize = srv_set_message(inbuf, outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -423,7 +425,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) (int)aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(outbuf,outsize - 4); + _smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " @@ -448,6 +450,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; + const char *inbuf = aio_ex->inbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); @@ -492,8 +495,9 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) return 0; } - UNIXERROR(ERRHRD,ERRdiskfull); ret = errno; + ERROR_BOTH(ERRHRD, ERRdiskfull, map_nt_error_from_unix(ret)); + srv_set_message(inbuf,outbuf,0,0,true); } else { bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); NTSTATUS status; @@ -509,8 +513,9 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) fsp->fnum, (int)numtowrite, (int)nwritten)); status = sync_file(fsp->conn,fsp, write_through); if (!NT_STATUS_IS_OK(status)) { - UNIXERROR(ERRHRD,ERRdiskfull); ret = errno; + ERROR_BOTH(ERRHRD, ERRdiskfull, map_nt_error_from_unix(ret)); + srv_set_message(inbuf,outbuf,0,0,true); DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); } -- cgit From bd7fc51f2d26ba238b68db83106883bfa1fe1d7b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 27 Dec 2007 19:56:44 +0100 Subject: Fix the build (This used to be commit 7fb858b350856d626fed6f062029fcf09b8251e2) --- source3/smbd/aio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index f13393b764..a439c3a4f0 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -496,7 +496,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) } ret = errno; - ERROR_BOTH(ERRHRD, ERRdiskfull, map_nt_error_from_unix(ret)); + ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull); srv_set_message(inbuf,outbuf,0,0,true); } else { bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); @@ -514,7 +514,8 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) status = sync_file(fsp->conn,fsp, write_through); if (!NT_STATUS_IS_OK(status)) { ret = errno; - ERROR_BOTH(ERRHRD, ERRdiskfull, map_nt_error_from_unix(ret)); + ERROR_BOTH(map_nt_error_from_unix(ret), + ERRHRD, ERRdiskfull); srv_set_message(inbuf,outbuf,0,0,true); DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); -- cgit From 9254bb4ef1c3c3a52ea8e935edb0e7a86ec3ea7a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 12:56:23 -0800 Subject: Refactor the crypto code after a very helpful conversation with Volker. Mostly making sure we have data on the incoming packet type, not stored in the smb header. Jeremy. (This used to be commit c4e5a505043965eec77b5bb9bc60957e8f3b97c8) --- source3/smbd/aio.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index a439c3a4f0..bc1761b0fd 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -236,7 +236,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, } construct_reply_common((char *)req->inbuf, aio_ex->outbuf); - srv_set_message((const char *)req->inbuf, aio_ex->outbuf, 12, 0, True); + srv_set_message(aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -356,8 +356,9 @@ bool schedule_aio_write_and_X(connection_struct *conn, SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); show_msg(aio_ex->outbuf); - if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { - exit_server_cleanly("handle_aio_write: send_smb " + if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf, + IS_CONN_ENCRYPTED(fsp->conn))) { + exit_server_cleanly("handle_aio_write: srv_send_smb " "failed."); } DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " @@ -387,7 +388,6 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; - const char *inbuf = aio_ex->inbuf; char *data = smb_buf(outbuf); ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); @@ -410,9 +410,9 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) ret = errno; ERROR_NT(map_nt_error_from_unix(ret)); - outsize = srv_set_message(inbuf,outbuf,0,0,true); + outsize = srv_set_message(outbuf,0,0,true); } else { - outsize = srv_set_message(inbuf, outbuf,12,nread,False); + outsize = srv_set_message(outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -425,10 +425,11 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) (int)aio_ex->acb.aio_nbytes, (int)nread ) ); } - _smb_setlen(outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4); show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("handle_aio_read_complete: send_smb " + if (!srv_send_smb(smbd_server_fd(),outbuf, + IS_CONN_ENCRYPTED(aio_ex->fsp->conn))) { + exit_server_cleanly("handle_aio_read_complete: srv_send_smb " "failed."); } @@ -497,7 +498,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) ret = errno; ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull); - srv_set_message(inbuf,outbuf,0,0,true); + srv_set_message(outbuf,0,0,true); } else { bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); NTSTATUS status; @@ -516,15 +517,15 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) ret = errno; ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull); - srv_set_message(inbuf,outbuf,0,0,true); + srv_set_message(outbuf,0,0,true); DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); } } show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("handle_aio_write: send_smb failed."); + if (!srv_send_smb(smbd_server_fd(),outbuf,IS_CONN_ENCRYPTED(fsp->conn))) { + exit_server_cleanly("handle_aio_write: srv_send_smb failed."); } DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed " -- cgit From 4a056e127ac35d640d899cd8a4735b927aa8d005 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 8 Jan 2008 12:20:51 +0100 Subject: Remove redundant parameter fd from SMB_VFS_AIO_CANCEL(). Michael (This used to be commit 3c997ae0002d4c50e8899600c17ddf74ac61f6f0) --- source3/smbd/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index bc1761b0fd..c8175f77ac 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -746,7 +746,7 @@ void cancel_aio_by_fsp(files_struct *fsp) /* Don't delete the aio_extra record as we may have completed and don't yet know it. Just do the aio_cancel call and return. */ - SMB_VFS_AIO_CANCEL(fsp,fsp->fh->fd, &aio_ex->acb); + SMB_VFS_AIO_CANCEL(fsp, &aio_ex->acb); aio_ex->fsp = NULL; /* fsp will be closed when we * return. */ } -- cgit From bb2c52ad43b12c30315189ebbd722ae3125e457b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 12 Jan 2008 19:12:30 +0100 Subject: Remove an unused variable (This used to be commit 24e719a1d432d5de022ab903457df0dd67c24b85) --- source3/smbd/aio.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index c8175f77ac..9c25f69c97 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -451,7 +451,6 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; - const char *inbuf = aio_ex->inbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); -- cgit From 34a92c6285513acff08c7c9ad67474243559fd2f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 30 Jan 2008 11:11:27 +0100 Subject: Re-enable async I/O for non-TSM systems The logic was wrong: A "SMB_VFS_AIO_FORCE()==False" disabled async I/O, whereas a "SMB_VFS_AIO_FORCE()==True" should enforce it regardless of other settings. Alexander, please check! (This used to be commit 46882ad9927c95caadeb7fb03c1d7491bbe1fb22) --- source3/smbd/aio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 9c25f69c97..86fdfe31b7 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -202,7 +202,8 @@ bool schedule_aio_read_and_X(connection_struct *conn, size_t bufsize; size_t min_aio_read_size = lp_aio_read_size(SNUM(conn)); - if (!min_aio_read_size || (smb_maxcnt < min_aio_read_size)) { + if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size)) + && !SMB_VFS_AIO_FORCE(fsp)) { /* Too small a read for aio request. */ DEBUG(10,("schedule_aio_read_and_X: read size (%u) too small " "for minimum aio_read of %u\n", @@ -284,7 +285,8 @@ bool schedule_aio_write_and_X(connection_struct *conn, 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)) { + if ((!min_aio_write_size || (numtowrite < min_aio_write_size)) + && !SMB_VFS_AIO_FORCE(fsp)) { /* Too small a write for aio request. */ DEBUG(10,("schedule_aio_write_and_X: write size (%u) too " "small for minimum aio_write of %u\n", -- cgit From e12cd305dd9d383058d5bdfa805078735c8018e3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Feb 2008 15:53:57 +0100 Subject: Inform level II oplock holders when we write using AIO Jeremy, please check! (This used to be commit 81d823e026fb332a88b6e1f15030fe49719f2522) --- source3/smbd/aio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 86fdfe31b7..5515582eec 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -351,6 +351,8 @@ bool schedule_aio_write_and_X(connection_struct *conn, return False; } + release_level_2_oplocks_on_change(fsp); + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) && fsp->aio_write_behind) { /* Lie to the client and immediately claim we finished the -- cgit From 4c4c1bfb798aafa5a338a821456bae75e4753da1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Feb 2008 13:27:08 +0100 Subject: Update position information also for AIO Necessary to survive RAW-SEEK with AIO enabled. Jeremy, please check! (This used to be commit e2ca12c2345c0e3916dd09d097b2ba1ce2989fa8) --- source3/smbd/aio.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 5515582eec..8c6eaf1498 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -423,6 +423,9 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1)); SSVAL(smb_buf(outbuf),-2,nread); + aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread; + aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos; + DEBUG( 3, ( "handle_aio_read_complete file %s max=%d " "nread=%d\n", aio_ex->fsp->fsp_name, @@ -524,6 +527,8 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", fsp->fsp_name, nt_errstr(status) )); } + + aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nwritten; } show_msg(outbuf); -- cgit From db9db9cef9b1ec04952ff7f0079cdff1e6ea8016 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Feb 2008 00:01:07 +0100 Subject: AIO on streams does not work (yet...) (This used to be commit 1ba223f202a070a695581e0d7161473a3ebf4332) --- source3/smbd/aio.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 8c6eaf1498..59dd9a9568 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -202,6 +202,12 @@ bool schedule_aio_read_and_X(connection_struct *conn, size_t bufsize; size_t min_aio_read_size = lp_aio_read_size(SNUM(conn)); + if (fsp->base_fsp != NULL) { + /* No AIO on streams yet */ + DEBUG(10, ("AIO on streams not yet supported\n")); + return false; + } + if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size)) && !SMB_VFS_AIO_FORCE(fsp)) { /* Too small a read for aio request. */ @@ -285,6 +291,12 @@ bool schedule_aio_write_and_X(connection_struct *conn, bool write_through = BITSETW(req->inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); + if (fsp->base_fsp != NULL) { + /* No AIO on streams yet */ + DEBUG(10, ("AIO on streams not yet supported\n")); + return false; + } + if ((!min_aio_write_size || (numtowrite < min_aio_write_size)) && !SMB_VFS_AIO_FORCE(fsp)) { /* Too small a write for aio request. */ -- cgit From 21b6a036780ae0c020e199043c25c63fbbf8fa95 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Feb 2008 11:39:57 +0100 Subject: Export aio_request_done() This is for external modules implementing the Posix AIO API that not necessarily depend on the signal mechanism to indicate completion. (This used to be commit 9a069d306bb6f8a2cd51b8ba87b433884942d13f) --- source3/smbd/aio.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 59dd9a9568..78189d32f7 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -150,12 +150,18 @@ static uint16 aio_pending_array[AIO_PENDING_SIZE]; Signal handler when an aio request completes. *****************************************************************************/ -static void signal_handler(int sig, siginfo_t *info, void *unused) +void aio_request_done(uint16_t mid) { if (signals_received < AIO_PENDING_SIZE) { - aio_pending_array[signals_received] = info->si_value.sival_int; + aio_pending_array[signals_received] = mid; signals_received++; - } /* Else signal is lost. */ + } + /* Else signal is lost. */ +} + +static void signal_handler(int sig, siginfo_t *info, void *unused) +{ + aio_request_done(info->si_value.sival_int); sys_select_signal(RT_SIGNAL_AIO); } -- cgit From fcee8fee63fc907f106477a55d651b5a1be692bf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Feb 2008 11:32:22 +0100 Subject: Allow "max mux" async i/o requests In the negprot reply, we allowed the client to issued "max mux" concurrent requests. The OS might allow less, for example AFAIK AIX has a configurable limit of concurrent AIO requests. We will fall back to sync operation for the requests that are too many when aio_read/aio_write return an error. Jeremy, please check! (This used to be commit 8f86f7f25c4eb71bbdfcc6bf2d12eaaae9a8d9ec) --- source3/smbd/aio.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 78189d32f7..2889e3c13f 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -141,10 +141,10 @@ static struct aio_extra *find_aio_ex(uint16 mid) We can have these many aio buffers in flight. *****************************************************************************/ -#define AIO_PENDING_SIZE 10 +static int aio_pending_size; static sig_atomic_t signals_received; static int outstanding_aio_calls; -static uint16 aio_pending_array[AIO_PENDING_SIZE]; +static uint16 *aio_pending_array; /**************************************************************************** Signal handler when an aio request completes. @@ -152,7 +152,7 @@ static uint16 aio_pending_array[AIO_PENDING_SIZE]; void aio_request_done(uint16_t mid) { - if (signals_received < AIO_PENDING_SIZE) { + if (signals_received < aio_pending_size) { aio_pending_array[signals_received] = mid; signals_received++; } @@ -182,6 +182,10 @@ void initialize_async_io_handler(void) { struct sigaction act; + aio_pending_size = lp_maxmux(); + aio_pending_array = SMB_MALLOC_ARRAY(uint16, aio_pending_size); + SMB_ASSERT(aio_pending_array != NULL); + ZERO_STRUCT(act); act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; @@ -231,7 +235,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, return False; } - if (outstanding_aio_calls >= AIO_PENDING_SIZE) { + if (outstanding_aio_calls >= aio_pending_size) { DEBUG(10,("schedule_aio_read_and_X: Already have %d aio " "activities outstanding.\n", outstanding_aio_calls )); @@ -320,7 +324,7 @@ bool schedule_aio_write_and_X(connection_struct *conn, return False; } - if (outstanding_aio_calls >= AIO_PENDING_SIZE) { + if (outstanding_aio_calls >= aio_pending_size) { DEBUG(3,("schedule_aio_write_and_X: Already have %d aio " "activities outstanding.\n", outstanding_aio_calls )); -- cgit From 563a7ccdd9d23ffbd3195c8def82cd4d8d4cb0dc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 24 Aug 2008 13:58:05 +1000 Subject: become root for AIO operations We need to become root for AIO read and write to allow the AIO thread to send a completion signal to the parent process when the IO completes (This used to be commit c548e5c69f9d8bc85a654f4d29d64c735a5e780b) --- source3/smbd/aio.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 2889e3c13f..74275368bd 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -268,12 +268,15 @@ bool schedule_aio_read_and_X(connection_struct *conn, a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; + become_root(); if (SMB_VFS_AIO_READ(fsp,a) == -1) { DEBUG(0,("schedule_aio_read_and_X: aio_read failed. " "Error %s\n", strerror(errno) )); delete_aio_ex(aio_ex); + unbecome_root(); return False; } + unbecome_root(); DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, " "offset %.0f, len = %u (mid = %u)\n", @@ -366,13 +369,16 @@ bool schedule_aio_write_and_X(connection_struct *conn, a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; + become_root(); if (SMB_VFS_AIO_WRITE(fsp,a) == -1) { DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. " "Error %s\n", strerror(errno) )); delete_aio_ex(aio_ex); + unbecome_root(); return False; } - + unbecome_root(); + release_level_2_oplocks_on_change(fsp); if (!write_through && !lp_syncalways(SNUM(fsp->conn)) -- cgit