summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2016-02-01 12:41:11 +0100
committerSimon Rettberg2016-02-01 12:41:11 +0100
commit81c9da3c9d55fab13ab9a912cade320015d01613 (patch)
tree03b8ab9263b72c3ce746d1827222a03696452a9d
parent[SERVER] Fix a lot of (mostly harmless) data races (diff)
downloaddnbd3-81c9da3c9d55fab13ab9a912cade320015d01613.tar.gz
dnbd3-81c9da3c9d55fab13ab9a912cade320015d01613.tar.xz
dnbd3-81c9da3c9d55fab13ab9a912cade320015d01613.zip
[SERVER] BREAKING: Get rid of pseudo case-insensitivityv2.1
This was a wrong decision made long time ago, and it's broken in certain scenarios (eg. two servers serving from same NFS mount). Also it's of limited use anyways since it only supportes ASCII and would ignore umlauts, so blöd and BLÖD would still be considered two different images. So if you relied on this "feature" in any way, be careful when updating.
-rw-r--r--src/server/altservers.c20
-rw-r--r--src/server/globals.h6
-rw-r--r--src/server/helper.c8
-rw-r--r--src/server/helper.h1
-rw-r--r--src/server/image.c30
-rw-r--r--src/server/integrity.c2
-rw-r--r--src/server/net.c6
-rw-r--r--src/server/uplink.c18
-rw-r--r--src/shared/protocol.h4
9 files changed, 41 insertions, 54 deletions
diff --git a/src/server/altservers.c b/src/server/altservers.c
index 1a1e844..e4a7dca 100644
--- a/src/server/altservers.c
+++ b/src/server/altservers.c
@@ -432,7 +432,7 @@ static void *altservers_main(void *data UNUSED)
int sock = sock_connect( &servers[itAlt], 750, _uplinkTimeout );
if ( sock < 0 ) continue;
// Select image ++++++++++++++++++++++++++++++
- if ( !dnbd3_select_image( sock, image->lower_name, image->rid, FLAGS8_SERVER ) ) {
+ if ( !dnbd3_select_image( sock, image->name, image->rid, FLAGS8_SERVER ) ) {
goto server_failed;
}
// See if selecting the image succeeded ++++++++++++++++++++++++++++++
@@ -443,36 +443,36 @@ static void *altservers_main(void *data UNUSED)
goto server_image_not_available;
}
if ( protocolVersion < MIN_SUPPORTED_SERVER ) goto server_failed;
- if ( name == NULL || strcmp( name, image->lower_name ) != 0 ) {
- ERROR_GOTO( server_failed, "[RTT] Server offers image '%s', requested '%s'", name, image->lower_name );
+ if ( name == NULL || strcmp( name, image->name ) != 0 ) {
+ ERROR_GOTO( server_failed, "[RTT] Server offers image '%s', requested '%s'", name, image->name );
}
if ( rid != image->rid ) {
ERROR_GOTO( server_failed, "[RTT] Server provides rid %d, requested was %d (%s)",
- (int)rid, (int)image->rid, image->lower_name );
+ (int)rid, (int)image->rid, image->name );
}
if ( imageSize != image->virtualFilesize ) {
ERROR_GOTO( server_failed, "[RTT] Remote size: %" PRIu64 ", expected: %" PRIu64 " (%s)",
- imageSize, image->virtualFilesize, image->lower_name );
+ imageSize, image->virtualFilesize, image->name );
}
// Request first block (NOT random!) ++++++++++++++++++++++++++++++
fixup_request( request );
if ( !dnbd3_get_block( sock, 0, DNBD3_BLOCK_SIZE, 0 ) ) {
- ERROR_GOTO( server_failed, "[RTT] Could not request first block for %s", image->lower_name );
+ ERROR_GOTO( server_failed, "[RTT] Could not request first block for %s", image->name );
}
// See if requesting the block succeeded ++++++++++++++++++++++
if ( !dnbd3_get_reply( sock, &reply ) ) {
char buf[100] = { 0 };
host_to_string( &servers[itAlt], buf, 100 );
ERROR_GOTO( server_failed, "[RTT] Received corrupted reply header (%s) after CMD_GET_BLOCK (%s)",
- buf, image->lower_name );
+ buf, image->name );
}
// check reply header
if ( reply.cmd != CMD_GET_BLOCK || reply.size != DNBD3_BLOCK_SIZE ) {
ERROR_GOTO( server_failed, "[RTT] Reply to first block request is %d bytes for %s",
- reply.size, image->lower_name );
+ reply.size, image->name );
}
if ( recv( sock, buffer, DNBD3_BLOCK_SIZE, MSG_WAITALL ) != DNBD3_BLOCK_SIZE ) {
- ERROR_GOTO( server_failed, "[RTT] Could not read first block payload for %s", image->lower_name );
+ ERROR_GOTO( server_failed, "[RTT] Could not read first block payload for %s", image->name );
}
clock_gettime( CLOCK_MONOTONIC_RAW, &end );
// Measurement done - everything fine so far
@@ -505,7 +505,7 @@ static void *altservers_main(void *data UNUSED)
// Done testing all servers. See if we should switch
if ( bestSock != -1 && (uplink->fd == -1 || (bestRtt < 10000000 && RTT_THRESHOLD_FACTOR(currentRtt) > bestRtt)) ) {
// yep
- logadd( LOG_DEBUG1, "Change @ %s - best: %uµs, current: %uµs\n", image->lower_name, bestRtt, currentRtt );
+ logadd( LOG_DEBUG1, "Change @ %s - best: %uµs, current: %uµs\n", image->name, bestRtt, currentRtt );
spin_lock( &uplink->rttLock );
uplink->betterFd = bestSock;
uplink->betterServer = servers[bestIndex];
diff --git a/src/server/globals.h b/src/server/globals.h
index c67b5a6..b0380fa 100644
--- a/src/server/globals.h
+++ b/src/server/globals.h
@@ -94,13 +94,13 @@ typedef struct
/**
* Image struct. An image path could be something like
* /mnt/images/rz/zfs/Windows7 ZfS.vmdk.r1
- * and the lower_name would then be
+ * and the name would then be
* rz/zfs/windows7 zfs.vmdk
*/
struct _dnbd3_image
{
char *path; // absolute path of the image
- char *lower_name; // relative path, all lowercase, minus revision ID
+ char *name; // public name of the image (usually relative path minus revision ID)
dnbd3_connection_t *uplink; // pointer to a server connection
uint8_t *cache_map; // cache map telling which parts are locally cached, NULL if complete
uint64_t virtualFilesize; // virtual size of image (real size rounded up to multiple of 4k)
@@ -116,7 +116,7 @@ struct _dnbd3_image
int completenessEstimate; // Completeness estimate in percent
int users; // clients currently using this image
int id; // Unique ID of this image. Only unique in the context of this running instance of DNBD3-Server
- bool working; // true if image exists and completeness is == 100% or a working upstream proxy is connected
+ bool working; // true if image exists and completeness is == 100% or a working upstream proxy is connected
pthread_spinlock_t lock;
};
diff --git a/src/server/helper.c b/src/server/helper.c
index 5201744..bb2eb9b 100644
--- a/src/server/helper.c
+++ b/src/server/helper.c
@@ -103,14 +103,6 @@ bool host_to_string(const dnbd3_host_t *host, char *target, size_t targetlen)
return true;
}
-void strtolower(char *string)
-{
- while ( *string ) {
- if ( *string >= 'A' && *string <= 'Z' ) *string += 32;
- ++string;
- }
-}
-
void remove_trailing_slash(char *string)
{
char *ptr = string + strlen( string ) - 1;
diff --git a/src/server/helper.h b/src/server/helper.h
index 1fb9835..fd63f7a 100644
--- a/src/server/helper.h
+++ b/src/server/helper.h
@@ -13,7 +13,6 @@
bool parse_address(char *string, dnbd3_host_t *host);
bool host_to_string(const dnbd3_host_t *host, char *target, size_t targetlen);
-void strtolower(char *string);
void remove_trailing_slash(char *string);
void trim_right(char * const string);
void setThreadName(const char *name);
diff --git a/src/server/image.c b/src/server/image.c
index 875117b..9643abc 100644
--- a/src/server/image.c
+++ b/src/server/image.c
@@ -268,13 +268,11 @@ dnbd3_image_t* image_get(char *name, uint16_t revision, bool checkIfWorking)
// Simple sanity check
const int len = strlen( name );
if ( len == 0 || name[len - 1] == '/' || name[0] == '/' ) return NULL ;
- // Always use lowercase name
- strtolower( name );
// Go through array
spin_lock( &imageListLock );
for (i = 0; i < _num_images; ++i) {
dnbd3_image_t * const image = _images[i];
- if ( image == NULL || strcmp( image->lower_name, name ) != 0 ) continue;
+ if ( image == NULL || strcmp( image->name, name ) != 0 ) continue;
if ( revision == image->rid ) {
candidate = image;
break;
@@ -353,7 +351,7 @@ dnbd3_image_t* image_get(char *name, uint16_t revision, bool checkIfWorking)
} else {
// Seems everything is fine again \o/
candidate->working = true;
- logadd( LOG_INFO, "Changed state of %s:%d to 'working'", candidate->lower_name, candidate->rid );
+ logadd( LOG_INFO, "Changed state of %s:%d to 'working'", candidate->name, candidate->rid );
}
}
}
@@ -542,7 +540,7 @@ static dnbd3_image_t* image_free(dnbd3_image_t *image)
{
assert( image != NULL );
if ( !_shutdown ) {
- logadd( LOG_INFO, "Freeing image %s:%d", image->lower_name, (int)image->rid );
+ logadd( LOG_INFO, "Freeing image %s:%d", image->name, (int)image->rid );
}
//
image_saveCacheMap( image );
@@ -551,7 +549,7 @@ static dnbd3_image_t* image_free(dnbd3_image_t *image)
free( image->cache_map );
free( image->crc32 );
free( image->path );
- free( image->lower_name );
+ free( image->name );
spin_unlock( &image->lock );
if ( image->cacheFd != -1 ) close( image->cacheFd );
if ( image->readFd != -1 ) close( image->readFd );
@@ -695,8 +693,6 @@ static bool image_load(char *base, char *path, int withUplink)
goto load_error;
}
- strtolower( imgName );
-
// Get pointer to already existing image if possible
existing = image_get( imgName, revision, true );
@@ -742,16 +738,16 @@ static bool image_load(char *base, char *path, int withUplink)
// Compare data just loaded to identical image we apparently already loaded
if ( existing != NULL ) {
if ( existing->realFilesize != realFilesize ) {
- logadd( LOG_WARNING, "Size of image '%s:%d' has changed.", existing->lower_name, (int)existing->rid );
+ logadd( LOG_WARNING, "Size of image '%s:%d' has changed.", existing->name, (int)existing->rid );
// Image will be replaced below
} else if ( existing->crc32 != NULL && crc32list != NULL
&& memcmp( existing->crc32, crc32list, sizeof(uint32_t) * hashBlockCount ) != 0 ) {
- logadd( LOG_WARNING, "CRC32 list of image '%s:%d' has changed.", existing->lower_name, (int)existing->rid );
+ logadd( LOG_WARNING, "CRC32 list of image '%s:%d' has changed.", existing->name, (int)existing->rid );
logadd( LOG_WARNING, "The image will be reloaded, but you should NOT replace existing images while the server is running." );
logadd( LOG_WARNING, "Actually even if it's not running this should never be done. Use a new RID instead!" );
// Image will be replaced below
} else if ( existing->crc32 == NULL && crc32list != NULL ) {
- logadd( LOG_INFO, "Found CRC-32 list for already loaded image '%s:%d', adding...", existing->lower_name, (int)existing->rid );
+ logadd( LOG_INFO, "Found CRC-32 list for already loaded image '%s:%d', adding...", existing->name, (int)existing->rid );
existing->crc32 = crc32list;
existing->masterCrc32 = masterCrc;
crc32list = NULL;
@@ -759,7 +755,7 @@ static bool image_load(char *base, char *path, int withUplink)
goto load_error; // Keep existing
} else if ( existing->cache_map != NULL && cache_map == NULL ) {
// Just ignore that fact, if replication is really complete the cache map will be removed anyways
- logadd( LOG_INFO, "Image '%s:%d' has no cache map on disk!", existing->lower_name, (int)existing->rid );
+ logadd( LOG_INFO, "Image '%s:%d' has no cache map on disk!", existing->name, (int)existing->rid );
function_return = true;
goto load_error; // Keep existing
} else {
@@ -776,7 +772,7 @@ static bool image_load(char *base, char *path, int withUplink)
// Load fresh image
dnbd3_image_t *image = calloc( 1, sizeof(dnbd3_image_t) );
image->path = strdup( path );
- image->lower_name = strdup( imgName );
+ image->name = strdup( imgName );
image->cache_map = cache_map;
image->crc32 = crc32list;
image->masterCrc32 = masterCrc;
@@ -844,7 +840,7 @@ static bool image_load(char *base, char *path, int withUplink)
image->readFd = fdImage;
fdImage = -1;
spin_unlock( &imageListLock );
- logadd( LOG_DEBUG1, "Loaded image '%s:%d'\n", image->lower_name, (int)image->rid );
+ logadd( LOG_DEBUG1, "Loaded image '%s:%d'\n", image->name, (int)image->rid );
function_return = true;
@@ -1403,8 +1399,8 @@ json_t* image_getListAsJson()
spin_unlock( &image->lock );
jsonImage = json_pack( "{sisssisisi}",
- "id", image->id, // id, lower_name, rid never change, so access them without locking
- "name", image->lower_name,
+ "id", image->id, // id, name, rid never change, so access them without locking
+ "name", image->name,
"rid", (int) image->rid,
"users", users,
"complete", completeness );
@@ -1554,7 +1550,7 @@ static bool image_ensureDiskSpace(uint64_t size)
}
oldest = image_lock( oldest );
if ( oldest == NULL ) continue; // Image freed in the meantime? Try again
- logadd( LOG_INFO, "'%s:%d' has to go!", oldest->lower_name, (int)oldest->rid );
+ logadd( LOG_INFO, "'%s:%d' has to go!", oldest->name, (int)oldest->rid );
unlink( oldest->path );
size_t len = strlen( oldest->path ) + 5 + 1;
char buffer[len];
diff --git a/src/server/integrity.c b/src/server/integrity.c
index c697be8..d673a9d 100644
--- a/src/server/integrity.c
+++ b/src/server/integrity.c
@@ -139,7 +139,7 @@ static void* integrity_main(void * data UNUSED)
memcpy( buffer, image->crc32, required );
spin_unlock( &image->lock );
if ( !image_checkBlocksCrc32( image->readFd, (uint32_t*)buffer, blocks, fileSize ) ) {
- logadd( LOG_WARNING, "Hash check for block %d of %s failed!", blocks[0], image->lower_name );
+ logadd( LOG_WARNING, "Hash check for block %d of %s failed!", blocks[0], image->name );
image_updateCachemap( image, blocks[0] * HASH_BLOCK_SIZE, (blocks[0] + 1) * HASH_BLOCK_SIZE, false );
}
pthread_mutex_lock( &integrityQueueLock );
diff --git a/src/server/net.c b/src/server/net.c
index 8929937..93145a5 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -228,7 +228,7 @@ void *net_client_handler(void *dnbd3_client)
image_file = image->readFd;
serializer_reset_write( &payload );
serializer_put_uint16( &payload, PROTOCOL_VERSION );
- serializer_put_string( &payload, image->lower_name );
+ serializer_put_string( &payload, image->name );
serializer_put_uint16( &payload, (uint16_t)image->rid );
serializer_put_uint64( &payload, image->virtualFilesize );
reply.cmd = CMD_SELECT_IMAGE;
@@ -331,7 +331,7 @@ void *net_client_handler(void *dnbd3_client)
if ( !isCached ) {
if ( !uplink_request( client, request.handle, request.offset, request.size ) ) {
logadd( LOG_DEBUG1, "Could not relay uncached request from %s to upstream proxy, disabling image %s:%d",
- client->hostName, image->lower_name, image->rid );
+ client->hostName, image->name, image->rid );
image->working = false;
goto exit_client_cleanup;
}
@@ -375,7 +375,7 @@ void *net_client_handler(void *dnbd3_client)
client->hostName, (int)done, (int)realBytes, err );
}
if ( err == EBADF || err == EFAULT || err == EINVAL || err == EIO ) {
- logadd( LOG_INFO, "Disabling %s:%d", image->lower_name, image->rid );
+ logadd( LOG_INFO, "Disabling %s:%d", image->name, image->rid );
image->working = false;
}
}
diff --git a/src/server/uplink.c b/src/server/uplink.c
index e0bdcae..3f14266 100644
--- a/src/server/uplink.c
+++ b/src/server/uplink.c
@@ -65,7 +65,7 @@ bool uplink_init(dnbd3_image_t *image, int sock, dnbd3_host_t *host)
return true; // There's already an uplink, so should we consider this success or failure?
}
if ( image->cache_map == NULL ) {
- logadd( LOG_WARNING, "Uplink was requested for image %s, but it is already complete", image->lower_name );
+ logadd( LOG_WARNING, "Uplink was requested for image %s, but it is already complete", image->name );
goto failure;
}
link = image->uplink = calloc( 1, sizeof(dnbd3_connection_t) );
@@ -211,7 +211,7 @@ bool uplink_request(dnbd3_client_t *client, uint64_t handle, uint64_t start, uin
if ( foundExisting != -1 && existingType != ULR_NEW && freeSlot > foundExisting ) foundExisting = -1;
#ifdef _DEBUG
if ( foundExisting != -1 ) {
- logadd( LOG_DEBUG2, "%p (%s) Found existing request of type %s at slot %d, attaching in slot %d.\n", (void*)uplink, uplink->image->lower_name, existingType == ULR_NEW ? "ULR_NEW" : "ULR_PENDING", foundExisting, freeSlot );
+ logadd( LOG_DEBUG2, "%p (%s) Found existing request of type %s at slot %d, attaching in slot %d.\n", (void*)uplink, uplink->image->name, existingType == ULR_NEW ? "ULR_NEW" : "ULR_PENDING", foundExisting, freeSlot );
logadd( LOG_DEBUG2, "Original %" PRIu64 "-%" PRIu64 " (%p)\n"
"New %" PRIu64 "-%" PRIu64 " (%p)\n",
uplink->queue[foundExisting].from, uplink->queue[foundExisting].to, (void*)uplink->queue[foundExisting].client,
@@ -295,7 +295,7 @@ static void* uplink_mainloop(void *data)
link->replicatedLastBlock = false; // Reset this to be safe - request could've been sent but reply was never received
buffer[0] = '@';
if ( host_to_string( &link->currentServer, buffer + 1, sizeof(buffer) - 1 ) ) {
- logadd( LOG_DEBUG1, "(Uplink %s) Now connected to %s\n", link->image->lower_name, buffer + 1 );
+ logadd( LOG_DEBUG1, "(Uplink %s) Now connected to %s\n", link->image->name, buffer + 1 );
setThreadName( buffer );
}
// If we don't have a crc32 list yet, see if the new server has one
@@ -352,7 +352,7 @@ static void* uplink_mainloop(void *data)
if ( events[i].data.fd == link->signal ) {
// Event on the signal fd -> a client requests data
if ( signal_clear( link->signal ) == SIGNAL_ERROR ) {
- logadd( LOG_WARNING, "Errno on eventfd on uplink for %s! Things will break!", link->image->lower_name );
+ logadd( LOG_WARNING, "Errno on eventfd on uplink for %s! Things will break!", link->image->name );
}
if ( link->fd != -1 ) {
// Uplink seems fine, relay requests to it...
@@ -390,7 +390,7 @@ static void* uplink_mainloop(void *data)
// It seems it's time for a check
if ( image_isComplete( link->image ) ) {
// Quit work if image is complete
- logadd( LOG_INFO, "Replication of %s complete.", link->image->lower_name );
+ logadd( LOG_INFO, "Replication of %s complete.", link->image->name );
image_markComplete( link->image );
goto cleanup;
} else {
@@ -415,7 +415,7 @@ static void* uplink_mainloop(void *data)
for (i = 0; i < link->queueLen; ++i) {
if ( link->queue[i].status != ULR_FREE && link->queue[i].entered < deadline ) {
snprintf( buffer, sizeof(buffer), "[DEBUG %p] Starving request slot %d detected:\n"
- "%s\n(from %" PRIu64 " to %" PRIu64 ", status: %d)\n", (void*)link, i, link->queue[i].client->image->lower_name,
+ "%s\n(from %" PRIu64 " to %" PRIu64 ", status: %d)\n", (void*)link, i, link->queue[i].client->image->name,
link->queue[i].from, link->queue[i].to, link->queue[i].status );
link->queue[i].status = ULR_NEW;
resend = true;
@@ -594,7 +594,7 @@ static void uplink_handleReceive(dnbd3_connection_t *link)
if ( done > 0 ) image_updateCachemap( link->image, start, start + done, true );
if ( ret == -1 && ( errno == EBADF || errno == EINVAL || errno == EIO ) ) {
logadd( LOG_WARNING, "Error writing received data for %s:%d; disabling caching.",
- link->image->lower_name, (int)link->image->rid );
+ link->image->name, (int)link->image->rid );
const int fd = link->image->cacheFd;
link->image->cacheFd = -1;
close( fd );
@@ -655,7 +655,7 @@ static void uplink_handleReceive(dnbd3_connection_t *link)
spin_unlock( &link->queueLock );
#ifdef _DEBUG
if ( !served && start != link->replicationHandle )
- logadd( LOG_DEBUG2, "%p, %s -- Unmatched reply: %" PRIu64 " to %" PRIu64, (void*)link, link->image->lower_name, start, end );
+ logadd( LOG_DEBUG2, "%p, %s -- Unmatched reply: %" PRIu64 " to %" PRIu64, (void*)link, link->image->name, start, end );
#endif
if ( start == link->replicationHandle ) link->replicationHandle = 0;
}
@@ -702,7 +702,7 @@ static void uplink_addCrc32(dnbd3_connection_t *uplink)
uint32_t lists_crc = crc32( 0L, Z_NULL, 0 );
lists_crc = crc32( lists_crc, (Bytef*)buffer, bytes );
if ( lists_crc != masterCrc ) {
- logadd( LOG_WARNING, "Received corrupted crc32 list from uplink server (%s)!", uplink->image->lower_name );
+ logadd( LOG_WARNING, "Received corrupted crc32 list from uplink server (%s)!", uplink->image->name );
free( buffer );
return;
}
diff --git a/src/shared/protocol.h b/src/shared/protocol.h
index 3539c21..a2f79f4 100644
--- a/src/shared/protocol.h
+++ b/src/shared/protocol.h
@@ -43,14 +43,14 @@ static inline bool dnbd3_get_reply(int sock, dnbd3_reply_t *reply)
return ret == REPLY_OK;
}
-static inline bool dnbd3_select_image(int sock, const char *lower_name, uint16_t rid, uint8_t flags8)
+static inline bool dnbd3_select_image(int sock, const char *name, uint16_t rid, uint8_t flags8)
{
serialized_buffer_t serialized;
dnbd3_request_t request;
struct iovec iov[2];
serializer_reset_write( &serialized );
serializer_put_uint16( &serialized, PROTOCOL_VERSION );
- serializer_put_string( &serialized, lower_name );
+ serializer_put_string( &serialized, name );
serializer_put_uint16( &serialized, rid );
serializer_put_uint8( &serialized, flags8 );
const ssize_t len = serializer_get_written_length( &serialized );