summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2018-07-10 15:41:53 +0200
committerSimon Rettberg2018-07-10 15:41:53 +0200
commit4d66496ca02aca59489cc52dc111c46401846220 (patch)
tree17bade129429c35d05bb447951e938f0cfcbb79f
parent[SERVER] Fix use of wrong constant; increase queue len for hash checker (diff)
downloaddnbd3-4d66496ca02aca59489cc52dc111c46401846220.tar.gz
dnbd3-4d66496ca02aca59489cc52dc111c46401846220.tar.xz
dnbd3-4d66496ca02aca59489cc52dc111c46401846220.zip
[SERVER] Reload server config on SIGHUP
Most config settings can now be changed at runtime using SIGHUP. This currently excludes the basePath, listenPort, and the client and image count limits, as well as vmdkLegacyMode.
-rw-r--r--src/server/globals.c126
-rw-r--r--src/server/globals.h39
-rw-r--r--src/server/server.c1
3 files changed, 96 insertions, 70 deletions
diff --git a/src/server/globals.c b/src/server/globals.c
index aca7551..ee4de19 100644
--- a/src/server/globals.c
+++ b/src/server/globals.c
@@ -9,29 +9,36 @@
#include <errno.h>
char *_configDir = NULL;
-volatile bool _shutdown = false;
+atomic_bool _shutdown = false;
// [dnbd3]
-int _listenPort = PORT;
+atomic_int _listenPort = PORT;
char *_basePath = NULL;
-int _serverPenalty = 0;
-int _clientPenalty = 0;
-bool _isProxy = false;
-int _backgroundReplication = BGR_FULL;
-int _bgrMinClients = 0;
-bool _lookupMissingForProxy = true;
-bool _sparseFiles = false;
-bool _removeMissingImages = true;
-int _uplinkTimeout = SOCKET_TIMEOUT_UPLINK;
-int _clientTimeout = SOCKET_TIMEOUT_CLIENT;
-bool _closeUnusedFd = false;
-bool _vmdkLegacyMode = false;
+atomic_int _serverPenalty = 0;
+atomic_int _clientPenalty = 0;
+atomic_bool _isProxy = false;
+atomic_int _backgroundReplication = BGR_FULL;
+atomic_int _bgrMinClients = 0;
+atomic_bool _lookupMissingForProxy = true;
+atomic_bool _sparseFiles = false;
+atomic_bool _removeMissingImages = true;
+atomic_int _uplinkTimeout = SOCKET_TIMEOUT_UPLINK;
+atomic_int _clientTimeout = SOCKET_TIMEOUT_CLIENT;
+atomic_bool _closeUnusedFd = false;
+atomic_bool _vmdkLegacyMode = false;
// Not really needed anymore since we have '+' and '-' in alt-servers
-bool _proxyPrivateOnly = false;
+atomic_bool _proxyPrivateOnly = false;
// [limits]
-int _maxClients = SERVER_MAX_CLIENTS;
-int _maxImages = SERVER_MAX_IMAGES;
-int _maxPayload = 9000000; // 9MB
-uint64_t _maxReplicationSize = (uint64_t)100000000000LL;
+atomic_int _maxClients = SERVER_MAX_CLIENTS;
+atomic_int _maxImages = SERVER_MAX_IMAGES;
+atomic_int _maxPayload = 9000000; // 9MB
+atomic_uint_fast64_t _maxReplicationSize = (uint64_t)100000000000LL;
+
+/**
+ * True when loading config the first time. Consecutive loads will
+ * ignore certain values which cannot be changed safely at runtime.
+ */
+static atomic_bool initialLoad = true;
+static pthread_mutex_t loadLock = PTHREAD_MUTEX_INITIALIZER;
#define IS_TRUE(value) (atoi(value) != 0 || strcmp(value, "true") == 0 || strcmp(value, "True") == 0 || strcmp(value, "TRUE") == 0)
#define SAVE_TO_VAR_STR(ss, kk) do { if (strcmp(section, #ss) == 0 && strcmp(key, #kk) == 0) { if (_ ## kk != NULL) free(_ ## kk); _ ## kk = strdup(value); } } while (0)
@@ -40,19 +47,26 @@ uint64_t _maxReplicationSize = (uint64_t)100000000000LL;
#define SAVE_TO_VAR_UINT(ss, kk) do { if (strcmp(section, #ss) == 0 && strcmp(key, #kk) == 0) parse32u(value, &_ ## kk, #ss); } while (0)
#define SAVE_TO_VAR_UINT64(ss, kk) do { if (strcmp(section, #ss) == 0 && strcmp(key, #kk) == 0) parse64u(value, &_ ## kk, #ss); } while (0)
+static void sanitizeFixedConfig();
+
static void handleMaskString( const char *value, void(*func)(logmask_t) );
static const char* units = "KMGTPEZY";
-static bool parse64(const char *in, int64_t *out, const char *optname);
-static bool parse64u(const char *in, uint64_t *out, const char *optname);
-static bool parse32(const char *in, int *out, const char *optname) UNUSED;
-static bool parse32u(const char *in, int *out, const char *optname);
+static bool parse64(const char *in, atomic_int_fast64_t *out, const char *optname);
+static bool parse64u(const char *in, atomic_uint_fast64_t *out, const char *optname);
+static bool parse32(const char *in, atomic_int *out, const char *optname) UNUSED;
+static bool parse32u(const char *in, atomic_int *out, const char *optname);
static int ini_handler(void *custom UNUSED, const char* section, const char* key, const char* value)
{
- if ( _basePath == NULL ) SAVE_TO_VAR_STR( dnbd3, basePath );
- SAVE_TO_VAR_BOOL( dnbd3, vmdkLegacyMode );
+ if ( initialLoad ) {
+ if ( _basePath == NULL ) SAVE_TO_VAR_STR( dnbd3, basePath );
+ SAVE_TO_VAR_BOOL( dnbd3, vmdkLegacyMode );
+ SAVE_TO_VAR_UINT( dnbd3, listenPort );
+ SAVE_TO_VAR_UINT( limits, maxClients );
+ SAVE_TO_VAR_UINT( limits, maxImages );
+ }
SAVE_TO_VAR_BOOL( dnbd3, isProxy );
SAVE_TO_VAR_BOOL( dnbd3, proxyPrivateOnly );
SAVE_TO_VAR_INT( dnbd3, bgrMinClients );
@@ -64,9 +78,6 @@ static int ini_handler(void *custom UNUSED, const char* section, const char* key
SAVE_TO_VAR_UINT( dnbd3, clientPenalty );
SAVE_TO_VAR_UINT( dnbd3, uplinkTimeout );
SAVE_TO_VAR_UINT( dnbd3, clientTimeout );
- SAVE_TO_VAR_UINT( dnbd3, listenPort );
- SAVE_TO_VAR_UINT( limits, maxClients );
- SAVE_TO_VAR_UINT( limits, maxImages );
SAVE_TO_VAR_UINT( limits, maxPayload );
SAVE_TO_VAR_UINT64( limits, maxReplicationSize );
if ( strcmp( section, "dnbd3" ) == 0 && strcmp( key, "backgroundReplication" ) == 0 ) {
@@ -97,8 +108,29 @@ void globals_loadConfig()
char *name = NULL;
asprintf( &name, "%s/%s", _configDir, CONFIG_FILENAME );
if ( name == NULL ) return;
+ if ( pthread_mutex_trylock( &loadLock ) != 0 ) {
+ logadd( LOG_INFO, "Ignoring config reload request due to already running reload" );
+ return;
+ }
ini_parse( name, &ini_handler, NULL );
free( name );
+ if ( initialLoad ) {
+ sanitizeFixedConfig();
+ }
+ if ( _backgroundReplication == BGR_FULL && _sparseFiles && _bgrMinClients < 5 ) {
+ logadd( LOG_WARNING, "Ignoring 'sparseFiles=true' since backgroundReplication is set to true and bgrMinClients is too low" );
+ _sparseFiles = false;
+ }
+ // Dump config as interpreted
+ char buffer[2000];
+ globals_dumpConfig( buffer, sizeof(buffer) );
+ logadd( LOG_DEBUG1, "Effective configuration:\n%s", buffer );
+ initialLoad = false;
+ pthread_mutex_unlock( &loadLock );
+}
+
+static void sanitizeFixedConfig()
+{
// Validate settings after loading:
// base path for images valid?
if ( _basePath == NULL || _basePath[0] == '\0' ) {
@@ -160,14 +192,6 @@ void globals_loadConfig()
}
}
}
- if ( _backgroundReplication == BGR_FULL && _sparseFiles && _bgrMinClients < 5 ) {
- logadd( LOG_WARNING, "Ignoring 'sparseFiles=true' since backgroundReplication is set to true and bgrMinClients is too low" );
- _sparseFiles = false;
- }
- // Dump config as interpreted
- char buffer[2000];
- globals_dumpConfig( buffer, sizeof(buffer) );
- logadd( LOG_DEBUG1, "Effective configuration:\n%s", buffer );
}
#define SETLOGBIT(name) do { if ( strstr( value, #name ) != NULL ) mask |= LOG_ ## name; } while (0)
@@ -183,7 +207,7 @@ static void handleMaskString( const char *value, void(*func)(logmask_t) )
(*func)( mask );
}
-static bool parse64(const char *in, int64_t *out, const char *optname)
+static bool parse64(const char *in, atomic_int_fast64_t *out, const char *optname)
{
if ( *in == '\0' ) {
logadd( LOG_WARNING, "Ignoring empty numeric setting '%s'", optname );
@@ -212,43 +236,43 @@ static bool parse64(const char *in, int64_t *out, const char *optname)
}
}
while ( exp-- > 0 ) num *= base;
- *out = (int64_t)num;
+ *out = (atomic_int_fast64_t)num;
return true;
}
-static bool parse64u(const char *in, uint64_t *out, const char *optname)
+static bool parse64u(const char *in, atomic_uint_fast64_t *out, const char *optname)
{
- int64_t v;
+ atomic_int_fast64_t v;
if ( !parse64( in, &v, optname ) ) return false;
if ( v < 0 ) {
logadd( LOG_WARNING, "Ignoring value '%s' for '%s': Cannot be negative", in, optname );
return false;
}
- *out = (uint64_t)v;
+ *out = (atomic_uint_fast64_t)v;
return true;
}
-static bool parse32(const char *in, int *out, const char *optname)
+static bool parse32(const char *in, atomic_int *out, const char *optname)
{
- int64_t v;
+ atomic_int_fast64_t v;
if ( !parse64( in, &v, optname ) ) return false;
if ( v < INT_MIN || v > INT_MAX ) {
logadd( LOG_WARNING, "'%s' must be between %d and %d, but is '%s'", optname, (int)INT_MIN, (int)INT_MAX, in );
return false;
}
- *out = (int)v;
+ *out = (atomic_int)v;
return true;
}
-static bool parse32u(const char *in, int *out, const char *optname)
+static bool parse32u(const char *in, atomic_int *out, const char *optname)
{
- int64_t v;
+ atomic_int_fast64_t v;
if ( !parse64( in, &v, optname ) ) return false;
if ( v < 0 || v > INT_MAX ) {
logadd( LOG_WARNING, "'%s' must be between %d and %d, but is '%s'", optname, (int)0, (int)INT_MAX, in );
return false;
}
- *out = (int)v;
+ *out = (atomic_int)v;
return true;
}
@@ -258,10 +282,10 @@ static bool parse32u(const char *in, int *out, const char *optname)
rem -= r; \
buffer += r; \
} while (0)
-#define PVAR(var,type) P_ARG(#var "=%" type "\n", _ ## var)
-#define PINT(var) PVAR(var, "d")
-#define PUINT64(var) PVAR(var, PRIu64)
-#define PSTR(var) PVAR(var, "s")
+#define PVAR(var,type,cast) P_ARG(#var "=%" type "\n", (cast) _ ## var)
+#define PINT(var) PVAR(var, "d", int)
+#define PUINT64(var) PVAR(var, PRIu64, uint64_t)
+#define PSTR(var) PVAR(var, "s", const char*)
#define PBOOL(var) P_ARG(#var "=%s\n", _ ## var ? "true" : "false")
size_t globals_dumpConfig(char *buffer, size_t size)
diff --git a/src/server/globals.h b/src/server/globals.h
index e82ea1b..c384ac6 100644
--- a/src/server/globals.h
+++ b/src/server/globals.h
@@ -5,6 +5,7 @@
#include "../shared/fdsignal.h"
#include "../serverconfig.h"
#include <stdint.h>
+#include <stdatomic.h>
#include <time.h>
#include <pthread.h>
@@ -154,59 +155,59 @@ extern char *_basePath;
/**
* Whether or not simple *.vmdk files should be treated as revision 1
*/
-extern bool _vmdkLegacyMode;
+extern atomic_bool _vmdkLegacyMode;
/**
* How much artificial delay should we add when a server connects to us?
*/
-extern int _serverPenalty;
+extern atomic_int _serverPenalty;
/**
* How much artificial delay should we add when a client connects to us?
*/
-extern int _clientPenalty;
+extern atomic_int _clientPenalty;
/**
* Is server shutting down?
*/
-extern volatile bool _shutdown;
+extern atomic_bool _shutdown;
/**
* Is server allowed to provide images in proxy mode?
*/
-extern bool _isProxy;
+extern atomic_bool _isProxy;
/**
* Only use servers as upstream proxy which are private?
*/
-extern bool _proxyPrivateOnly;
+extern atomic_bool _proxyPrivateOnly;
/**
* Whether to remove missing images from image list on SIGHUP
*/
-extern bool _removeMissingImages;
+extern atomic_bool _removeMissingImages;
/**
* Read timeout when waiting for or sending data on an uplink
*/
-extern int _uplinkTimeout;
+extern atomic_int _uplinkTimeout;
/**
* Read timeout when waiting for or sending data from/to client
*/
-extern int _clientTimeout;
+extern atomic_int _clientTimeout;
/**
* If true, images with no active client will have their fd closed after some
* idle time.
*/
-extern bool _closeUnusedFd;
+extern atomic_bool _closeUnusedFd;
/**
* Should we replicate incomplete images in the background?
* Otherwise, only blocks that were explicitly requested will be cached.
*/
-extern int _backgroundReplication;
+extern atomic_int _backgroundReplication;
#define BGR_DISABLED (0)
#define BGR_FULL (1)
#define BGR_HASHBLOCK (2)
@@ -214,14 +215,14 @@ extern int _backgroundReplication;
/**
* Minimum connected clients for background replication to kick in
*/
-extern int _bgrMinClients;
+extern atomic_int _bgrMinClients;
/**
* (In proxy mode): If connecting client is a proxy, and the requested image
* is not known locally, should we ask our known alt servers for it?
* Otherwise the request is rejected.
*/
-extern bool _lookupMissingForProxy;
+extern atomic_bool _lookupMissingForProxy;
/**
* Should we preallocate proxied images right at the start to make
@@ -235,22 +236,22 @@ extern bool _lookupMissingForProxy;
* This setting will have no effect if background replication is
* turned on.
*/
-extern bool _sparseFiles;
+extern atomic_bool _sparseFiles;
/**
* Port to listen on (default: #define PORT (5003))
*/
-extern int _listenPort;
+extern atomic_int _listenPort;
/**
* Max number of DNBD3 clients we accept
*/
-extern int _maxClients;
+extern atomic_int _maxClients;
/**
* Max number of Images we support (in baseDir)
*/
-extern int _maxImages;
+extern atomic_int _maxImages;
/**
* Maximum payload length we accept on uplinks and thus indirectly
@@ -258,13 +259,13 @@ extern int _maxImages;
* Usually this isn't even a megabyte for "real" clients (blockdev
* or fuse).
*/
-extern int _maxPayload;
+extern atomic_int _maxPayload;
/**
* If in proxy mode, don't replicate images that are
* larger than this according to the uplink server.
*/
-extern uint64_t _maxReplicationSize;
+extern atomic_uint_fast64_t _maxReplicationSize;
/**
* Load the server configuration.
diff --git a/src/server/server.c b/src/server/server.c
index 0944c51..10ab208 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -488,6 +488,7 @@ uint32_t dnbd3_serverUptime()
static void* server_asyncImageListLoad(void *data UNUSED)
{
setThreadName( "img-list-loader" );
+ globals_loadConfig();
image_loadAll( NULL );
return NULL;
}