2013-02-07 18:26:37 +04:00
/*
Unix SMB / CIFS implementation .
smbd scavenger daemon
Copyright ( C ) Gregor Beck 2013
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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "messages.h"
# include "serverid.h"
# include "smbd/globals.h"
2021-10-26 14:48:28 +03:00
# include "smbd/smbXsrv_open.h"
2013-02-07 18:26:37 +04:00
# include "smbd/scavenger.h"
2020-10-28 14:09:39 +03:00
# include "locking/share_mode_lock.h"
2020-11-03 15:25:57 +03:00
# include "locking/leases_db.h"
2013-02-07 18:26:37 +04:00
# include "locking/proto.h"
2020-11-03 15:25:57 +03:00
# include "librpc/gen_ndr/open_files.h"
2017-01-01 23:00:55 +03:00
# include "lib/util/server_id.h"
2013-02-07 18:26:37 +04:00
# include "lib/util/util_process.h"
2015-10-29 16:27:32 +03:00
# include "lib/util/sys_rw_data.h"
2013-02-07 18:26:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_SCAVENGER
struct smbd_scavenger_state {
struct tevent_context * ev ;
struct messaging_context * msg ;
struct server_id parent_id ;
struct server_id * scavenger_id ;
bool am_scavenger ;
} ;
static struct smbd_scavenger_state * smbd_scavenger_state = NULL ;
struct scavenger_message {
struct file_id file_id ;
uint64_t open_persistent_id ;
NTTIME until ;
} ;
static int smbd_scavenger_main ( struct smbd_scavenger_state * state )
{
2015-04-28 14:30:58 +03:00
struct server_id_buf tmp1 , tmp2 ;
2013-02-07 18:26:37 +04:00
DEBUG ( 10 , ( " scavenger: %s started, parent: %s \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( * state - > scavenger_id , & tmp1 ) ,
server_id_str_buf ( state - > parent_id , & tmp2 ) ) ) ;
2013-02-07 18:26:37 +04:00
while ( true ) {
TALLOC_CTX * frame = talloc_stackframe ( ) ;
int ret ;
ret = tevent_loop_once ( state - > ev ) ;
if ( ret ! = 0 ) {
DEBUG ( 2 , ( " tevent_loop_once failed: %s \n " ,
strerror ( errno ) ) ) ;
TALLOC_FREE ( frame ) ;
return 1 ;
}
DEBUG ( 10 , ( " scavenger: %s event loop iteration \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( * state - > scavenger_id , & tmp1 ) ) ) ;
2013-02-07 18:26:37 +04:00
TALLOC_FREE ( frame ) ;
}
return 0 ;
}
static void smbd_scavenger_done ( struct tevent_context * event_ctx , struct tevent_fd * fde ,
uint16_t flags , void * private_data )
{
struct smbd_scavenger_state * state = talloc_get_type_abort (
private_data , struct smbd_scavenger_state ) ;
2015-04-28 14:30:58 +03:00
struct server_id_buf tmp ;
2013-02-07 18:26:37 +04:00
DEBUG ( 2 , ( " scavenger: %s died \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( * state - > scavenger_id , & tmp ) ) ) ;
2013-02-07 18:26:37 +04:00
TALLOC_FREE ( state - > scavenger_id ) ;
}
static void smbd_scavenger_parent_dead ( struct tevent_context * event_ctx ,
struct tevent_fd * fde ,
uint16_t flags , void * private_data )
{
struct smbd_scavenger_state * state = talloc_get_type_abort (
private_data , struct smbd_scavenger_state ) ;
2015-04-28 14:30:58 +03:00
struct server_id_buf tmp1 , tmp2 ;
2013-02-07 18:26:37 +04:00
DEBUG ( 2 , ( " scavenger: %s parent %s died \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( * state - > scavenger_id , & tmp1 ) ,
server_id_str_buf ( state - > parent_id , & tmp2 ) ) ) ;
2013-02-07 18:26:37 +04:00
2023-07-05 12:33:58 +03:00
exit_server_cleanly ( " smbd_scavenger_parent_dead " ) ;
2013-02-07 18:26:37 +04:00
}
static void scavenger_sig_term_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
exit_server_cleanly ( " termination signal " ) ;
}
static void scavenger_setup_sig_term_handler ( struct tevent_context * ev_ctx )
{
struct tevent_signal * se ;
se = tevent_add_signal ( ev_ctx ,
ev_ctx ,
SIGTERM , 0 ,
scavenger_sig_term_handler ,
NULL ) ;
if ( se = = NULL ) {
exit_server ( " failed to setup SIGTERM handler " ) ;
}
}
static bool smbd_scavenger_running ( struct smbd_scavenger_state * state )
{
if ( state - > scavenger_id = = NULL ) {
return false ;
}
return serverid_exists ( state - > scavenger_id ) ;
}
static int smbd_scavenger_server_id_destructor ( struct server_id * id )
{
return 0 ;
}
static bool scavenger_say_hello ( int fd , struct server_id self )
{
2015-10-29 16:27:32 +03:00
ssize_t ret ;
2015-04-28 14:30:58 +03:00
struct server_id_buf tmp ;
2013-02-07 18:26:37 +04:00
2015-10-29 16:27:32 +03:00
ret = write_data ( fd , & self , sizeof ( self ) ) ;
if ( ret = = - 1 ) {
DEBUG ( 2 , ( " Failed to write to pipe: %s \n " , strerror ( errno ) ) ) ;
return false ;
}
if ( ret < sizeof ( self ) ) {
DBG_WARNING ( " Could not write serverid \n " ) ;
return false ;
2013-02-07 18:26:37 +04:00
}
DEBUG ( 4 , ( " scavenger_say_hello: self[%s] \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( self , & tmp ) ) ) ;
2013-02-07 18:26:37 +04:00
return true ;
}
static bool scavenger_wait_hello ( int fd , struct server_id * child )
{
2015-04-28 14:30:58 +03:00
struct server_id_buf tmp ;
2015-10-29 16:27:32 +03:00
ssize_t ret ;
2013-02-07 18:26:37 +04:00
2015-10-29 16:27:32 +03:00
ret = read_data ( fd , child , sizeof ( struct server_id ) ) ;
if ( ret = = - 1 ) {
DEBUG ( 2 , ( " Failed to read from pipe: %s \n " ,
strerror ( errno ) ) ) ;
return false ;
}
if ( ret < sizeof ( struct server_id ) ) {
DBG_WARNING ( " Could not read serverid \n " ) ;
return false ;
2013-02-07 18:26:37 +04:00
}
DEBUG ( 4 , ( " scavenger_say_hello: child[%s] \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( * child , & tmp ) ) ) ;
2013-02-07 18:26:37 +04:00
return true ;
}
static bool smbd_scavenger_start ( struct smbd_scavenger_state * state )
{
struct server_id self = messaging_server_id ( state - > msg ) ;
struct tevent_fd * fde = NULL ;
int fds [ 2 ] ;
int ret ;
bool ok ;
SMB_ASSERT ( server_id_equal ( & state - > parent_id , & self ) ) ;
if ( smbd_scavenger_running ( state ) ) {
2015-04-28 14:30:58 +03:00
struct server_id_buf tmp ;
2013-02-07 18:26:37 +04:00
DEBUG ( 10 , ( " scavenger %s already running \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( * state - > scavenger_id ,
& tmp ) ) ) ;
2013-02-07 18:26:37 +04:00
return true ;
}
if ( state - > scavenger_id ! = NULL ) {
2015-04-28 14:30:58 +03:00
struct server_id_buf tmp ;
2013-02-07 18:26:37 +04:00
DEBUG ( 10 , ( " scavenger zombie %s, cleaning up \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( * state - > scavenger_id ,
& tmp ) ) ) ;
2013-02-07 18:26:37 +04:00
TALLOC_FREE ( state - > scavenger_id ) ;
}
state - > scavenger_id = talloc_zero ( state , struct server_id ) ;
if ( state - > scavenger_id = = NULL ) {
DEBUG ( 2 , ( " Out of memory \n " ) ) ;
goto fail ;
}
talloc_set_destructor ( state - > scavenger_id ,
smbd_scavenger_server_id_destructor ) ;
ret = socketpair ( AF_UNIX , SOCK_STREAM , 0 , fds ) ;
if ( ret = = - 1 ) {
2023-08-07 07:50:39 +03:00
DEBUG ( 2 , ( " socketpair failed: %s \n " , strerror ( errno ) ) ) ;
2013-02-07 18:26:37 +04:00
goto fail ;
}
smb_set_close_on_exec ( fds [ 0 ] ) ;
smb_set_close_on_exec ( fds [ 1 ] ) ;
ret = fork ( ) ;
if ( ret = = - 1 ) {
int err = errno ;
close ( fds [ 0 ] ) ;
close ( fds [ 1 ] ) ;
2023-08-07 07:50:39 +03:00
DEBUG ( 0 , ( " fork failed: %s \n " , strerror ( err ) ) ) ;
2013-02-07 18:26:37 +04:00
goto fail ;
}
if ( ret = = 0 ) {
/* child */
NTSTATUS status ;
close ( fds [ 0 ] ) ;
2015-09-23 21:14:05 +03:00
status = smbd_reinit_after_fork ( state - > msg , state - > ev ,
2022-12-03 18:59:39 +03:00
true ) ;
2013-02-07 18:26:37 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " reinit_after_fork failed: %s \n " ,
nt_errstr ( status ) ) ) ;
exit_server ( " reinit_after_fork failed " ) ;
return false ;
}
2022-12-03 18:56:20 +03:00
process_set_title ( " smbd-scavenger " , " scavenger " ) ;
2019-12-03 15:22:06 +03:00
reopen_logs ( ) ;
2013-02-07 18:26:37 +04:00
state - > am_scavenger = true ;
* state - > scavenger_id = messaging_server_id ( state - > msg ) ;
scavenger_setup_sig_term_handler ( state - > ev ) ;
ok = scavenger_say_hello ( fds [ 1 ] , * state - > scavenger_id ) ;
if ( ! ok ) {
DEBUG ( 2 , ( " scavenger_say_hello failed \n " ) ) ;
exit_server ( " scavenger_say_hello failed " ) ;
return false ;
}
fde = tevent_add_fd ( state - > ev , state - > scavenger_id ,
fds [ 1 ] , TEVENT_FD_READ ,
smbd_scavenger_parent_dead , state ) ;
if ( fde = = NULL ) {
DEBUG ( 2 , ( " tevent_add_fd(smbd_scavenger_parent_dead) "
" failed \n " ) ) ;
exit_server ( " tevent_add_fd(smbd_scavenger_parent_dead) "
" failed " ) ;
return false ;
}
tevent_fd_set_auto_close ( fde ) ;
ret = smbd_scavenger_main ( state ) ;
DEBUG ( 10 , ( " scavenger ended: %d \n " , ret ) ) ;
exit_server_cleanly ( " scavenger ended " ) ;
return false ;
}
/* parent */
close ( fds [ 1 ] ) ;
ok = scavenger_wait_hello ( fds [ 0 ] , state - > scavenger_id ) ;
if ( ! ok ) {
close ( fds [ 0 ] ) ;
goto fail ;
}
fde = tevent_add_fd ( state - > ev , state - > scavenger_id ,
fds [ 0 ] , TEVENT_FD_READ ,
smbd_scavenger_done , state ) ;
if ( fde = = NULL ) {
close ( fds [ 0 ] ) ;
goto fail ;
}
tevent_fd_set_auto_close ( fde ) ;
return true ;
fail :
TALLOC_FREE ( state - > scavenger_id ) ;
return false ;
}
static void scavenger_add_timer ( struct smbd_scavenger_state * state ,
struct scavenger_message * msg ) ;
static void smbd_scavenger_msg ( struct messaging_context * msg_ctx ,
void * private_data ,
uint32_t msg_type ,
struct server_id src ,
DATA_BLOB * data )
{
struct smbd_scavenger_state * state =
talloc_get_type_abort ( private_data ,
struct smbd_scavenger_state ) ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct server_id self = messaging_server_id ( msg_ctx ) ;
struct scavenger_message * msg = NULL ;
2015-04-28 14:30:58 +03:00
struct server_id_buf tmp1 , tmp2 ;
2013-02-07 18:26:37 +04:00
DEBUG ( 10 , ( " smbd_scavenger_msg: %s got message from %s \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( self , & tmp1 ) ,
server_id_str_buf ( src , & tmp2 ) ) ) ;
2013-02-07 18:26:37 +04:00
if ( server_id_equal ( & state - > parent_id , & self ) ) {
NTSTATUS status ;
if ( ! smbd_scavenger_running ( state ) & &
! smbd_scavenger_start ( state ) )
{
DEBUG ( 2 , ( " Failed to start scavenger \n " ) ) ;
goto done ;
}
DEBUG ( 10 , ( " forwarding message to scavenger \n " ) ) ;
status = messaging_send ( msg_ctx ,
* state - > scavenger_id , msg_type , data ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " forwarding message to scavenger failed: "
" %s \n " , nt_errstr ( status ) ) ) ;
goto done ;
}
goto done ;
}
if ( ! state - > am_scavenger ) {
DEBUG ( 10 , ( " im not the scavenger: ignore message \n " ) ) ;
goto done ;
}
if ( ! server_id_equal ( & state - > parent_id , & src ) ) {
DEBUG ( 10 , ( " scavenger: ignore spurious message \n " ) ) ;
goto done ;
}
DEBUG ( 10 , ( " scavenger: got a message \n " ) ) ;
msg = ( struct scavenger_message * ) data - > data ;
scavenger_add_timer ( state , msg ) ;
done :
talloc_free ( frame ) ;
}
bool smbd_scavenger_init ( TALLOC_CTX * mem_ctx ,
struct messaging_context * msg ,
struct tevent_context * ev )
{
struct smbd_scavenger_state * state ;
NTSTATUS status ;
if ( smbd_scavenger_state ) {
DEBUG ( 10 , ( " smbd_scavenger_init called again \n " ) ) ;
return true ;
}
state = talloc_zero ( mem_ctx , struct smbd_scavenger_state ) ;
if ( state = = NULL ) {
DEBUG ( 2 , ( " Out of memory \n " ) ) ;
return false ;
}
state - > msg = msg ;
state - > ev = ev ;
state - > parent_id = messaging_server_id ( msg ) ;
status = messaging_register ( msg , state , MSG_SMB_SCAVENGER ,
smbd_scavenger_msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " failed to register message handler: %s \n " ,
nt_errstr ( status ) ) ) ;
goto fail ;
}
smbd_scavenger_state = state ;
return true ;
fail :
talloc_free ( state ) ;
return false ;
}
void scavenger_schedule_disconnected ( struct files_struct * fsp )
{
NTSTATUS status ;
struct server_id self = messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ;
struct timeval disconnect_time , until ;
uint64_t timeout_usec ;
struct scavenger_message msg ;
DATA_BLOB msg_blob ;
2015-04-28 14:30:58 +03:00
struct server_id_buf tmp ;
2019-11-09 20:27:30 +03:00
struct file_id_buf idbuf ;
2013-02-07 18:26:37 +04:00
2014-05-01 21:58:51 +04:00
if ( fsp - > op = = NULL ) {
return ;
}
2013-02-07 18:26:37 +04:00
nttime_to_timeval ( & disconnect_time , fsp - > op - > global - > disconnect_time ) ;
2023-10-06 05:20:35 +03:00
timeout_usec = UINT64_C ( 1000 ) * fsp - > op - > global - > durable_timeout_msec ;
2013-02-07 18:26:37 +04:00
until = timeval_add ( & disconnect_time ,
timeout_usec / 1000000 ,
timeout_usec % 1000000 ) ;
ZERO_STRUCT ( msg ) ;
msg . file_id = fsp - > file_id ;
msg . open_persistent_id = fsp - > op - > global - > open_persistent_id ;
msg . until = timeval_to_nttime ( & until ) ;
DEBUG ( 10 , ( " smbd: %s mark file %s as disconnected at %s with timeout "
" at %s in %fs \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( self , & tmp ) ,
2019-11-09 20:27:30 +03:00
file_id_str_buf ( fsp - > file_id , & idbuf ) ,
2013-02-07 18:26:37 +04:00
timeval_string ( talloc_tos ( ) , & disconnect_time , true ) ,
timeval_string ( talloc_tos ( ) , & until , true ) ,
fsp - > op - > global - > durable_timeout_msec / 1000.0 ) ) ;
SMB_ASSERT ( server_id_is_disconnected ( & fsp - > op - > global - > server_id ) ) ;
SMB_ASSERT ( ! server_id_equal ( & self , & smbd_scavenger_state - > parent_id ) ) ;
SMB_ASSERT ( ! smbd_scavenger_state - > am_scavenger ) ;
msg_blob = data_blob_const ( & msg , sizeof ( msg ) ) ;
DEBUG ( 10 , ( " send message to scavenger \n " ) ) ;
status = messaging_send ( smbd_scavenger_state - > msg ,
smbd_scavenger_state - > parent_id ,
MSG_SMB_SCAVENGER ,
& msg_blob ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2015-04-28 14:30:58 +03:00
struct server_id_buf tmp1 , tmp2 ;
2013-02-07 18:26:37 +04:00
DEBUG ( 2 , ( " Failed to send message to parent smbd %s "
" from %s: %s \n " ,
2015-04-28 14:30:58 +03:00
server_id_str_buf ( smbd_scavenger_state - > parent_id ,
& tmp1 ) ,
server_id_str_buf ( self , & tmp2 ) ,
2013-02-07 18:26:37 +04:00
nt_errstr ( status ) ) ) ;
}
}
struct scavenger_timer_context {
struct smbd_scavenger_state * state ;
struct scavenger_message msg ;
} ;
2020-11-03 15:25:57 +03:00
struct cleanup_disconnected_state {
2020-11-04 15:35:26 +03:00
struct file_id fid ;
2020-11-03 15:25:57 +03:00
struct share_mode_lock * lck ;
uint64_t open_persistent_id ;
size_t num_disconnected ;
bool found_connected ;
} ;
static bool cleanup_disconnected_lease ( struct share_mode_entry * e ,
void * private_data )
{
struct cleanup_disconnected_state * state = private_data ;
NTSTATUS status ;
2020-11-04 15:35:26 +03:00
status = leases_db_del ( & e - > client_guid , & e - > lease_key , & state - > fid ) ;
2020-11-03 15:25:57 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " leases_db_del failed: %s \n " ,
nt_errstr ( status ) ) ;
}
return false ;
}
static bool share_mode_find_connected_fn (
struct share_mode_entry * e ,
bool * modified ,
void * private_data )
{
struct cleanup_disconnected_state * state = private_data ;
bool disconnected ;
disconnected = server_id_is_disconnected ( & e - > pid ) ;
if ( ! disconnected ) {
2020-11-04 15:32:14 +03:00
char * name = share_mode_filename ( talloc_tos ( ) , state - > lck ) ;
2020-11-03 15:25:57 +03:00
struct file_id_buf tmp1 ;
struct server_id_buf tmp2 ;
2020-11-04 15:32:14 +03:00
DBG_INFO ( " file (file-id='%s', servicepath='%s', name='%s') "
2020-11-03 15:25:57 +03:00
" is used by server %s ==> do not cleanup \n " ,
2020-11-04 15:35:26 +03:00
file_id_str_buf ( state - > fid , & tmp1 ) ,
2020-11-04 15:46:02 +03:00
share_mode_servicepath ( state - > lck ) ,
2020-11-04 15:32:14 +03:00
name ,
2020-11-03 15:25:57 +03:00
server_id_str_buf ( e - > pid , & tmp2 ) ) ;
2020-11-04 15:32:14 +03:00
TALLOC_FREE ( name ) ;
2020-11-03 15:25:57 +03:00
state - > found_connected = true ;
return true ;
}
if ( state - > open_persistent_id ! = e - > share_file_id ) {
2020-11-04 15:32:14 +03:00
char * name = share_mode_filename ( talloc_tos ( ) , state - > lck ) ;
2020-11-03 15:25:57 +03:00
struct file_id_buf tmp ;
DBG_INFO ( " entry for file "
2020-11-04 15:32:14 +03:00
" (file-id='%s', servicepath='%s', name='%s') "
2020-11-03 15:25:57 +03:00
" has share_file_id % " PRIu64 " but expected "
" % " PRIu64 " ==> do not cleanup \n " ,
2020-11-04 15:35:26 +03:00
file_id_str_buf ( state - > fid , & tmp ) ,
2020-11-04 15:46:02 +03:00
share_mode_servicepath ( state - > lck ) ,
2020-11-04 15:32:14 +03:00
name ,
2020-11-03 15:25:57 +03:00
e - > share_file_id ,
state - > open_persistent_id ) ;
2020-11-04 15:32:14 +03:00
TALLOC_FREE ( name ) ;
2020-11-03 15:25:57 +03:00
state - > found_connected = true ;
return true ;
}
state - > num_disconnected + = 1 ;
return false ;
}
static bool cleanup_disconnected_share_mode_entry_fn (
struct share_mode_entry * e ,
bool * modified ,
void * private_data )
{
struct cleanup_disconnected_state * state = private_data ;
bool disconnected ;
disconnected = server_id_is_disconnected ( & e - > pid ) ;
if ( ! disconnected ) {
2020-11-04 15:32:14 +03:00
char * name = share_mode_filename ( talloc_tos ( ) , state - > lck ) ;
2020-11-03 15:25:57 +03:00
struct file_id_buf tmp1 ;
struct server_id_buf tmp2 ;
2020-11-04 15:32:14 +03:00
DBG_ERR ( " file (file-id='%s', servicepath='%s', name='%s') "
2020-11-03 15:25:57 +03:00
" is used by server %s ==> internal error \n " ,
2020-11-04 15:35:26 +03:00
file_id_str_buf ( state - > fid , & tmp1 ) ,
2020-11-04 15:46:02 +03:00
share_mode_servicepath ( state - > lck ) ,
2020-11-04 15:32:14 +03:00
name ,
2020-11-03 15:25:57 +03:00
server_id_str_buf ( e - > pid , & tmp2 ) ) ;
2020-11-04 15:32:14 +03:00
TALLOC_FREE ( name ) ;
2020-11-03 15:25:57 +03:00
smb_panic ( __location__ ) ;
}
/*
* Setting e - > stale = true is
* the indication to delete the entry .
*/
e - > stale = true ;
return false ;
}
static bool share_mode_cleanup_disconnected (
struct file_id fid , uint64_t open_persistent_id )
{
struct cleanup_disconnected_state state = {
2020-11-04 15:35:26 +03:00
. fid = fid ,
2020-11-03 15:25:57 +03:00
. open_persistent_id = open_persistent_id
} ;
bool ret = false ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2020-11-04 15:32:14 +03:00
char * name = NULL ;
2020-11-03 15:25:57 +03:00
struct file_id_buf idbuf ;
bool ok ;
state . lck = get_existing_share_mode_lock ( frame , fid ) ;
if ( state . lck = = NULL ) {
DBG_INFO ( " Could not fetch share mode entry for %s \n " ,
file_id_str_buf ( fid , & idbuf ) ) ;
goto done ;
}
2020-11-04 15:32:14 +03:00
name = share_mode_filename ( frame , state . lck ) ;
2020-11-03 15:25:57 +03:00
ok = share_mode_forall_entries (
state . lck , share_mode_find_connected_fn , & state ) ;
if ( ! ok ) {
DBG_DEBUG ( " share_mode_forall_entries failed \n " ) ;
goto done ;
}
if ( state . found_connected ) {
DBG_DEBUG ( " Found connected entry \n " ) ;
goto done ;
}
ok = share_mode_forall_leases (
state . lck , cleanup_disconnected_lease , & state ) ;
if ( ! ok ) {
DBG_DEBUG ( " failed to clean up leases associated "
" with file (file-id='%s', servicepath='%s', "
2020-11-04 15:32:14 +03:00
" name='%s') and open_persistent_id % " PRIu64 " "
2020-11-03 15:25:57 +03:00
" ==> do not cleanup \n " ,
file_id_str_buf ( fid , & idbuf ) ,
2020-11-04 15:46:02 +03:00
share_mode_servicepath ( state . lck ) ,
2020-11-04 15:32:14 +03:00
name ,
2020-11-03 15:25:57 +03:00
open_persistent_id ) ;
goto done ;
}
ok = brl_cleanup_disconnected ( fid , open_persistent_id ) ;
if ( ! ok ) {
DBG_DEBUG ( " failed to clean up byte range locks associated "
" with file (file-id='%s', servicepath='%s', "
2020-11-04 15:32:14 +03:00
" name='%s') and open_persistent_id % " PRIu64 " "
2020-11-03 15:25:57 +03:00
" ==> do not cleanup \n " ,
file_id_str_buf ( fid , & idbuf ) ,
2020-11-04 15:46:02 +03:00
share_mode_servicepath ( state . lck ) ,
2020-11-04 15:32:14 +03:00
name ,
2020-11-03 15:25:57 +03:00
open_persistent_id ) ;
goto done ;
}
DBG_DEBUG ( " cleaning up %zu entries for file "
2020-11-04 15:32:14 +03:00
" (file-id='%s', servicepath='%s', name='%s') "
2020-11-03 15:25:57 +03:00
" from open_persistent_id % " PRIu64 " \n " ,
state . num_disconnected ,
file_id_str_buf ( fid , & idbuf ) ,
2020-11-04 15:46:02 +03:00
share_mode_servicepath ( state . lck ) ,
2020-11-04 15:32:14 +03:00
name ,
2020-11-03 15:25:57 +03:00
open_persistent_id ) ;
ok = share_mode_forall_entries (
state . lck , cleanup_disconnected_share_mode_entry_fn , & state ) ;
if ( ! ok ) {
DBG_DEBUG ( " failed to clean up %zu entries associated "
" with file (file-id='%s', servicepath='%s', "
2020-11-04 15:32:14 +03:00
" name='%s') and open_persistent_id % " PRIu64 " "
2020-11-03 15:25:57 +03:00
" ==> do not cleanup \n " ,
state . num_disconnected ,
file_id_str_buf ( fid , & idbuf ) ,
2020-11-04 15:46:02 +03:00
share_mode_servicepath ( state . lck ) ,
2020-11-04 15:32:14 +03:00
name ,
2020-11-03 15:25:57 +03:00
open_persistent_id ) ;
goto done ;
}
ret = true ;
done :
talloc_free ( frame ) ;
return ret ;
}
2013-02-07 18:26:37 +04:00
static void scavenger_timer ( struct tevent_context * ev ,
struct tevent_timer * te ,
struct timeval t , void * data )
{
struct scavenger_timer_context * ctx =
talloc_get_type_abort ( data , struct scavenger_timer_context ) ;
2019-11-09 20:30:37 +03:00
struct file_id_buf idbuf ;
2013-02-07 18:26:37 +04:00
NTSTATUS status ;
bool ok ;
2019-11-09 20:30:37 +03:00
DBG_DEBUG ( " do cleanup for file %s at %s \n " ,
file_id_str_buf ( ctx - > msg . file_id , & idbuf ) ,
timeval_string ( talloc_tos ( ) , & t , true ) ) ;
2013-02-07 18:26:37 +04:00
ok = share_mode_cleanup_disconnected ( ctx - > msg . file_id ,
ctx - > msg . open_persistent_id ) ;
if ( ! ok ) {
2019-11-09 20:30:37 +03:00
DBG_WARNING ( " Failed to cleanup share modes and byte range "
" locks for file %s open % " PRIu64 " \n " ,
file_id_str_buf ( ctx - > msg . file_id , & idbuf ) ,
ctx - > msg . open_persistent_id ) ;
2013-02-07 18:26:37 +04:00
}
status = smbXsrv_open_cleanup ( ctx - > msg . open_persistent_id ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2019-11-09 20:30:37 +03:00
DBG_WARNING ( " Failed to cleanup open global for file %s open "
" % " PRIu64 " : %s \n " ,
file_id_str_buf ( ctx - > msg . file_id , & idbuf ) ,
ctx - > msg . open_persistent_id ,
nt_errstr ( status ) ) ;
2013-02-07 18:26:37 +04:00
}
}
static void scavenger_add_timer ( struct smbd_scavenger_state * state ,
struct scavenger_message * msg )
{
struct tevent_timer * te ;
struct scavenger_timer_context * ctx ;
struct timeval until ;
2019-11-09 20:53:19 +03:00
struct file_id_buf idbuf ;
2013-02-07 18:26:37 +04:00
nttime_to_timeval ( & until , msg - > until ) ;
2019-11-09 20:53:19 +03:00
DBG_DEBUG ( " schedule file %s for cleanup at %s \n " ,
file_id_str_buf ( msg - > file_id , & idbuf ) ,
timeval_string ( talloc_tos ( ) , & until , true ) ) ;
2013-02-07 18:26:37 +04:00
ctx = talloc_zero ( state , struct scavenger_timer_context ) ;
if ( ctx = = NULL ) {
DEBUG ( 2 , ( " Failed to talloc_zero(scavenger_timer_context) \n " ) ) ;
return ;
}
ctx - > state = state ;
ctx - > msg = * msg ;
te = tevent_add_timer ( state - > ev ,
state ,
until ,
scavenger_timer ,
ctx ) ;
if ( te = = NULL ) {
DEBUG ( 2 , ( " Failed to add scavenger_timer event \n " ) ) ;
talloc_free ( ctx ) ;
return ;
}
/* delete context after handler was running */
talloc_steal ( te , ctx ) ;
}