From 8b303a6c68079a3db781b2a361707719406279e3 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 14 Apr 2021 14:55:26 +0200 Subject: [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. --- src/server/uplink.c | 25 ++++++++++++++++++++----- 1 file 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 #include +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; -- cgit v1.2.3-55-g7522