david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[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.
This commit is contained in:
Michael Brown 2008-06-10 12:30:43 +01:00
parent 1e5c2d48cb
commit 2456b9b4ba
1 changed files with 41 additions and 22 deletions

View File

@ -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;
} }
/** /**