summaryrefslogtreecommitdiffstats
path: root/src/server/net.c
diff options
context:
space:
mode:
authorSimon Rettberg2020-03-13 16:03:29 +0100
committerSimon Rettberg2020-03-13 16:03:29 +0100
commit290d3478f245bb7d2112bb781286a9fbae42b983 (patch)
tree3cc825ae2249126d1f97f4e06592358ab9cfd81a /src/server/net.c
parent[SERVER] Fix data type (diff)
downloaddnbd3-290d3478f245bb7d2112bb781286a9fbae42b983.tar.gz
dnbd3-290d3478f245bb7d2112bb781286a9fbae42b983.tar.xz
dnbd3-290d3478f245bb7d2112bb781286a9fbae42b983.zip
[SERVER] Rewrite uplink queue handling
- Now uses linked lists instead of huge array - Does prefetch data on client requests - Can have multiple replication requests in-flight
Diffstat (limited to 'src/server/net.c')
-rw-r--r--src/server/net.c44
1 files changed, 11 insertions, 33 deletions
diff --git a/src/server/net.c b/src/server/net.c
index 954cb8a..9ba9dbc 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -197,6 +197,7 @@ void* net_handleNewConnection(void *clientPtr)
client->hostName[HOSTNAMELEN-1] = '\0';
mutex_unlock( &client->lock );
client->bytesSent = 0;
+ client->relayedCount = 0;
if ( !addToList( client ) ) {
freeClientStruct( client );
@@ -344,41 +345,18 @@ void* net_handleNewConnection(void *clientPtr)
// This is a proxyed image, check if we need to relay the request...
const uint64_t start = offset & ~(uint64_t)(DNBD3_BLOCK_SIZE - 1);
const uint64_t end = (offset + request.size + DNBD3_BLOCK_SIZE - 1) & ~(uint64_t)(DNBD3_BLOCK_SIZE - 1);
- const uint64_t firstByteInMap = start >> 15;
- const uint64_t lastByteInMap = (end - 1) >> 15;
- const uint8_t fb = (uint8_t)(0xff << ((start >> 12) & 7));
- const uint8_t lb = (uint8_t)(~(0xff << ((((end - 1) >> 12) & 7) + 1)));
- uint64_t pos;
- uint8_t b;
- bool isCached;
- if ( firstByteInMap == lastByteInMap ) { // Single byte to check, much simpler
- b = cache->map[firstByteInMap];
- isCached = ( b & ( fb & lb ) ) == ( fb & lb );
- } else {
- isCached = true;
- atomic_thread_fence( memory_order_acquire );
- // First byte
- if ( isCached ) {
- b = atomic_load_explicit( &cache->map[firstByteInMap], memory_order_relaxed );
- isCached = ( ( b & fb ) == fb );
- }
- // Last byte
- if ( isCached ) {
- b = atomic_load_explicit( &cache->map[lastByteInMap], memory_order_relaxed );
- isCached = ( ( b & lb ) == lb );
- }
- // Middle, must be all bits set (0xff)
- if ( isCached ) {
- for ( pos = firstByteInMap + 1; pos < lastByteInMap; ++pos ) {
- if ( atomic_load_explicit( &cache->map[pos], memory_order_relaxed ) != 0xff ) {
- isCached = false;
- break;
- }
+ if ( !image_isRangeCachedUnsafe( cache, start, end ) ) {
+ if ( unlikely( client->relayedCount > 250 ) ) {
+ logadd( LOG_DEBUG1, "Client is overloading uplink; throttling" );
+ for ( int i = 0; i < 100 && client->relayedCount > 200; ++i ) {
+ usleep( 10000 );
+ }
+ if ( client->relayedCount > 250 ) {
+ logadd( LOG_WARNING, "Could not lower client's uplink backlog; dropping client" );
+ goto exit_client_cleanup;
}
}
- }
- if ( !isCached ) {
- if ( !uplink_request( client, request.handle, offset, request.size, request.hops ) ) {
+ if ( !uplink_request( NULL, client, request.handle, offset, request.size, request.hops ) ) {
logadd( LOG_DEBUG1, "Could not relay uncached request from %s to upstream proxy for image %s:%d",
client->hostName, image->name, image->rid );
goto exit_client_cleanup;