summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2021-04-14 14:55:26 +0200
committerSimon Rettberg2021-04-14 14:55:26 +0200
commit8b303a6c68079a3db781b2a361707719406279e3 (patch)
treed731b92624654c0cbe415e4745763a48b11c63e7
parent[SERVER] Set TCP_NODELAY on outgoing connections (diff)
downloaddnbd3-8b303a6c68079a3db781b2a361707719406279e3.tar.gz
dnbd3-8b303a6c68079a3db781b2a361707719406279e3.tar.xz
dnbd3-8b303a6c68079a3db781b2a361707719406279e3.zip
[SERVER] Mark uplink requests with BGR/prefetch flags and handle them
Incoming requests from clients might actually be prefetch jobs from another downstream proxy. Don't do prefetching for those, as this would cascade upwars in the proxy chain (prefetch for a prefetch of a prefetch) Incoming requests might also be background replication. Don't relay those if we're not configured for background replication as well.
-rw-r--r--src/server/uplink.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/src/server/uplink.c b/src/server/uplink.c
index dedaa17..11c9d05 100644
--- a/src/server/uplink.c
+++ b/src/server/uplink.c
@@ -18,6 +18,8 @@
#include <unistd.h>
#include <stdatomic.h>
+static const uint8_t HOP_FLAG_BGR = 0x80;
+static const uint8_t HOP_FLAG_PREFETCH = 0x40;
#define FILE_BYTES_PER_MAP_BYTE ( DNBD3_BLOCK_SIZE * 8 )
#define MAP_BYTES_PER_HASH_BLOCK (int)( HASH_BLOCK_SIZE / FILE_BYTES_PER_MAP_BYTE )
#define MAP_INDEX_HASH_START_MASK ( ~(int)( MAP_BYTES_PER_HASH_BLOCK - 1 ) )
@@ -251,8 +253,8 @@ void uplink_removeEntry(dnbd3_uplink_t *uplink, void *data, uplink_callback call
bool uplink_requestClient(dnbd3_client_t *client, uplink_callback callback, uint64_t handle, uint64_t start, uint32_t length, uint8_t hops)
{
assert( client != NULL && callback != NULL );
- if ( hops > 200 ) { // This is just silly
- logadd( LOG_WARNING, "Refusing to relay a request that has > 200 hops" );
+ if ( ( hops & 0x3f ) > 60 ) { // This is just silly
+ logadd( LOG_WARNING, "Refusing to relay a request that has > 60 hops" );
return false;
}
dnbd3_uplink_t *uplink = ref_get_uplink( &client->image->uplinkref );
@@ -338,6 +340,12 @@ static bool uplink_requestInternal(dnbd3_uplink_t *uplink, void *data, uplink_ca
{
assert( uplink != NULL );
assert( data == NULL || callback != NULL );
+ if ( ( hops & HOP_FLAG_BGR ) // This is a background replication request
+ && _backgroundReplication != BGR_FULL ) { // Deny if we're not doing BGR
+ // TODO: Allow BGR_HASHBLOCK too, but only if hash block isn't completely empty
+ logadd( LOG_DEBUG2, "Dopping client because of BGR policy" );
+ return false;
+ }
if ( uplink->shutdown ) {
logadd( LOG_DEBUG1, "Uplink request for image with uplink shutting down" );
return false;
@@ -348,8 +356,14 @@ static bool uplink_requestInternal(dnbd3_uplink_t *uplink, void *data, uplink_ca
return false;
}
- req_t req, preReq;
hops++;
+ if ( callback == NULL ) {
+ // Set upper-most bit for replication requests that we fire
+ // In client mode, at least set prefetch flag to prevent prefetch cascading
+ hops |= _pretendClient ? HOP_FLAG_PREFETCH : HOP_FLAG_BGR;
+ }
+
+ req_t req, preReq;
dnbd3_queue_entry_t *request = NULL, *last = NULL, *pre = NULL;
bool isNew;
const uint64_t end = start + length;
@@ -447,6 +461,7 @@ static bool uplink_requestInternal(dnbd3_uplink_t *uplink, void *data, uplink_ca
// async prefetching in another thread was sometimes so slow that we'd process
// another request from the same client before the prefetch job would execute.
if ( callback != NULL && ( isNew || request->clients == NULL || request->clients->data == data )
+ && !( hops & (HOP_FLAG_BGR | HOP_FLAG_PREFETCH) ) // No cascading of prefetches
&& end == request->to && length <= _maxPrefetch ) {
// Only if this is a client request, and the !! end boundary matches exactly !!
// (See above for reason why)
@@ -464,7 +479,7 @@ static bool uplink_requestInternal(dnbd3_uplink_t *uplink, void *data, uplink_ca
pre->handle = preReq.handle = ++uplink->queueId;
pre->from = preReq.start;
pre->to = preReq.end;
- pre->hopCount = hops;
+ pre->hopCount = hops | HOP_FLAG_PREFETCH;
pre->sent = true; // Optimistic; would be set to false on failure
pre->clients = NULL;
#ifdef DEBUG
@@ -498,7 +513,7 @@ static bool uplink_requestInternal(dnbd3_uplink_t *uplink, void *data, uplink_ca
ret1 = requestBlock( uplink, &req, hops );
}
if ( pre != NULL ) {
- ret2 = requestBlock( uplink, &preReq, hops );
+ ret2 = requestBlock( uplink, &preReq, hops | HOP_FLAG_PREFETCH );
}
if ( !ret1 || !ret2 ) { // Set with send locked
uplink->image->problem.uplink = true;