2009-09-03 20:20:39 +04:00
/*
ctdb banning code
Copyright ( C ) Ronnie Sahlberg 2009
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/>.
*/
2015-10-26 08:50:46 +03:00
# include "replace.h"
2009-09-03 20:20:39 +04:00
# include "system/time.h"
# include "system/network.h"
# include "system/filesys.h"
# include "system/wait.h"
2015-10-26 08:50:46 +03:00
# include <talloc.h>
# include <tevent.h>
# include "lib/util/debug.h"
# include "lib/util/samba_util.h"
# include "ctdb_private.h"
# include "ctdb_client.h"
# include "ctdb_logging.h"
2009-09-03 20:20:39 +04:00
2015-10-26 08:50:09 +03:00
static void ctdb_ban_node_event ( struct tevent_context * ev ,
struct tevent_timer * te ,
struct timeval t , void * private_data )
2009-09-03 20:20:39 +04:00
{
struct ctdb_context * ctdb = talloc_get_type ( private_data , struct ctdb_context ) ;
2013-07-01 11:40:36 +04:00
/* Make sure we were able to freeze databases during banning */
2014-08-21 06:32:02 +04:00
if ( ! ctdb_db_all_frozen ( ctdb ) ) {
2013-07-01 11:40:36 +04:00
DEBUG ( DEBUG_ERR , ( " Banning timedout, but still unable to freeze databases \n " ) ) ;
ctdb_ban_self ( ctdb ) ;
return ;
}
2009-09-03 20:20:39 +04:00
DEBUG ( DEBUG_ERR , ( " Banning timedout \n " ) ) ;
ctdb - > nodes [ ctdb - > pnn ] - > flags & = ~ NODE_FLAGS_BANNED ;
if ( ctdb - > banning_ctx ! = NULL ) {
talloc_free ( ctdb - > banning_ctx ) ;
ctdb - > banning_ctx = NULL ;
}
}
2013-06-28 08:04:18 +04:00
void ctdb_local_node_got_banned ( struct ctdb_context * ctdb )
2010-08-31 11:28:34 +04:00
{
2015-09-11 07:20:44 +03:00
struct ctdb_db_context * ctdb_db ;
2015-09-16 11:20:31 +03:00
DEBUG ( DEBUG_NOTICE , ( " This node has been banned - forcing recovery \n " ) ) ;
2010-08-31 11:28:34 +04:00
/* Reset the generation id to 1 to make us ignore any
REQ / REPLY CALL / DMASTER someone sends to us .
We are now banned so we shouldnt service database calls
anymore .
*/
ctdb - > vnn_map - > generation = INVALID_GENERATION ;
2015-09-11 07:20:44 +03:00
for ( ctdb_db = ctdb - > db_list ; ctdb_db ! = NULL ; ctdb_db = ctdb_db - > next ) {
ctdb_db - > generation = INVALID_GENERATION ;
}
2010-08-31 11:28:34 +04:00
2015-09-16 11:20:31 +03:00
/* make sure we get frozen */
2014-05-06 08:24:52 +04:00
ctdb - > recovery_mode = CTDB_RECOVERY_ACTIVE ;
2015-09-16 11:20:31 +03:00
2010-08-31 11:28:34 +04:00
ctdb_release_all_ips ( ctdb ) ;
}
2009-09-03 20:20:39 +04:00
int32_t ctdb_control_set_ban_state ( struct ctdb_context * ctdb , TDB_DATA indata )
{
struct ctdb_ban_time * bantime = ( struct ctdb_ban_time * ) indata . dptr ;
2015-07-27 09:51:08 +03:00
bool already_banned ;
2009-09-03 20:20:39 +04:00
DEBUG ( DEBUG_INFO , ( " SET BAN STATE \n " ) ) ;
if ( bantime - > pnn ! = ctdb - > pnn ) {
2013-11-11 05:39:27 +04:00
if ( bantime - > pnn > = ctdb - > num_nodes ) {
2009-09-03 20:20:39 +04:00
DEBUG ( DEBUG_ERR , ( __location__ " ERROR: Invalid ban request. PNN:%d is invalid. Max nodes %d \n " , bantime - > pnn , ctdb - > num_nodes ) ) ;
return - 1 ;
}
if ( bantime - > time = = 0 ) {
2013-06-24 08:31:50 +04:00
DEBUG ( DEBUG_NOTICE , ( " unbanning node %d \n " , bantime - > pnn ) ) ;
2009-09-03 20:20:39 +04:00
ctdb - > nodes [ bantime - > pnn ] - > flags & = ~ NODE_FLAGS_BANNED ;
} else {
2013-06-24 08:31:50 +04:00
DEBUG ( DEBUG_NOTICE , ( " banning node %d \n " , bantime - > pnn ) ) ;
2009-09-03 20:20:39 +04:00
if ( ctdb - > tunable . enable_bans = = 0 ) {
2013-06-24 08:31:50 +04:00
/* FIXME: This is bogus. We really should be
* taking decision based on the tunables on
* the banned node and not local node .
*/
DEBUG ( DEBUG_WARNING , ( " Bans are disabled - ignoring ban of node %u \n " , bantime - > pnn ) ) ;
2009-09-03 20:20:39 +04:00
return 0 ;
}
ctdb - > nodes [ bantime - > pnn ] - > flags | = NODE_FLAGS_BANNED ;
}
return 0 ;
}
2015-07-27 09:51:08 +03:00
already_banned = false ;
2009-09-03 20:20:39 +04:00
if ( ctdb - > banning_ctx ! = NULL ) {
talloc_free ( ctdb - > banning_ctx ) ;
ctdb - > banning_ctx = NULL ;
2015-07-27 09:51:08 +03:00
already_banned = true ;
2009-09-03 20:20:39 +04:00
}
if ( bantime - > time = = 0 ) {
DEBUG ( DEBUG_ERR , ( " Unbanning this node \n " ) ) ;
ctdb - > nodes [ bantime - > pnn ] - > flags & = ~ NODE_FLAGS_BANNED ;
return 0 ;
}
if ( ctdb - > tunable . enable_bans = = 0 ) {
DEBUG ( DEBUG_ERR , ( " Bans are disabled - ignoring ban of node %u \n " , bantime - > pnn ) ) ;
return 0 ;
}
ctdb - > banning_ctx = talloc ( ctdb , struct ctdb_ban_time ) ;
if ( ctdb - > banning_ctx = = NULL ) {
DEBUG ( DEBUG_CRIT , ( __location__ " ERROR Failed to allocate new banning state \n " ) ) ;
return - 1 ;
}
* ( ( struct ctdb_ban_time * ) ( ctdb - > banning_ctx ) ) = * bantime ;
DEBUG ( DEBUG_ERR , ( " Banning this node for %d seconds \n " , bantime - > time ) ) ;
ctdb - > nodes [ bantime - > pnn ] - > flags | = NODE_FLAGS_BANNED ;
2015-10-26 08:50:09 +03:00
tevent_add_timer ( ctdb - > ev , ctdb - > banning_ctx ,
timeval_current_ofs ( bantime - > time , 0 ) ,
ctdb_ban_node_event , ctdb ) ;
2010-08-31 11:28:34 +04:00
2015-07-27 09:51:08 +03:00
if ( ! already_banned ) {
ctdb_local_node_got_banned ( ctdb ) ;
}
2009-09-03 20:20:39 +04:00
return 0 ;
}
int32_t ctdb_control_get_ban_state ( struct ctdb_context * ctdb , TDB_DATA * outdata )
{
struct ctdb_ban_time * bantime ;
bantime = talloc ( outdata , struct ctdb_ban_time ) ;
CTDB_NO_MEMORY ( ctdb , bantime ) ;
if ( ctdb - > banning_ctx ! = NULL ) {
* bantime = * ( struct ctdb_ban_time * ) ( ctdb - > banning_ctx ) ;
} else {
bantime - > pnn = ctdb - > pnn ;
bantime - > time = 0 ;
}
outdata - > dptr = ( uint8_t * ) bantime ;
outdata - > dsize = sizeof ( struct ctdb_ban_time ) ;
return 0 ;
}
2009-12-07 15:48:40 +03:00
/* Routine to ban ourselves for a while when trouble strikes. */
void ctdb_ban_self ( struct ctdb_context * ctdb )
{
TDB_DATA data ;
struct ctdb_ban_time bantime ;
bantime . pnn = ctdb - > pnn ;
bantime . time = ctdb - > tunable . recovery_ban_period ;
data . dsize = sizeof ( bantime ) ;
data . dptr = ( uint8_t * ) & bantime ;
ctdb_control_set_ban_state ( ctdb , data ) ;
}