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"
2011-03-22 16:57:01 +01:00
# include "smbd/smbd.h"
2009-01-08 12:03:45 +01:00
# include "smbd/globals.h"
2011-04-28 17:38:09 +02:00
# include "../lib/util/tevent_ntstatus.h"
2012-07-13 13:41:47 +02:00
# include "../lib/util/tevent_unix.h"
2005-06-27 22:53:56 +00:00
2012-07-12 10:57:47 -07:00
/****************************************************************************
Accessor function to return write_through state .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool aio_write_through_requested ( struct aio_extra * aio_ex )
{
return aio_ex - > write_through ;
}
2005-06-27 22:53:56 +00:00
/****************************************************************************
Create the extended aio struct we must keep around for the lifetime
2008-11-03 21:56:02 +01:00
of the aio call .
2005-06-27 22:53:56 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-03-11 09:17:59 -07:00
struct aio_extra * create_aio_extra ( TALLOC_CTX * mem_ctx ,
files_struct * fsp ,
size_t buflen )
2005-06-27 22:53:56 +00:00
{
2011-06-07 11:44:43 +10:00
struct aio_extra * aio_ex = talloc_zero ( mem_ctx , struct aio_extra ) ;
2005-06-27 22:53:56 +00:00
if ( ! aio_ex ) {
return NULL ;
}
2008-11-03 19:59:11 +01:00
2005-06-27 22:53:56 +00:00
/* 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 . */
2010-06-07 16:26:30 -07:00
if ( buflen ) {
aio_ex - > outbuf = data_blob_talloc ( aio_ex , NULL , buflen ) ;
if ( ! aio_ex - > outbuf . data ) {
TALLOC_FREE ( aio_ex ) ;
return NULL ;
}
2005-06-27 22:53:56 +00:00
}
aio_ex - > fsp = fsp ;
return aio_ex ;
}
2012-07-06 09:37:57 +02:00
struct aio_req_fsp_link {
2023-09-18 14:43:23 -07:00
# ifdef DEVELOPER
struct smbd_server_connection * sconn ;
# endif
2012-07-06 09:37:57 +02:00
files_struct * fsp ;
struct tevent_req * req ;
} ;
static int aio_del_req_from_fsp ( struct aio_req_fsp_link * lnk )
{
unsigned i ;
files_struct * fsp = lnk - > fsp ;
struct tevent_req * req = lnk - > req ;
2023-09-18 14:43:23 -07:00
# ifdef DEVELOPER
struct files_struct * ifsp = NULL ;
bool found = false ;
/*
* When this is called , lnk - > fsp must still exist
* on the files list for this connection . Panic if not .
*/
for ( ifsp = lnk - > sconn - > files ; ifsp ; ifsp = ifsp - > next ) {
if ( ifsp = = fsp ) {
found = true ;
}
}
if ( ! found ) {
smb_panic ( " orphaned lnk on fsp aio list. \n " ) ;
}
# endif
2012-07-06 09:37:57 +02:00
for ( i = 0 ; i < fsp - > num_aio_requests ; i + + ) {
if ( fsp - > aio_requests [ i ] = = req ) {
break ;
}
}
if ( i = = fsp - > num_aio_requests ) {
DEBUG ( 1 , ( " req %p not found in fsp %p \n " , req , fsp ) ) ;
return 0 ;
}
fsp - > num_aio_requests - = 1 ;
fsp - > aio_requests [ i ] = fsp - > aio_requests [ fsp - > num_aio_requests ] ;
2012-07-17 22:24:51 +02:00
if ( fsp - > num_aio_requests = = 0 ) {
2020-03-10 10:55:22 -07:00
TALLOC_FREE ( fsp - > aio_requests ) ;
2012-07-17 22:24:51 +02:00
}
2012-07-06 09:37:57 +02:00
return 0 ;
}
2014-12-04 21:13:33 -08:00
bool aio_add_req_to_fsp ( files_struct * fsp , struct tevent_req * req )
2012-07-06 09:37:57 +02:00
{
size_t array_len ;
struct aio_req_fsp_link * lnk ;
lnk = talloc ( req , struct aio_req_fsp_link ) ;
if ( lnk = = NULL ) {
return false ;
}
array_len = talloc_array_length ( fsp - > aio_requests ) ;
if ( array_len < = fsp - > num_aio_requests ) {
struct tevent_req * * tmp ;
2020-03-11 14:47:50 -07:00
if ( fsp - > num_aio_requests + 10 < 10 ) {
/* Integer wrap. */
TALLOC_FREE ( lnk ) ;
return false ;
}
/*
* Allocate in blocks of 10 so we don ' t allocate
* on every aio request .
*/
2012-07-06 09:37:57 +02:00
tmp = talloc_realloc (
fsp , fsp - > aio_requests , struct tevent_req * ,
2020-03-11 14:47:50 -07:00
fsp - > num_aio_requests + 10 ) ;
2012-07-06 09:37:57 +02:00
if ( tmp = = NULL ) {
TALLOC_FREE ( lnk ) ;
return false ;
}
fsp - > aio_requests = tmp ;
}
fsp - > aio_requests [ fsp - > num_aio_requests ] = req ;
fsp - > num_aio_requests + = 1 ;
lnk - > fsp = fsp ;
lnk - > req = req ;
2023-09-18 14:43:23 -07:00
# ifdef DEVELOPER
lnk - > sconn = fsp - > conn - > sconn ;
# endif
2012-07-06 09:37:57 +02:00
talloc_set_destructor ( lnk , aio_del_req_from_fsp ) ;
return true ;
}
2012-07-13 13:41:47 +02:00
struct pwrite_fsync_state {
struct tevent_context * ev ;
files_struct * fsp ;
bool write_through ;
ssize_t nwritten ;
} ;
static void pwrite_fsync_write_done ( struct tevent_req * subreq ) ;
static void pwrite_fsync_sync_done ( struct tevent_req * subreq ) ;
2022-03-11 09:21:35 -07:00
struct tevent_req * pwrite_fsync_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct files_struct * fsp ,
const void * data ,
size_t n , off_t offset ,
bool write_through )
2012-07-13 13:41:47 +02:00
{
struct tevent_req * req , * subreq ;
struct pwrite_fsync_state * state ;
2020-05-11 18:18:24 +02:00
bool ok ;
2012-07-13 13:41:47 +02:00
req = tevent_req_create ( mem_ctx , & state , struct pwrite_fsync_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > ev = ev ;
state - > fsp = fsp ;
state - > write_through = write_through ;
2020-05-11 18:18:24 +02:00
ok = vfs_valid_pwrite_range ( offset , n ) ;
if ( ! ok ) {
tevent_req_error ( req , EINVAL ) ;
return tevent_req_post ( req , ev ) ;
}
2020-05-11 18:18:24 +02:00
if ( n = = 0 ) {
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
2012-07-13 13:41:47 +02:00
subreq = SMB_VFS_PWRITE_SEND ( state , ev , fsp , data , n , offset ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , pwrite_fsync_write_done , req ) ;
return req ;
}
static void pwrite_fsync_write_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct pwrite_fsync_state * state = tevent_req_data (
req , struct pwrite_fsync_state ) ;
connection_struct * conn = state - > fsp - > conn ;
bool do_sync ;
2016-02-26 10:54:01 +01:00
struct vfs_aio_state vfs_aio_state ;
2012-07-13 13:41:47 +02:00
2016-02-26 10:54:01 +01:00
state - > nwritten = SMB_VFS_PWRITE_RECV ( subreq , & vfs_aio_state ) ;
2012-07-13 13:41:47 +02:00
TALLOC_FREE ( subreq ) ;
if ( state - > nwritten = = - 1 ) {
2016-02-26 10:54:01 +01:00
tevent_req_error ( req , vfs_aio_state . error ) ;
2012-07-13 13:41:47 +02:00
return ;
}
do_sync = ( lp_strict_sync ( SNUM ( conn ) ) & &
2014-02-04 15:09:12 +13:00
( lp_sync_always ( SNUM ( conn ) ) | | state - > write_through ) ) ;
2012-07-13 13:41:47 +02:00
if ( ! do_sync ) {
tevent_req_done ( req ) ;
return ;
}
subreq = SMB_VFS_FSYNC_SEND ( state , state - > ev , state - > fsp ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq , pwrite_fsync_sync_done , req ) ;
}
static void pwrite_fsync_sync_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
2016-02-26 10:54:01 +01:00
int ret ;
struct vfs_aio_state vfs_aio_state ;
2012-07-13 13:41:47 +02:00
2016-02-26 10:54:01 +01:00
ret = SMB_VFS_FSYNC_RECV ( subreq , & vfs_aio_state ) ;
2012-07-13 13:41:47 +02:00
TALLOC_FREE ( subreq ) ;
if ( ret = = - 1 ) {
2016-02-26 10:54:01 +01:00
tevent_req_error ( req , vfs_aio_state . error ) ;
2012-07-13 13:41:47 +02:00
return ;
}
tevent_req_done ( req ) ;
}
2022-03-11 09:21:35 -07:00
ssize_t pwrite_fsync_recv ( struct tevent_req * req , int * perr )
2012-07-13 13:41:47 +02:00
{
struct pwrite_fsync_state * state = tevent_req_data (
req , struct pwrite_fsync_state ) ;
if ( tevent_req_is_unix_error ( req , perr ) ) {
return - 1 ;
}
return state - > nwritten ;
}
2011-11-14 09:52:47 +01:00
bool cancel_smb2_aio ( struct smb_request * smbreq )
{
struct smbd_smb2_request * smb2req = smbreq - > smb2req ;
struct aio_extra * aio_ex = NULL ;
if ( smb2req ) {
aio_ex = talloc_get_type ( smbreq - > async_priv ,
struct aio_extra ) ;
}
if ( aio_ex = = NULL ) {
return false ;
}
if ( aio_ex - > fsp = = NULL ) {
return false ;
}
2012-07-06 09:37:57 +02:00
/*
2018-10-28 19:35:59 +01:00
* We let the aio request run and don ' t try to cancel it which means
* processing of the SMB2 request must continue as normal , cf MS - SMB2
* 3.3 .5 .16 :
*
* If the target request is not successfully canceled , processing of
* the target request MUST continue and no response is sent to the
* cancel request .
2012-07-06 09:37:57 +02:00
*/
2011-11-14 09:52:47 +01:00
2018-10-28 19:35:59 +01:00
return false ;
2011-11-14 09:52:47 +01:00
}
2012-07-02 12:46:03 +02:00
static void aio_pread_smb2_done ( struct tevent_req * req ) ;
2010-06-10 13:20:37 -07:00
/****************************************************************************
Set up an aio request from a SMB2 read call .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS schedule_smb2_aio_read ( connection_struct * conn ,
struct smb_request * smbreq ,
files_struct * fsp ,
2010-12-14 16:32:10 -08:00
TALLOC_CTX * ctx ,
DATA_BLOB * preadbuf ,
2012-04-05 14:53:08 +10:00
off_t startpos ,
2010-06-10 13:20:37 -07:00
size_t smb_maxcnt )
{
struct aio_extra * aio_ex ;
size_t min_aio_read_size = lp_aio_read_size ( SNUM ( conn ) ) ;
2012-07-02 12:46:03 +02:00
struct tevent_req * req ;
2022-11-18 10:50:35 -08:00
bool is_compound = false ;
bool is_last_in_compound = false ;
2020-05-11 18:18:24 +02:00
bool ok ;
ok = vfs_valid_pread_range ( startpos , smb_maxcnt ) ;
if ( ! ok ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2010-06-10 13:20:37 -07:00
2022-02-11 09:37:35 +01:00
if ( fsp_is_alternate_stream ( fsp ) ) {
2010-06-10 13:20:37 -07:00
DEBUG ( 10 , ( " AIO on streams not yet supported \n " ) ) ;
return NT_STATUS_RETRY ;
}
2014-05-01 10:58:51 -07:00
if ( fsp - > op = = NULL ) {
/* No AIO on internal opens. */
return NT_STATUS_RETRY ;
}
2010-06-10 13:20:37 -07:00
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 , ( " smb2: read size (%u) too small "
" for minimum aio_read of %u \n " ,
( unsigned int ) smb_maxcnt ,
( unsigned int ) min_aio_read_size ) ) ;
return NT_STATUS_RETRY ;
}
2022-11-18 10:50:35 -08:00
is_compound = smbd_smb2_is_compound ( smbreq - > smb2req ) ;
is_last_in_compound = smbd_smb2_is_last_in_compound ( smbreq - > smb2req ) ;
if ( is_compound & & ! is_last_in_compound ) {
/*
* Only allow going async if this is the last
* request in a compound .
*/
2017-09-21 12:08:01 -07:00
return NT_STATUS_RETRY ;
}
2010-12-14 16:32:10 -08:00
/* Create the out buffer. */
* preadbuf = data_blob_talloc ( ctx , NULL , smb_maxcnt ) ;
if ( preadbuf - > data = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2010-06-10 13:20:37 -07:00
if ( ! ( aio_ex = create_aio_extra ( smbreq - > smb2req , fsp , 0 ) ) ) {
return NT_STATUS_NO_MEMORY ;
}
2021-11-16 15:00:03 -08:00
init_strict_lock_struct ( fsp ,
fsp - > op - > global - > open_persistent_id ,
( uint64_t ) startpos ,
( uint64_t ) smb_maxcnt ,
READ_LOCK ,
lp_posix_cifsu_locktype ( fsp ) ,
& aio_ex - > lock ) ;
2010-06-10 13:20:37 -07:00
/* Take the lock until the AIO completes. */
2017-07-09 14:34:10 +02:00
if ( ! SMB_VFS_STRICT_LOCK_CHECK ( conn , fsp , & aio_ex - > lock ) ) {
2010-06-10 13:20:37 -07:00
TALLOC_FREE ( aio_ex ) ;
return NT_STATUS_FILE_LOCK_CONFLICT ;
}
2012-07-06 15:05:02 +02:00
aio_ex - > nbyte = smb_maxcnt ;
aio_ex - > offset = startpos ;
2010-06-10 13:20:37 -07:00
2018-12-27 15:18:55 +01:00
req = SMB_VFS_PREAD_SEND ( aio_ex , fsp - > conn - > sconn - > ev_ctx , fsp ,
2012-07-02 12:46:03 +02:00
preadbuf - > data , smb_maxcnt , startpos ) ;
if ( req = = NULL ) {
DEBUG ( 0 , ( " smb2: SMB_VFS_PREAD_SEND failed. "
" Error %s \n " , strerror ( errno ) ) ) ;
2010-06-10 13:20:37 -07:00
TALLOC_FREE ( aio_ex ) ;
return NT_STATUS_RETRY ;
}
2012-07-02 12:46:03 +02:00
tevent_req_set_callback ( req , aio_pread_smb2_done , aio_ex ) ;
2010-06-10 13:20:37 -07:00
2012-07-06 09:37:57 +02:00
if ( ! aio_add_req_to_fsp ( fsp , req ) ) {
DEBUG ( 1 , ( " Could not add req to fsp \n " ) ) ;
TALLOC_FREE ( aio_ex ) ;
return NT_STATUS_RETRY ;
}
2010-06-10 13:20:37 -07:00
/* We don't need talloc_move here as both aio_ex and
* smbreq are children of smbreq - > smb2req . */
aio_ex - > smbreq = smbreq ;
2011-11-14 09:52:47 +01:00
smbreq - > async_priv = aio_ex ;
2010-06-10 13:20:37 -07:00
DEBUG ( 10 , ( " smb2: scheduled aio_read for file %s, "
" offset %.0f, len = %u (mid = %u) \n " ,
fsp_str_dbg ( fsp ) , ( double ) startpos , ( unsigned int ) smb_maxcnt ,
( unsigned int ) aio_ex - > smbreq - > mid ) ) ;
return NT_STATUS_OK ;
}
2012-07-02 12:46:03 +02:00
static void aio_pread_smb2_done ( struct tevent_req * req )
{
struct aio_extra * aio_ex = tevent_req_callback_data (
req , struct aio_extra ) ;
struct tevent_req * subreq = aio_ex - > smbreq - > smb2req - > subreq ;
files_struct * fsp = aio_ex - > fsp ;
NTSTATUS status ;
ssize_t nread ;
2016-02-26 10:54:01 +01:00
struct vfs_aio_state vfs_aio_state = { 0 } ;
2012-07-02 12:46:03 +02:00
2016-02-26 10:54:01 +01:00
nread = SMB_VFS_PREAD_RECV ( req , & vfs_aio_state ) ;
2012-07-02 12:46:03 +02:00
TALLOC_FREE ( req ) ;
DEBUG ( 10 , ( " pread_recv returned %d, err = %s \n " , ( int ) nread ,
2016-02-26 10:54:01 +01:00
( nread = = - 1 ) ? strerror ( vfs_aio_state . error ) : " no error " ) ) ;
2012-07-02 12:46:03 +02:00
/* Common error or success code processing for async or sync
read returns . */
2016-02-26 10:54:01 +01:00
status = smb2_read_complete ( subreq , nread , vfs_aio_state . error ) ;
2012-07-02 12:46:03 +02:00
if ( nread > 0 ) {
2020-09-28 10:32:29 +02:00
fh_set_pos ( fsp - > fh , aio_ex - > offset + nread ) ;
fh_set_position_information ( fsp - > fh ,
fh_get_pos ( fsp - > fh ) ) ;
2012-07-02 12:46:03 +02:00
}
DEBUG ( 10 , ( " smb2: scheduled aio_read completed "
" for file %s, offset %.0f, len = %u "
" (errcode = %d, NTSTATUS = %s) \n " ,
fsp_str_dbg ( aio_ex - > fsp ) ,
2012-07-06 15:05:02 +02:00
( double ) aio_ex - > offset ,
2012-07-02 12:46:03 +02:00
( unsigned int ) nread ,
2016-02-26 10:54:01 +01:00
vfs_aio_state . error , nt_errstr ( status ) ) ) ;
2012-07-02 12:46:03 +02:00
2022-09-01 12:30:57 +02:00
if ( tevent_req_nterror ( subreq , status ) ) {
2012-07-02 12:46:03 +02:00
return ;
}
tevent_req_done ( subreq ) ;
}
2012-07-02 12:46:03 +02:00
static void aio_pwrite_smb2_done ( struct tevent_req * req ) ;
2010-06-10 13:20:37 -07:00
/****************************************************************************
Set up an aio request from a SMB2write call .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS schedule_aio_smb2_write ( connection_struct * conn ,
struct smb_request * smbreq ,
files_struct * fsp ,
uint64_t in_offset ,
DATA_BLOB in_data ,
bool write_through )
{
struct aio_extra * aio_ex = NULL ;
size_t min_aio_write_size = lp_aio_write_size ( SNUM ( conn ) ) ;
2012-07-02 12:46:03 +02:00
struct tevent_req * req ;
2022-11-18 10:45:19 -08:00
bool is_compound = false ;
bool is_last_in_compound = false ;
2010-06-10 13:20:37 -07:00
2022-02-11 09:37:35 +01:00
if ( fsp_is_alternate_stream ( fsp ) ) {
2010-06-10 13:20:37 -07:00
/* No AIO on streams yet */
DEBUG ( 10 , ( " AIO on streams not yet supported \n " ) ) ;
return NT_STATUS_RETRY ;
}
2014-05-01 10:58:51 -07:00
if ( fsp - > op = = NULL ) {
/* No AIO on internal opens. */
return NT_STATUS_RETRY ;
}
2010-06-10 13:20:37 -07:00
if ( ( ! min_aio_write_size | | ( in_data . length < min_aio_write_size ) )
& & ! SMB_VFS_AIO_FORCE ( fsp ) ) {
/* Too small a write for aio request. */
DEBUG ( 10 , ( " smb2: write size (%u) too "
" small for minimum aio_write of %u \n " ,
( unsigned int ) in_data . length ,
( unsigned int ) min_aio_write_size ) ) ;
return NT_STATUS_RETRY ;
}
2022-11-18 10:45:19 -08:00
is_compound = smbd_smb2_is_compound ( smbreq - > smb2req ) ;
is_last_in_compound = smbd_smb2_is_last_in_compound ( smbreq - > smb2req ) ;
if ( is_compound & & ! is_last_in_compound ) {
/*
* Only allow going async if this is the last
* request in a compound .
*/
2017-09-21 12:08:01 -07:00
return NT_STATUS_RETRY ;
}
2013-03-18 12:00:25 -07:00
if ( smbreq - > unread_bytes ) {
/* Can't do async with recvfile. */
return NT_STATUS_RETRY ;
}
2010-06-10 13:20:37 -07:00
if ( ! ( aio_ex = create_aio_extra ( smbreq - > smb2req , fsp , 0 ) ) ) {
return NT_STATUS_NO_MEMORY ;
}
aio_ex - > write_through = write_through ;
2021-11-16 15:00:03 -08:00
init_strict_lock_struct ( fsp ,
fsp - > op - > global - > open_persistent_id ,
in_offset ,
( uint64_t ) in_data . length ,
WRITE_LOCK ,
lp_posix_cifsu_locktype ( fsp ) ,
& aio_ex - > lock ) ;
2010-06-10 13:20:37 -07:00
/* Take the lock until the AIO completes. */
2017-07-09 14:34:10 +02:00
if ( ! SMB_VFS_STRICT_LOCK_CHECK ( conn , fsp , & aio_ex - > lock ) ) {
2010-06-10 13:20:37 -07:00
TALLOC_FREE ( aio_ex ) ;
return NT_STATUS_FILE_LOCK_CONFLICT ;
}
2012-07-06 15:05:02 +02:00
aio_ex - > nbyte = in_data . length ;
aio_ex - > offset = in_offset ;
2010-06-10 13:20:37 -07:00
2018-12-27 15:18:55 +01:00
req = pwrite_fsync_send ( aio_ex , fsp - > conn - > sconn - > ev_ctx , fsp ,
2012-07-13 13:41:47 +02:00
in_data . data , in_data . length , in_offset ,
write_through ) ;
2012-07-02 12:46:03 +02:00
if ( req = = NULL ) {
DEBUG ( 3 , ( " smb2: SMB_VFS_PWRITE_SEND failed. "
" Error %s \n " , strerror ( errno ) ) ) ;
2010-06-10 13:20:37 -07:00
TALLOC_FREE ( aio_ex ) ;
return NT_STATUS_RETRY ;
}
2012-07-02 12:46:03 +02:00
tevent_req_set_callback ( req , aio_pwrite_smb2_done , aio_ex ) ;
2010-06-10 13:20:37 -07:00
2012-07-06 09:37:57 +02:00
if ( ! aio_add_req_to_fsp ( fsp , req ) ) {
DEBUG ( 1 , ( " Could not add req to fsp \n " ) ) ;
TALLOC_FREE ( aio_ex ) ;
return NT_STATUS_RETRY ;
}
2010-06-10 13:20:37 -07:00
/* We don't need talloc_move here as both aio_ex and
* smbreq are children of smbreq - > smb2req . */
aio_ex - > smbreq = smbreq ;
2011-11-14 09:52:47 +01:00
smbreq - > async_priv = aio_ex ;
2010-06-10 13:20:37 -07:00
/* This should actually be improved to span the write. */
contend_level2_oplocks_begin ( fsp , LEVEL2_CONTEND_WRITE ) ;
contend_level2_oplocks_end ( fsp , LEVEL2_CONTEND_WRITE ) ;
/*
* We don ' t want to do write behind due to ownership
* issues of the request structs . Maybe add it if I
* figure those out . JRA .
*/
DEBUG ( 10 , ( " smb2: scheduled aio_write for file "
2018-05-09 09:32:45 -07:00
" %s, offset %.0f, len = %u (mid = %u) \n " ,
2010-06-10 13:20:37 -07:00
fsp_str_dbg ( fsp ) ,
( double ) in_offset ,
( unsigned int ) in_data . length ,
2018-05-09 09:32:45 -07:00
( unsigned int ) aio_ex - > smbreq - > mid ) ) ;
2010-06-10 13:20:37 -07:00
return NT_STATUS_OK ;
}
2012-07-02 12:46:03 +02:00
static void aio_pwrite_smb2_done ( struct tevent_req * req )
{
struct aio_extra * aio_ex = tevent_req_callback_data (
req , struct aio_extra ) ;
2012-07-06 15:05:02 +02:00
ssize_t numtowrite = aio_ex - > nbyte ;
2012-07-02 12:46:03 +02:00
struct tevent_req * subreq = aio_ex - > smbreq - > smb2req - > subreq ;
files_struct * fsp = aio_ex - > fsp ;
NTSTATUS status ;
ssize_t nwritten ;
int err = 0 ;
2012-07-13 13:41:47 +02:00
nwritten = pwrite_fsync_recv ( req , & err ) ;
2012-07-02 12:46:03 +02:00
TALLOC_FREE ( req ) ;
DEBUG ( 10 , ( " pwrite_recv returned %d, err = %s \n " , ( int ) nwritten ,
( nwritten = = - 1 ) ? strerror ( err ) : " no error " ) ) ;
2013-06-20 18:27:39 +02:00
mark_file_modified ( fsp ) ;
2012-07-13 13:41:47 +02:00
status = smb2_write_complete_nosync ( subreq , nwritten , err ) ;
2012-07-02 12:46:03 +02:00
DEBUG ( 10 , ( " smb2: scheduled aio_write completed "
" for file %s, offset %.0f, requested %u, "
" written = %u (errcode = %d, NTSTATUS = %s) \n " ,
fsp_str_dbg ( fsp ) ,
2012-07-06 15:05:02 +02:00
( double ) aio_ex - > offset ,
2012-07-02 12:46:03 +02:00
( unsigned int ) numtowrite ,
( unsigned int ) nwritten ,
err , nt_errstr ( status ) ) ) ;
2022-09-01 12:30:57 +02:00
if ( tevent_req_nterror ( subreq , status ) ) {
2012-07-02 12:46:03 +02:00
return ;
}
tevent_req_done ( subreq ) ;
}