|
@@ -191,14 +191,14 @@ static void slam_finished ( struct slam_request *slam, int rc ) {
|
191
|
191
|
* @v slam SLAM request
|
192
|
192
|
* @v iobuf I/O buffer
|
193
|
193
|
* @v value Value to add
|
194
|
|
- * @ret rc Return status code
|
|
194
|
+ * @v reserved Length of reserved space at end of buffer
|
|
195
|
+ * @ret len Length of value, or negative error.
|
195
|
196
|
*
|
196
|
|
- * Adds a variable-length value to the end of an I/O buffer. Will
|
197
|
|
- * refuse to use the last byte of the I/O buffer; this is to allow
|
198
|
|
- * space for the terminating NUL.
|
|
197
|
+ * Adds a variable-length value to the end of an I/O buffer.
|
199
|
198
|
*/
|
200
|
199
|
static int slam_put_value ( struct slam_request *slam,
|
201
|
|
- struct io_buffer *iobuf, unsigned long value ) {
|
|
200
|
+ struct io_buffer *iobuf, unsigned long value,
|
|
201
|
+ size_t reserved ) {
|
202
|
202
|
uint8_t *data;
|
203
|
203
|
size_t len;
|
204
|
204
|
unsigned int i;
|
|
@@ -207,7 +207,7 @@ static int slam_put_value ( struct slam_request *slam,
|
207
|
207
|
* leave at least one byte in the I/O buffer.
|
208
|
208
|
*/
|
209
|
209
|
len = ( ( flsl ( value ) + 10 ) / 8 );
|
210
|
|
- if ( len >= iob_tailroom ( iobuf ) ) {
|
|
210
|
+ if ( ( len + reserved ) > iob_tailroom ( iobuf ) ) {
|
211
|
211
|
DBGC2 ( slam, "SLAM %p cannot add %d-byte value\n",
|
212
|
212
|
slam, len );
|
213
|
213
|
return -ENOBUFS;
|
|
@@ -227,7 +227,7 @@ static int slam_put_value ( struct slam_request *slam,
|
227
|
227
|
*data |= ( len << 5 );
|
228
|
228
|
assert ( value == 0 );
|
229
|
229
|
|
230
|
|
- return 0;
|
|
230
|
+ return len;
|
231
|
231
|
}
|
232
|
232
|
|
233
|
233
|
/**
|
|
@@ -239,13 +239,16 @@ static int slam_put_value ( struct slam_request *slam,
|
239
|
239
|
*/
|
240
|
240
|
static int slam_build_block_list ( struct slam_request *slam,
|
241
|
241
|
struct io_buffer *iobuf ) {
|
242
|
|
- unsigned int block;
|
243
|
|
- unsigned int block_count;
|
|
242
|
+ unsigned long block;
|
|
243
|
+ unsigned long block_count;
|
244
|
244
|
int block_present;
|
245
|
245
|
int last_block_present;
|
|
246
|
+ int len;
|
|
247
|
+ size_t last_len = 0;
|
|
248
|
+ unsigned long last_block_count = 0;
|
246
|
249
|
int rc;
|
247
|
250
|
|
248
|
|
- DBGC ( slam, "SLAM %p asking for ", slam );
|
|
251
|
+ DBGC ( slam, "SLAM %p asking for", slam );
|
249
|
252
|
|
250
|
253
|
/* Walk bitmap to construct list */
|
251
|
254
|
block_count = 0;
|
|
@@ -253,27 +256,43 @@ static int slam_build_block_list ( struct slam_request *slam,
|
253
|
256
|
for ( block = 0 ; block < slam->num_blocks ; block++ ) {
|
254
|
257
|
block_present = ( !! bitmap_test ( &slam->bitmap, block ) );
|
255
|
258
|
if ( block_present != last_block_present ) {
|
256
|
|
- if ( ( rc = slam_put_value ( slam, iobuf,
|
257
|
|
- block_count ) ) != 0 ) {
|
258
|
|
- DBGC ( slam, "...\n" );
|
259
|
|
- return rc;
|
260
|
|
- }
|
261
|
|
- DBGC ( slam, "%c%d",
|
|
259
|
+ if ( ( len = slam_put_value ( slam, iobuf, block_count,
|
|
260
|
+ ( sizeof ( block ) + 1 ) ) ) < 0 )
|
|
261
|
+ goto truncated;
|
|
262
|
+ DBGC ( slam, "%c%ld",
|
262
|
263
|
( last_block_present ? ' ' : '-' ),
|
263
|
264
|
( last_block_present ? block : block - 1 ) );
|
264
|
|
- block_count = 0;
|
|
265
|
+ last_len = len;
|
|
266
|
+ last_block_count = block_count;
|
265
|
267
|
last_block_present = block_present;
|
|
268
|
+ block_count = 0;
|
266
|
269
|
}
|
267
|
270
|
block_count++;
|
268
|
271
|
}
|
269
|
|
- if ( ( rc = slam_put_value ( slam, iobuf, block_count ) ) != 0 ) {
|
270
|
|
- DBGC ( slam, "...\n" );
|
271
|
|
- return rc;
|
272
|
|
- }
|
273
|
|
- DBGC ( slam, "%c%d\n", ( last_block_present ? ' ' : '-' ),
|
|
272
|
+ if ( ( len = slam_put_value ( slam, iobuf, block_count,
|
|
273
|
+ ( sizeof ( block ) + 1 ) ) ) < 0 )
|
|
274
|
+ goto truncated;
|
|
275
|
+ DBGC ( slam, "%c%ld\n", ( last_block_present ? ' ' : '-' ),
|
274
|
276
|
( last_block_present ? block : block - 1 ) );
|
275
|
277
|
|
276
|
278
|
return 0;
|
|
279
|
+
|
|
280
|
+ truncated:
|
|
281
|
+ rc = len;
|
|
282
|
+ block -= block_count;
|
|
283
|
+ assert ( last_len != 0 ); /* Cannot truncate on first entry */
|
|
284
|
+ if ( last_block_present ) {
|
|
285
|
+ /* Replace last missing-blocks number */
|
|
286
|
+ DBGC ( slam, "#" );
|
|
287
|
+ iob_unput ( iobuf, last_len );
|
|
288
|
+ block -= last_block_count;
|
|
289
|
+ }
|
|
290
|
+ /* Report all remaining blocks as missing */
|
|
291
|
+ block_count = ( slam->num_blocks - block );
|
|
292
|
+ DBGC ( slam, "-%ld\n", ( slam->num_blocks - 1 ) );
|
|
293
|
+ len = slam_put_value ( slam, iobuf, block_count, 1 );
|
|
294
|
+ assert ( len > 0 );
|
|
295
|
+ return rc;
|
277
|
296
|
}
|
278
|
297
|
|
279
|
298
|
/**
|