2004-10-18 11:40:17 +04:00
/*
Unix SMB / CIFS implementation .
POSIX NTVFS backend - async request wait routines
Copyright ( C ) Andrew Tridgell 2004
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-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-10-18 11:40:17 +04: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 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-10-18 11:40:17 +04:00
*/
2004-11-05 10:24:25 +03:00
# include "includes.h"
2005-02-03 14:56:03 +03:00
# include "lib/events/events.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2004-10-18 11:40:17 +04:00
# include "vfs_posix.h"
2020-11-20 17:27:17 +03:00
# include "samba/service_stream.h"
2005-06-05 10:53:07 +04:00
# include "lib/messaging/irpc.h"
2004-10-18 11:40:17 +04:00
/* the context for a single wait instance */
struct pvfs_wait {
2004-11-04 14:28:38 +03:00
struct pvfs_wait * next , * prev ;
struct pvfs_state * pvfs ;
2004-11-05 05:22:07 +03:00
void ( * handler ) ( void * , enum pvfs_wait_notice ) ;
2008-02-21 10:59:21 +03:00
void * private_data ;
2004-10-18 11:40:17 +04:00
int msg_type ;
2011-05-03 04:40:33 +04:00
struct imessaging_context * msg_ctx ;
2008-12-29 22:24:57 +03:00
struct tevent_context * ev ;
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ;
2004-11-05 05:22:07 +03:00
enum pvfs_wait_notice reason ;
2004-10-18 11:40:17 +04:00
} ;
2004-10-18 17:27:22 +04:00
/*
called from the ntvfs layer when we have requested setup of an async
call . this ensures that async calls runs with the right state of
previous ntvfs handlers in the chain ( such as security context )
*/
NTSTATUS pvfs_async_setup ( struct ntvfs_module_context * ntvfs ,
2008-02-21 10:59:21 +03:00
struct ntvfs_request * req , void * private_data )
2004-10-18 17:27:22 +04:00
{
2008-02-21 10:59:21 +03:00
struct pvfs_wait * pwait = talloc_get_type ( private_data ,
struct pvfs_wait ) ;
pwait - > handler ( pwait - > private_data , pwait - > reason ) ;
2004-10-18 17:27:22 +04:00
return NT_STATUS_OK ;
}
2004-10-18 11:40:17 +04:00
/*
receive a completion message for a wait
*/
2011-05-03 04:40:33 +04:00
static void pvfs_wait_dispatch ( struct imessaging_context * msg ,
2019-09-18 19:19:37 +03:00
void * private_data ,
uint32_t msg_type ,
struct server_id src ,
size_t num_fds ,
int * fds ,
DATA_BLOB * data )
2004-10-18 11:40:17 +04:00
{
2008-02-21 10:59:21 +03:00
struct pvfs_wait * pwait = talloc_get_type ( private_data ,
struct pvfs_wait ) ;
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ;
2007-05-15 22:23:58 +04:00
void * p = NULL ;
2004-10-18 11:40:17 +04:00
2019-09-18 19:19:37 +03:00
if ( num_fds ! = 0 ) {
DBG_WARNING ( " Received %zu fds, ignoring message \n " , num_fds ) ;
return ;
}
2004-11-03 13:09:48 +03:00
/* we need to check that this one is for us. See
2011-05-03 04:40:33 +04:00
imessaging_send_ptr ( ) for the other side of this .
2004-11-03 13:09:48 +03:00
*/
2007-05-15 22:23:58 +04:00
if ( data - > length = = sizeof ( void * ) ) {
void * * pp ;
pp = ( void * * ) data - > data ;
p = * pp ;
}
2008-02-21 10:59:21 +03:00
if ( p = = NULL | | p ! = pwait - > private_data ) {
2004-10-18 11:40:17 +04:00
return ;
}
2007-05-15 22:23:58 +04:00
2004-11-05 05:22:07 +03:00
pwait - > reason = PVFS_WAIT_EVENT ;
2004-10-18 17:27:22 +04:00
/* the extra reference here is to ensure that the req
structure is not destroyed when the async request reply is
sent , which would cause problems with the other ntvfs
modules above us */
2009-02-04 10:53:45 +03:00
req = talloc_reference ( msg , pwait - > req ) ;
2004-10-18 17:27:22 +04:00
ntvfs_async_setup ( pwait - > req , pwait ) ;
2007-02-08 06:01:47 +03:00
talloc_unlink ( msg , req ) ;
2004-10-18 11:40:17 +04:00
}
/*
receive a timeout on a message wait
*/
2008-12-29 22:24:57 +03:00
static void pvfs_wait_timeout ( struct tevent_context * ev ,
struct tevent_timer * te , struct timeval t ,
2008-02-21 10:59:21 +03:00
void * private_data )
2004-10-18 11:40:17 +04:00
{
2008-02-21 10:59:21 +03:00
struct pvfs_wait * pwait = talloc_get_type ( private_data ,
struct pvfs_wait ) ;
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req = pwait - > req ;
2004-10-18 17:27:22 +04:00
2004-11-05 05:22:07 +03:00
pwait - > reason = PVFS_WAIT_TIMEOUT ;
2004-10-18 17:27:22 +04:00
2010-05-22 01:14:19 +04:00
req = talloc_reference ( ev , req ) ;
if ( req ! = NULL ) {
ntvfs_async_setup ( req , pwait ) ;
talloc_unlink ( ev , req ) ;
}
2004-10-18 11:40:17 +04:00
}
/*
destroy a pending wait
*/
2006-05-24 11:35:06 +04:00
static int pvfs_wait_destructor ( struct pvfs_wait * pwait )
2004-10-18 11:40:17 +04:00
{
2006-03-29 17:31:30 +04:00
if ( pwait - > msg_type ! = - 1 ) {
2011-05-03 04:40:33 +04:00
imessaging_deregister ( pwait - > msg_ctx , pwait - > msg_type , pwait ) ;
2006-03-29 17:31:30 +04:00
}
2004-11-04 14:28:38 +03:00
DLIST_REMOVE ( pwait - > pvfs - > wait_list , pwait ) ;
2004-10-18 11:40:17 +04:00
return 0 ;
}
/*
setup a request to wait on a message of type msg_type , with a
timeout ( given as an expiry time )
the return value is a handle . To stop waiting talloc_free this
handle .
2006-03-29 17:31:30 +04:00
if msg_type = = - 1 then no message is registered , and it is assumed
that the caller handles any messaging setup needed
2004-10-18 11:40:17 +04:00
*/
2008-02-21 11:02:17 +03:00
struct pvfs_wait * pvfs_wait_message ( struct pvfs_state * pvfs ,
struct ntvfs_request * req ,
int msg_type ,
struct timeval end_time ,
void ( * fn ) ( void * , enum pvfs_wait_notice ) ,
void * private_data )
2004-10-18 11:40:17 +04:00
{
struct pvfs_wait * pwait ;
2005-01-27 10:08:20 +03:00
pwait = talloc ( pvfs , struct pvfs_wait ) ;
2004-10-18 11:40:17 +04:00
if ( pwait = = NULL ) {
return NULL ;
}
2008-02-21 10:59:21 +03:00
pwait - > private_data = private_data ;
2004-10-18 11:40:17 +04:00
pwait - > handler = fn ;
2006-03-15 20:28:46 +03:00
pwait - > msg_ctx = pvfs - > ntvfs - > ctx - > msg_ctx ;
pwait - > ev = pvfs - > ntvfs - > ctx - > event_ctx ;
2004-10-18 11:40:17 +04:00
pwait - > msg_type = msg_type ;
2004-11-07 13:05:35 +03:00
pwait - > req = talloc_reference ( pwait , req ) ;
2004-11-04 14:28:38 +03:00
pwait - > pvfs = pvfs ;
2004-10-18 11:40:17 +04:00
2006-03-21 14:39:48 +03:00
if ( ! timeval_is_zero ( & end_time ) ) {
/* setup a timer */
2010-05-25 23:27:41 +04:00
tevent_add_timer ( pwait - > ev , pwait , end_time , pvfs_wait_timeout , pwait ) ;
2006-03-21 14:39:48 +03:00
}
2004-10-18 11:40:17 +04:00
/* register with the messaging subsystem for this message
type */
2006-03-29 17:31:30 +04:00
if ( msg_type ! = - 1 ) {
2011-05-03 04:40:33 +04:00
imessaging_register ( pwait - > msg_ctx ,
2006-03-29 17:31:30 +04:00
pwait ,
msg_type ,
pvfs_wait_dispatch ) ;
}
2004-10-18 11:40:17 +04:00
/* tell the main smb server layer that we will be replying
asynchronously */
2004-10-29 01:48:53 +04:00
req - > async_states - > state | = NTVFS_ASYNC_STATE_ASYNC ;
2004-10-18 11:40:17 +04:00
2004-11-04 14:28:38 +03:00
DLIST_ADD ( pvfs - > wait_list , pwait ) ;
2004-10-18 11:40:17 +04:00
/* make sure we cleanup the timer and message handler */
talloc_set_destructor ( pwait , pvfs_wait_destructor ) ;
return pwait ;
}
2004-11-04 14:28:38 +03:00
/*
cancel an outstanding async request
*/
2006-03-10 17:31:17 +03:00
NTSTATUS pvfs_cancel ( struct ntvfs_module_context * ntvfs , struct ntvfs_request * req )
2004-11-04 14:28:38 +03:00
{
2009-02-04 10:52:41 +03:00
struct pvfs_state * pvfs = talloc_get_type ( ntvfs - > private_data ,
struct pvfs_state ) ;
2004-11-04 14:28:38 +03:00
struct pvfs_wait * pwait ;
2006-03-16 21:54:19 +03:00
2004-11-04 14:28:38 +03:00
for ( pwait = pvfs - > wait_list ; pwait ; pwait = pwait - > next ) {
2006-07-11 22:15:42 +04:00
if ( pwait - > req = = req ) {
2004-11-05 05:22:07 +03:00
/* trigger a cancel on the request */
pwait - > reason = PVFS_WAIT_CANCEL ;
ntvfs_async_setup ( pwait - > req , pwait ) ;
2004-11-04 14:28:38 +03:00
return NT_STATUS_OK ;
}
}
2005-07-04 09:08:27 +04:00
return NT_STATUS_DOS ( ERRDOS , ERRcancelviolation ) ;
2004-11-04 14:28:38 +03:00
}