2014-06-06 12:55:56 +10:00
/*
common system utilities
Copyright ( C ) Amitay Isaacs 2014
Copyright ( C ) Martin Schwenke 2014
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 16:50:46 +11:00
# include "replace.h"
2014-06-06 12:55:56 +10:00
# include "system/filesys.h"
2014-06-10 17:04:34 +10:00
# include "system/shmem.h"
2015-10-26 16:50:46 +11:00
# include "system/network.h"
2014-06-06 12:55:56 +10:00
2016-03-11 11:44:12 +11:00
# include <talloc.h>
2014-06-06 12:55:56 +10:00
# include <libgen.h>
2015-10-26 16:50:46 +11:00
# include "lib/util/debug.h"
2015-11-02 16:03:29 +11:00
# include "protocol/protocol.h"
2015-10-23 14:11:53 +11:00
2015-11-11 14:43:56 +11:00
# include "common/logging.h"
2015-10-23 14:11:53 +11:00
# include "common/system.h"
2014-06-06 13:52:15 +10:00
# if HAVE_SCHED_H
# include <sched.h>
# endif
# if HAVE_PROCINFO_H
# include <procinfo.h>
# endif
2017-03-08 08:33:56 -07:00
# include "lib/util/mkdir_p.h"
2014-06-06 13:52:15 +10:00
/*
if possible , make this task real time
*/
2014-09-12 11:22:36 +10:00
bool set_scheduler ( void )
2014-06-06 13:52:15 +10:00
{
# ifdef _AIX_
# if HAVE_THREAD_SETSCHED
struct thrdentry64 te ;
tid64_t ti ;
ti = 0ULL ;
if ( getthrds64 ( getpid ( ) , & te , sizeof ( te ) , & ti , 1 ) ! = 1 ) {
DEBUG ( DEBUG_ERR , ( " Unable to get thread information \n " ) ) ;
2014-09-12 11:22:36 +10:00
return false ;
2014-06-06 13:52:15 +10:00
}
if ( thread_setsched ( te . ti_tid , 0 , SCHED_RR ) = = - 1 ) {
DEBUG ( DEBUG_ERR , ( " Unable to set scheduler to SCHED_RR (%s) \n " ,
strerror ( errno ) ) ) ;
2014-09-12 11:22:36 +10:00
return false ;
2014-06-06 13:52:15 +10:00
} else {
2014-09-12 11:22:36 +10:00
return true ;
2014-06-06 13:52:15 +10:00
}
# endif
# else /* no AIX */
# if HAVE_SCHED_SETSCHEDULER
struct sched_param p ;
p . sched_priority = 1 ;
2016-10-24 18:24:54 +11:00
if ( sched_setscheduler ( 0 , SCHED_FIFO , & p ) = = - 1 ) {
2014-06-06 13:52:15 +10:00
DEBUG ( DEBUG_CRIT , ( " Unable to set scheduler to SCHED_FIFO (%s) \n " ,
strerror ( errno ) ) ) ;
2014-09-12 11:22:36 +10:00
return false ;
2014-06-06 13:52:15 +10:00
} else {
2014-09-12 11:22:36 +10:00
return true ;
2014-06-06 13:52:15 +10:00
}
# endif
# endif
2014-09-15 11:48:33 +10:00
DEBUG ( DEBUG_CRIT , ( " No way to set real-time priority. \n " ) ) ;
2014-09-12 11:22:36 +10:00
return false ;
2014-06-06 13:52:15 +10:00
}
/*
reset scheduler from real - time to normal scheduling
*/
void reset_scheduler ( void )
{
# ifdef _AIX_
# if HAVE_THREAD_SETSCHED
struct thrdentry64 te ;
tid64_t ti ;
ti = 0ULL ;
if ( getthrds64 ( getpid ( ) , & te , sizeof ( te ) , & ti , 1 ) ! = 1 ) {
DEBUG ( DEBUG_ERR , ( " Unable to get thread information \n " ) ) ;
}
if ( thread_setsched ( te . ti_tid , 0 , SCHED_OTHER ) = = - 1 ) {
DEBUG ( DEBUG_ERR , ( " Unable to set scheduler to SCHED_OTHER \n " ) ) ;
}
# endif
# else /* no AIX */
# if HAVE_SCHED_SETSCHEDULER
struct sched_param p ;
p . sched_priority = 0 ;
if ( sched_setscheduler ( 0 , SCHED_OTHER , & p ) = = - 1 ) {
DEBUG ( DEBUG_ERR , ( " Unable to set scheduler to SCHED_OTHER \n " ) ) ;
}
# endif
# endif
}
2017-09-19 23:51:21 +10:00
static bool parse_ipv4 ( const char * s , unsigned port , struct sockaddr_in * sin )
2014-06-06 13:52:15 +10:00
{
sin - > sin_family = AF_INET ;
sin - > sin_port = htons ( port ) ;
if ( inet_pton ( AF_INET , s , & sin - > sin_addr ) ! = 1 ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to translate %s into sin_addr \n " , s ) ) ;
return false ;
}
2015-02-20 11:47:23 +11:00
# ifdef HAVE_SOCK_SIN_LEN
2015-08-19 07:33:48 +02:00
sin - > sin_len = sizeof ( * sin ) ;
2015-02-20 11:47:23 +11:00
# endif
2014-06-06 13:52:15 +10:00
return true ;
}
static bool parse_ipv6 ( const char * s , const char * ifaces , unsigned port , ctdb_sock_addr * saddr )
{
saddr - > ip6 . sin6_family = AF_INET6 ;
saddr - > ip6 . sin6_port = htons ( port ) ;
saddr - > ip6 . sin6_flowinfo = 0 ;
saddr - > ip6 . sin6_scope_id = 0 ;
if ( inet_pton ( AF_INET6 , s , & saddr - > ip6 . sin6_addr ) ! = 1 ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to translate %s into sin6_addr \n " , s ) ) ;
return false ;
}
if ( ifaces & & IN6_IS_ADDR_LINKLOCAL ( & saddr - > ip6 . sin6_addr ) ) {
if ( strchr ( ifaces , ' , ' ) ) {
DEBUG ( DEBUG_ERR , ( __location__ " Link local address %s "
" is specified for multiple ifaces %s \n " ,
s , ifaces ) ) ;
return false ;
}
saddr - > ip6 . sin6_scope_id = if_nametoindex ( ifaces ) ;
}
2015-02-20 11:47:23 +11:00
# ifdef HAVE_SOCK_SIN_LEN
saddr - > ip6 . sin6_len = sizeof ( * saddr ) ;
# endif
2014-06-06 13:52:15 +10:00
return true ;
}
/*
parse an ip
*/
2017-09-19 23:51:21 +10:00
static bool parse_ip ( const char * addr , const char * ifaces , unsigned port ,
ctdb_sock_addr * saddr )
2014-06-06 13:52:15 +10:00
{
char * p ;
bool ret ;
ZERO_STRUCTP ( saddr ) ; /* valgrind :-) */
2017-03-01 17:22:22 +11:00
/* IPv4 or IPv6 address?
*
* Use rindex ( ) because we need the right - most ' : ' below for
* IPv4 - mapped IPv6 addresses anyway . . .
*/
p = rindex ( addr , ' : ' ) ;
2014-06-06 13:52:15 +10:00
if ( p = = NULL ) {
ret = parse_ipv4 ( addr , port , & saddr - > ip ) ;
} else {
2017-03-01 17:22:22 +11:00
uint8_t ipv4_mapped_prefix [ 12 ] = {
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0xff , 0xff
} ;
2014-06-06 13:52:15 +10:00
ret = parse_ipv6 ( addr , ifaces , port , saddr ) ;
2017-03-01 17:22:22 +11:00
if ( ! ret ) {
return ret ;
}
/*
* Check for IPv4 - mapped IPv6 address
* ( e . g . : : ffff : 192.0 .2 .128 ) - reparse as IPv4 if
* necessary
*/
if ( memcmp ( & saddr - > ip6 . sin6_addr . s6_addr [ 0 ] ,
ipv4_mapped_prefix ,
sizeof ( ipv4_mapped_prefix ) ) = = 0 ) {
/* Reparse as IPv4 */
ret = parse_ipv4 ( p + 1 , port , & saddr - > ip ) ;
}
2014-06-06 13:52:15 +10:00
}
return ret ;
}
/*
parse a ip / mask pair
*/
bool parse_ip_mask ( const char * str , const char * ifaces , ctdb_sock_addr * addr , unsigned * mask )
{
char * p ;
char s [ 64 ] ; /* Much longer than INET6_ADDRSTRLEN */
char * endp = NULL ;
ssize_t len ;
bool ret ;
ZERO_STRUCT ( * addr ) ;
len = strlen ( str ) ;
if ( len > = sizeof ( s ) ) {
DEBUG ( DEBUG_ERR , ( " Address %s is unreasonably long \n " , str ) ) ;
return false ;
}
strncpy ( s , str , len + 1 ) ;
p = rindex ( s , ' / ' ) ;
if ( p = = NULL ) {
DEBUG ( DEBUG_ERR , ( __location__ " This addr: %s does not contain a mask \n " , s ) ) ;
return false ;
}
* mask = strtoul ( p + 1 , & endp , 10 ) ;
if ( endp = = NULL | | * endp ! = 0 ) {
/* trailing garbage */
DEBUG ( DEBUG_ERR , ( __location__ " Trailing garbage after the mask in %s \n " , s ) ) ;
return false ;
}
* p = 0 ;
/* now is this a ipv4 or ipv6 address ?*/
ret = parse_ip ( s , ifaces , 0 , addr ) ;
return ret ;
}
2014-06-10 17:04:34 +10:00
/* we don't lock future pages here; it would increase the chance that
* we ' d fail to mmap later on . */
void lockdown_memory ( bool valgrinding )
{
# if defined(HAVE_MLOCKALL) && !defined(_AIX_)
/* Extra stack, please! */
char dummy [ 10000 ] ;
memset ( dummy , 0 , sizeof ( dummy ) ) ;
if ( valgrinding ) {
return ;
}
/* Ignore when running in local daemons mode */
if ( getuid ( ) ! = 0 ) {
return ;
}
/* Avoid compiler optimizing out dummy. */
mlock ( dummy , sizeof ( dummy ) ) ;
if ( mlockall ( MCL_CURRENT ) ! = 0 ) {
DEBUG ( DEBUG_WARNING , ( " Failed to lockdown memory: %s' \n " ,
strerror ( errno ) ) ) ;
}
# endif
}
2014-06-06 15:25:08 +10:00
void mkdir_p_or_die ( const char * dir , int mode )
{
int ret ;
ret = mkdir_p ( dir , mode ) ;
if ( ret ! = 0 ) {
DEBUG ( DEBUG_ALERT ,
( " ctdb exiting with error: "
" failed to create directory \" %s \" (%s) \n " ,
dir , strerror ( errno ) ) ) ;
exit ( 1 ) ;
}
}
2014-07-30 20:50:59 +10:00
2015-12-08 14:12:46 +11:00
void ctdb_wait_for_process_to_exit ( pid_t pid )
{
while ( kill ( pid , 0 ) = = 0 | | errno ! = ESRCH ) {
sleep ( 5 ) ;
}
}