2005-06-27 22:53:56 +00:00
/*
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
2007-07-09 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
2005-06-27 22:53:56 +00:00
( 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
2007-07-10 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-06-27 22:53:56 +00:00
*/
# 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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-04-19 20:50:49 +00:00
static struct aio_extra * create_aio_ex_read ( files_struct * fsp ,
size_t buflen ,
uint16 mid ,
2007-08-11 16:28:10 +00:00
const uint8 * inbuf )
2005-06-27 22:53:56 +00:00
{
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 ;
}
2007-04-19 20:50:49 +00:00
/* 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 ) ;
2005-06-27 22:53:56 +00:00
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-02-10 13:15:58 +00:00
static struct aio_extra * create_aio_ex_write ( files_struct * fsp ,
2007-02-11 14:07:50 +00:00
size_t inbuflen ,
size_t outbuflen ,
uint16 mid )
2005-06-27 22:53:56 +00:00
{
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 ;
}
2007-02-11 14:07:50 +00:00
if ( ! ( aio_ex - > inbuf = SMB_MALLOC_ARRAY ( char , inbuflen ) ) ) {
2005-06-27 22:53:56 +00:00
SAFE_FREE ( aio_ex - > outbuf ) ;
SAFE_FREE ( aio_ex ) ;
return NULL ;
}
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 ) ;
2007-02-11 14:07:50 +00:00
SAFE_FREE ( aio_ex - > inbuf ) ;
2005-06-27 22:53:56 +00:00
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 )
{
2007-02-11 13:42:48 +00:00
if ( signals_received < AIO_PENDING_SIZE ) {
2005-10-25 05:26:53 +00:00
aio_pending_array [ signals_received ] = info - > si_value . sival_int ;
2005-06-27 22:53:56 +00:00
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 ,
2007-08-11 16:28:10 +00:00
struct smb_request * req ,
2005-06-27 22:53:56 +00:00
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 ;
}
2007-02-10 13:15:58 +00:00
/* Only do this on non-chained and non-chaining reads not using the
* write cache . */
2007-08-11 16:28:10 +00:00
if ( chain_size ! = 0 | | ( CVAL ( req - > inbuf , smb_vwv0 ) ! = 0xFF )
2007-02-10 13:15:58 +00:00
| | ( lp_write_cache_size ( SNUM ( conn ) ) ! = 0 ) ) {
2005-06-27 22:53:56 +00:00
return False ;
}
if ( outstanding_aio_calls > = AIO_PENDING_SIZE ) {
2007-02-10 13:15:58 +00:00
DEBUG ( 10 , ( " schedule_aio_read_and_X: Already have %d aio "
" activities outstanding. \n " ,
2005-06-27 22:53:56 +00:00
outstanding_aio_calls ) ) ;
return False ;
}
2007-08-11 16:28:10 +00:00
/* The following is safe from integer wrap as we've already checked
smb_maxcnt is 128 k or less . Wct is 12 for read replies */
bufsize = smb_size + 12 * 2 + smb_maxcnt ;
2005-06-27 22:53:56 +00:00
2007-08-11 16:28:10 +00:00
if ( ! ( aio_ex = create_aio_ex_read ( fsp , bufsize , req - > mid ,
req - > inbuf ) ) ) {
2005-06-27 22:53:56 +00:00
DEBUG ( 10 , ( " schedule_aio_read_and_X: malloc fail. \n " ) ) ;
return False ;
}
2007-08-11 16:28:10 +00:00
construct_reply_common ( ( char * ) req - > inbuf , aio_ex - > outbuf ) ;
set_message ( ( char * ) req - > inbuf , aio_ex - > outbuf , 12 , 0 , True ) ;
2005-06-27 22:53:56 +00:00
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. */
2005-07-13 00:26:52 +00:00
a - > aio_fildes = fsp - > fh - > fd ;
2005-06-27 22:53:56 +00:00
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 ;
2005-10-25 05:26:53 +00:00
a - > aio_sigevent . sigev_value . sival_int = aio_ex - > mid ;
2005-06-27 22:53:56 +00:00
if ( SMB_VFS_AIO_READ ( fsp , a ) = = - 1 ) {
2007-02-10 13:15:58 +00:00
DEBUG ( 0 , ( " schedule_aio_read_and_X: aio_read failed. "
" Error %s \n " , strerror ( errno ) ) ) ;
2005-06-27 22:53:56 +00:00
delete_aio_ex ( aio_ex ) ;
return False ;
}
2007-02-10 13:15:58 +00:00
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 ) ) ;
2005-06-27 22:53:56 +00:00
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 ,
2007-08-08 19:05:30 +00:00
struct smb_request * req ,
files_struct * fsp , char * data ,
SMB_OFF_T startpos ,
size_t numtowrite )
2005-06-27 22:53:56 +00:00
{
struct aio_extra * aio_ex ;
SMB_STRUCT_AIOCB * a ;
2007-02-11 14:07:50 +00:00
size_t inbufsize , outbufsize ;
2005-06-27 22:53:56 +00:00
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. */
2007-02-10 13:15:58 +00:00
DEBUG ( 10 , ( " schedule_aio_write_and_X: write size (%u) too "
" small for minimum aio_write of %u \n " ,
2005-06-27 22:53:56 +00:00
( unsigned int ) numtowrite ,
( unsigned int ) min_aio_write_size ) ) ;
return False ;
}
2007-02-10 13:15:58 +00:00
/* Only do this on non-chained and non-chaining reads not using the
* write cache . */
2007-08-08 19:05:30 +00:00
if ( chain_size ! = 0 | | ( CVAL ( req - > inbuf , smb_vwv0 ) ! = 0xFF )
2007-02-10 13:15:58 +00:00
| | ( lp_write_cache_size ( SNUM ( conn ) ) ! = 0 ) ) {
2005-06-27 22:53:56 +00:00
return False ;
}
if ( outstanding_aio_calls > = AIO_PENDING_SIZE ) {
2007-02-10 13:15:58 +00:00
DEBUG ( 3 , ( " schedule_aio_write_and_X: Already have %d aio "
" activities outstanding. \n " ,
2005-06-27 22:53:56 +00:00
outstanding_aio_calls ) ) ;
2007-02-10 13:15:58 +00:00
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 ,
2007-08-08 19:05:30 +00:00
( unsigned int ) req - > mid ) ) ;
2005-06-27 22:53:56 +00:00
return False ;
}
2007-08-08 19:05:30 +00:00
inbufsize = smb_len ( req - > inbuf ) + 4 ;
reply_outbuf ( req , 6 , 0 ) ;
outbufsize = smb_len ( req - > outbuf ) + 4 ;
2007-02-11 14:07:50 +00:00
if ( ! ( aio_ex = create_aio_ex_write ( fsp , inbufsize , outbufsize ,
2007-08-08 19:05:30 +00:00
req - > mid ) ) ) {
2005-06-27 22:53:56 +00:00
DEBUG ( 0 , ( " schedule_aio_write_and_X: malloc fail. \n " ) ) ;
return False ;
}
2007-02-11 14:07:50 +00:00
/* Copy the SMB header already setup in outbuf. */
2007-08-08 19:05:30 +00:00
memcpy ( aio_ex - > inbuf , req - > inbuf , inbufsize ) ;
2005-06-27 22:53:56 +00:00
/* Copy the SMB header already setup in outbuf. */
2007-08-08 19:05:30 +00:00
memcpy ( aio_ex - > outbuf , req - > outbuf , outbufsize ) ;
TALLOC_FREE ( req - > outbuf ) ;
2005-06-27 22:53:56 +00:00
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. */
2005-07-13 00:26:52 +00:00
a - > aio_fildes = fsp - > fh - > fd ;
2007-08-08 19:05:30 +00:00
a - > aio_buf = aio_ex - > inbuf + ( PTR_DIFF ( data , req - > inbuf ) ) ;
2005-06-27 22:53:56 +00:00
a - > aio_nbytes = numtowrite ;
a - > aio_offset = startpos ;
a - > aio_sigevent . sigev_notify = SIGEV_SIGNAL ;
a - > aio_sigevent . sigev_signo = RT_SIGNAL_AIO ;
2005-10-25 05:26:53 +00:00
a - > aio_sigevent . sigev_value . sival_int = aio_ex - > mid ;
2005-06-27 22:53:56 +00:00
if ( SMB_VFS_AIO_WRITE ( fsp , a ) = = - 1 ) {
2007-02-10 13:15:58 +00:00
DEBUG ( 3 , ( " schedule_aio_wrote_and_X: aio_write failed. "
" Error %s \n " , strerror ( errno ) ) ) ;
2005-06-27 22:53:56 +00:00
delete_aio_ex ( aio_ex ) ;
return False ;
}
2007-02-11 14:39:21 +00:00
srv_defer_sign_response ( aio_ex - > mid ) ;
2005-06-27 22:53:56 +00:00
outstanding_aio_calls + + ;
2007-02-10 13:15:58 +00:00
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 ) ) ;
2005-06-27 22:53:56 +00:00
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 ;
2007-04-20 12:06:38 +00:00
char * inbuf = aio_ex - > inbuf ;
2005-06-27 22:53:56 +00:00
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 . */
2007-02-10 13:15:58 +00:00
/* If errno is ECANCELED then don't return anything to the
* client . */
2005-06-27 22:53:56 +00:00
if ( errno = = ECANCELED ) {
srv_cancel_sign_response ( aio_ex - > mid ) ;
return 0 ;
}
2007-02-10 13:15:58 +00:00
DEBUG ( 3 , ( " handle_aio_read_complete: file %s nread == -1. "
" Error = %s \n " ,
aio_ex - > fsp - > fsp_name , strerror ( errno ) ) ) ;
2005-06-27 22:53:56 +00:00
outsize = ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
ret = errno ;
} else {
2007-04-20 12:06:38 +00:00
outsize = set_message ( inbuf , outbuf , 12 , nread , False ) ;
2005-06-27 22:53:56 +00:00
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 ) ;
2007-02-10 13:15:58 +00:00
DEBUG ( 3 , ( " handle_aio_read_complete file %s max=%d "
" nread=%d \n " ,
aio_ex - > fsp - > fsp_name ,
2007-07-25 18:53:16 +00:00
( int ) aio_ex - > acb . aio_nbytes , ( int ) nread ) ) ;
2005-06-27 22:53:56 +00:00
}
2007-04-20 12:06:38 +00:00
smb_setlen ( inbuf , outbuf , outsize - 4 ) ;
2005-06-27 22:53:56 +00:00
show_msg ( outbuf ) ;
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) ) {
2007-02-10 13:15:58 +00:00
exit_server_cleanly ( " handle_aio_read_complete: send_smb "
" failed. " ) ;
2005-06-27 22:53:56 +00:00
}
2007-02-10 13:15:58 +00:00
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 ) ) ;
2005-06-27 22:53:56 +00:00
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 ;
2007-04-20 12:06:38 +00:00
char * inbuf = aio_ex - > inbuf ;
2005-06-27 22:53:56 +00:00
ssize_t numtowrite = aio_ex - > acb . aio_nbytes ;
ssize_t nwritten = SMB_VFS_AIO_RETURN ( fsp , & aio_ex - > acb ) ;
/* 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 ) {
2007-02-10 13:15:58 +00:00
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 ) ) ) ;
2005-06-27 22:53:56 +00:00
2007-02-10 13:15:58 +00:00
/* If errno is ECANCELED then don't return anything to the
* client . */
2005-06-27 22:53:56 +00:00
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 ) ;
2007-06-15 19:24:04 +00:00
NTSTATUS status ;
2005-06-27 22:53:56 +00:00
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 ) ;
}
2007-02-10 13:15:58 +00:00
DEBUG ( 3 , ( " handle_aio_write: fnum=%d num=%d wrote=%d \n " ,
fsp - > fnum , ( int ) numtowrite , ( int ) nwritten ) ) ;
2007-06-15 19:24:04 +00:00
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 ) ) ) ;
}
2005-06-27 22:53:56 +00:00
}
show_msg ( outbuf ) ;
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) ) {
2006-12-18 04:25:21 +00:00
exit_server_cleanly ( " handle_aio_write: send_smb failed. " ) ;
2005-06-27 22:53:56 +00:00
}
2007-02-10 13:15:58 +00:00
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 ) ) ;
2005-06-27 22:53:56 +00:00
return ret ;
}
/****************************************************************************
2007-02-10 13:15:58 +00:00
Handle any aio completion . Returns True if finished ( and sets * perr if err
was non - zero ) , False if not .
2005-06-27 22:53:56 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 ) {
2007-02-10 13:15:58 +00:00
DEBUG ( 10 , ( " handle_aio_completed: operation mid %u still in "
" process for file %s \n " ,
aio_ex - > mid , aio_ex - > fsp - > fsp_name ) ) ;
2005-06-27 22:53:56 +00:00
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 ) ;
2007-02-10 13:15:58 +00:00
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 ) ) ;
2005-06-27 22:53:56 +00:00
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 ) {
2007-02-10 13:15:58 +00:00
DEBUG ( 3 , ( " process_aio_queue: Can't find record to "
" match mid %u. \n " , ( unsigned int ) mid ) ) ;
2005-06-27 22:53:56 +00:00
srv_cancel_sign_response ( mid ) ;
continue ;
}
fsp = aio_ex - > fsp ;
if ( fsp = = NULL ) {
2007-02-10 13:15:58 +00:00
/* file was closed whilst I/O was outstanding. Just
* ignore . */
DEBUG ( 3 , ( " process_aio_queue: file closed whilst "
" aio outstanding. \n " ) ) ;
2005-06-27 22:53:56 +00:00
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 ;
}
/****************************************************************************
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 ) {
2007-02-10 13:15:58 +00:00
/* 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 . */
2005-07-13 00:26:52 +00:00
SMB_VFS_AIO_CANCEL ( fsp , fsp - > fh - > fd , & aio_ex - > acb ) ;
2007-02-10 13:15:58 +00:00
aio_ex - > fsp = NULL ; /* fsp will be closed when we
* return . */
2005-06-27 22:53:56 +00:00
}
}
}
# 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 ,
2007-08-11 16:28:10 +00:00
struct smb_request * req ,
2005-06-27 22:53:56 +00:00
files_struct * fsp , SMB_OFF_T startpos ,
size_t smb_maxcnt )
{
return False ;
}
BOOL schedule_aio_write_and_X ( connection_struct * conn ,
2007-08-08 19:05:30 +00:00
struct smb_request * req ,
files_struct * fsp , char * data ,
SMB_OFF_T startpos ,
size_t numtowrite )
2005-06-27 22:53:56 +00:00
{
return False ;
}
void cancel_aio_by_fsp ( files_struct * fsp )
{
}
# endif