mirror of https://github.com/ipxe/ipxe.git
[slam] Request all remaining blocks if we run out of space for the blocklist
In a SLAM NACK packet, if we run out of space to represent the missing-block list, then indicate all remaining blocks as missing. This avoids the need to wait for the one-second timeout before receiving the blocks that otherwise wouldn't have been requested due to running out of space.pull/1/head
parent
1e5c2d48cb
commit
2456b9b4ba
|
@ -191,14 +191,14 @@ static void slam_finished ( struct slam_request *slam, int rc ) {
|
||||||
* @v slam SLAM request
|
* @v slam SLAM request
|
||||||
* @v iobuf I/O buffer
|
* @v iobuf I/O buffer
|
||||||
* @v value Value to add
|
* @v value Value to add
|
||||||
* @ret rc Return status code
|
* @v reserved Length of reserved space at end of buffer
|
||||||
|
* @ret len Length of value, or negative error.
|
||||||
*
|
*
|
||||||
* Adds a variable-length value to the end of an I/O buffer. Will
|
* Adds a variable-length value to the end of an I/O buffer.
|
||||||
* refuse to use the last byte of the I/O buffer; this is to allow
|
|
||||||
* space for the terminating NUL.
|
|
||||||
*/
|
*/
|
||||||
static int slam_put_value ( struct slam_request *slam,
|
static int slam_put_value ( struct slam_request *slam,
|
||||||
struct io_buffer *iobuf, unsigned long value ) {
|
struct io_buffer *iobuf, unsigned long value,
|
||||||
|
size_t reserved ) {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t len;
|
size_t len;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -207,7 +207,7 @@ static int slam_put_value ( struct slam_request *slam,
|
||||||
* leave at least one byte in the I/O buffer.
|
* leave at least one byte in the I/O buffer.
|
||||||
*/
|
*/
|
||||||
len = ( ( flsl ( value ) + 10 ) / 8 );
|
len = ( ( flsl ( value ) + 10 ) / 8 );
|
||||||
if ( len >= iob_tailroom ( iobuf ) ) {
|
if ( ( len + reserved ) > iob_tailroom ( iobuf ) ) {
|
||||||
DBGC2 ( slam, "SLAM %p cannot add %d-byte value\n",
|
DBGC2 ( slam, "SLAM %p cannot add %d-byte value\n",
|
||||||
slam, len );
|
slam, len );
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
|
@ -227,7 +227,7 @@ static int slam_put_value ( struct slam_request *slam,
|
||||||
*data |= ( len << 5 );
|
*data |= ( len << 5 );
|
||||||
assert ( value == 0 );
|
assert ( value == 0 );
|
||||||
|
|
||||||
return 0;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -239,13 +239,16 @@ static int slam_put_value ( struct slam_request *slam,
|
||||||
*/
|
*/
|
||||||
static int slam_build_block_list ( struct slam_request *slam,
|
static int slam_build_block_list ( struct slam_request *slam,
|
||||||
struct io_buffer *iobuf ) {
|
struct io_buffer *iobuf ) {
|
||||||
unsigned int block;
|
unsigned long block;
|
||||||
unsigned int block_count;
|
unsigned long block_count;
|
||||||
int block_present;
|
int block_present;
|
||||||
int last_block_present;
|
int last_block_present;
|
||||||
|
int len;
|
||||||
|
size_t last_len = 0;
|
||||||
|
unsigned long last_block_count = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
DBGC ( slam, "SLAM %p asking for ", slam );
|
DBGC ( slam, "SLAM %p asking for", slam );
|
||||||
|
|
||||||
/* Walk bitmap to construct list */
|
/* Walk bitmap to construct list */
|
||||||
block_count = 0;
|
block_count = 0;
|
||||||
|
@ -253,27 +256,43 @@ static int slam_build_block_list ( struct slam_request *slam,
|
||||||
for ( block = 0 ; block < slam->num_blocks ; block++ ) {
|
for ( block = 0 ; block < slam->num_blocks ; block++ ) {
|
||||||
block_present = ( !! bitmap_test ( &slam->bitmap, block ) );
|
block_present = ( !! bitmap_test ( &slam->bitmap, block ) );
|
||||||
if ( block_present != last_block_present ) {
|
if ( block_present != last_block_present ) {
|
||||||
if ( ( rc = slam_put_value ( slam, iobuf,
|
if ( ( len = slam_put_value ( slam, iobuf, block_count,
|
||||||
block_count ) ) != 0 ) {
|
( sizeof ( block ) + 1 ) ) ) < 0 )
|
||||||
DBGC ( slam, "...\n" );
|
goto truncated;
|
||||||
return rc;
|
DBGC ( slam, "%c%ld",
|
||||||
}
|
|
||||||
DBGC ( slam, "%c%d",
|
|
||||||
( last_block_present ? ' ' : '-' ),
|
( last_block_present ? ' ' : '-' ),
|
||||||
( last_block_present ? block : block - 1 ) );
|
( last_block_present ? block : block - 1 ) );
|
||||||
block_count = 0;
|
last_len = len;
|
||||||
|
last_block_count = block_count;
|
||||||
last_block_present = block_present;
|
last_block_present = block_present;
|
||||||
|
block_count = 0;
|
||||||
}
|
}
|
||||||
block_count++;
|
block_count++;
|
||||||
}
|
}
|
||||||
if ( ( rc = slam_put_value ( slam, iobuf, block_count ) ) != 0 ) {
|
if ( ( len = slam_put_value ( slam, iobuf, block_count,
|
||||||
DBGC ( slam, "...\n" );
|
( sizeof ( block ) + 1 ) ) ) < 0 )
|
||||||
return rc;
|
goto truncated;
|
||||||
}
|
DBGC ( slam, "%c%ld\n", ( last_block_present ? ' ' : '-' ),
|
||||||
DBGC ( slam, "%c%d\n", ( last_block_present ? ' ' : '-' ),
|
|
||||||
( last_block_present ? block : block - 1 ) );
|
( last_block_present ? block : block - 1 ) );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
truncated:
|
||||||
|
rc = len;
|
||||||
|
block -= block_count;
|
||||||
|
assert ( last_len != 0 ); /* Cannot truncate on first entry */
|
||||||
|
if ( last_block_present ) {
|
||||||
|
/* Replace last missing-blocks number */
|
||||||
|
DBGC ( slam, "#" );
|
||||||
|
iob_unput ( iobuf, last_len );
|
||||||
|
block -= last_block_count;
|
||||||
|
}
|
||||||
|
/* Report all remaining blocks as missing */
|
||||||
|
block_count = ( slam->num_blocks - block );
|
||||||
|
DBGC ( slam, "-%ld\n", ( slam->num_blocks - 1 ) );
|
||||||
|
len = slam_put_value ( slam, iobuf, block_count, 1 );
|
||||||
|
assert ( len > 0 );
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue