aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/ipxe/peermux.h7
-rw-r--r--src/net/peermux.c32
2 files changed, 30 insertions, 9 deletions
diff --git a/src/include/ipxe/peermux.h b/src/include/ipxe/peermux.h
index 54acbfe..8970759 100644
--- a/src/include/ipxe/peermux.h
+++ b/src/include/ipxe/peermux.h
@@ -18,6 +18,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/xferbuf.h>
#include <ipxe/pccrc.h>
+/** Minimum number of concurrent block downloads */
+#define PEERMUX_MIN_BLOCKS 2
+
/** Maximum number of concurrent block downloads */
#define PEERMUX_MAX_BLOCKS 32
@@ -69,6 +72,10 @@ struct peerdist_multiplexer {
/** Block download initiation process */
struct process process;
+ /** Number of concurrent block downloads */
+ unsigned int count;
+ /** Maximum number of concurrent block downloads */
+ unsigned int limit;
/** List of busy block downloads */
struct list_head busy;
/** List of idle block downloads */
diff --git a/src/net/peermux.c b/src/net/peermux.c
index a391ed3..c354f21 100644
--- a/src/net/peermux.c
+++ b/src/net/peermux.c
@@ -92,7 +92,8 @@ static int peermux_progress ( struct peerdist_multiplexer *peermux,
if ( stats->total ) {
percentage = ( ( 100 * stats->local ) / stats->total );
snprintf ( progress->message, sizeof ( progress->message ),
- "%3d%% from %d peers", percentage, stats->peers );
+ "%3d%% from %d peers (x%d)", percentage,
+ stats->peers, peermux->limit );
}
return 0;
@@ -184,14 +185,17 @@ static void peermux_step ( struct peerdist_multiplexer *peermux ) {
unsigned int next_block;
int rc;
- /* Stop initiation process if all block downloads are busy */
- peermblk = list_first_entry ( &peermux->idle,
- struct peerdist_multiplexed_block, list );
- if ( ! peermblk ) {
+ /* Stop initiation process if we have reached the concurrency limit */
+ if ( peermux->count >= peermux->limit ) {
process_del ( &peermux->process );
return;
}
+ /* Get next available idle block download */
+ peermblk = list_first_entry ( &peermux->idle,
+ struct peerdist_multiplexed_block, list );
+ assert ( peermblk != NULL );
+
/* Increment block index */
next_block = ( block->index + 1 );
@@ -251,6 +255,7 @@ static void peermux_step ( struct peerdist_multiplexer *peermux ) {
/* Move to list of busy block downloads */
list_del ( &peermblk->list );
list_add_tail ( &peermblk->list, &peermux->busy );
+ peermux->count++;
return;
@@ -319,12 +324,19 @@ static void peermux_block_stat ( struct peerdist_multiplexed_block *peermblk,
if ( count > stats->peers )
stats->peers = count;
- /* Update block counts */
- if ( peer )
+ /* Update block counts and concurrency limit */
+ if ( peer ) {
stats->local++;
+ if ( peermux->limit < PEERMUX_MAX_BLOCKS )
+ peermux->limit++;
+ } else {
+ if ( peermux->limit > PEERMUX_MIN_BLOCKS )
+ peermux->limit--;
+ }
stats->total++;
- DBGC2 ( peermux, "PEERMUX %p downloaded %d/%d from %d peers\n",
- peermux, stats->local, stats->total, stats->peers );
+ DBGC2 ( peermux, "PEERMUX %p downloaded %d/%d from %d peers (x%d)\n",
+ peermux, stats->local, stats->total, stats->peers,
+ peermux->limit );
}
/**
@@ -340,6 +352,7 @@ static void peermux_block_close ( struct peerdist_multiplexed_block *peermblk,
/* Move to list of idle downloads */
list_del ( &peermblk->list );
list_add_tail ( &peermblk->list, &peermux->idle );
+ peermux->count--;
/* If any error occurred, terminate the whole multiplexer */
if ( rc != 0 ) {
@@ -426,6 +439,7 @@ int peermux_filter ( struct interface *xfer, struct interface *info,
&peermux->cache.info.raw.data );
process_init_stopped ( &peermux->process, &peermux_process_desc,
&peermux->refcnt );
+ peermux->limit = PEERMUX_MIN_BLOCKS;
INIT_LIST_HEAD ( &peermux->busy );
INIT_LIST_HEAD ( &peermux->idle );
for ( i = 0 ; i < PEERMUX_MAX_BLOCKS ; i++ ) {