Skip to content

Commit 2903ecc

Browse files
two-heartlidatong
authored andcommitted
store: bug fixes
* initialize the pool esp. pool->ver_top * added the pool to verify * fixed under allocation due to rounding-up after footprint calc, as discussed in #5911 by validating inputs * check and clear magic in delete * added handholding check and docs for calling _clear on an empty store * Use &fec->key.mr instead implicitly of relying on the layout of the key struct * Various other nits
1 parent 59fc48a commit 2903ecc

File tree

3 files changed

+40
-15
lines changed

3 files changed

+40
-15
lines changed

src/disco/shred/fd_shred_tile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -921,7 +921,7 @@ after_frag( fd_shred_ctx_t * ctx,
921921

922922
long shacq_start, shacq_end, shrel_end;
923923
FD_STORE_SHACQ_TIMED( ctx->store, shacq_start, shacq_end );
924-
fd_store_fec_t * fec = fd_store_insert( ctx->store, (uint)ctx->round_robin_id, (fd_hash_t *)fd_type_pun( &out_merkle_root ) );
924+
fd_store_fec_t * fec = fd_store_insert( ctx->store, ctx->round_robin_id, (fd_hash_t *)fd_type_pun( &out_merkle_root ) );
925925
FD_STORE_SHREL_TIMED( ctx->store, shrel_end );
926926

927927
for( ulong i=0UL; i<set->data_shred_cnt; i++ ) {

src/disco/store/fd_store.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ fd_store_new( void * shmem, ulong fec_max, ulong part_cnt ) {
3838
}
3939

4040
fd_memset( shmem, 0, footprint );
41-
fec_max = fd_ulong_pow2_up( fec_max ); /* required by map_chain */
4241

4342
/* This seed value is very important. We have fec_max chains in the
4443
map, which means the size of each partition of buckets should be
@@ -66,6 +65,10 @@ fd_store_new( void * shmem, ulong fec_max, ulong part_cnt ) {
6665
store->root = null;
6766

6867
fd_store_pool_t pool = fd_store_pool( store );
68+
if( FD_UNLIKELY( !fd_store_pool_new( shpool ) ) ) {
69+
FD_LOG_WARNING(( "fd_store_pool_new failed" ));
70+
return NULL;
71+
}
6972
fd_store_pool_reset( &pool, 0 );
7073

7174
FD_COMPILER_MFENCE();
@@ -115,7 +118,8 @@ fd_store_leave( fd_store_t const * store ) {
115118
}
116119

117120
void *
118-
fd_store_delete( void * store ) {
121+
fd_store_delete( void * shstore ) {
122+
fd_store_t * store = shstore;
119123

120124
if( FD_UNLIKELY( !store ) ) {
121125
FD_LOG_WARNING(( "NULL store" ));
@@ -127,6 +131,15 @@ fd_store_delete( void * store ) {
127131
return NULL;
128132
}
129133

134+
if( FD_UNLIKELY( store->magic!=FD_STORE_MAGIC ) ) {
135+
FD_LOG_WARNING(( "bad magic" ));
136+
return NULL;
137+
}
138+
139+
FD_COMPILER_MFENCE();
140+
FD_VOLATILE( store->magic ) = 0UL;
141+
FD_COMPILER_MFENCE();
142+
130143
return store;
131144
}
132145

@@ -207,14 +220,14 @@ fd_store_publish( fd_store_t * store,
207220
any descendants of those ancestors. */
208221

209222
while( FD_LIKELY( head ) ) {
210-
fd_store_fec_t * child = fd_store_pool_ele( &pool, head->child ); /* left-child */
223+
fd_store_fec_t * child = fd_store_pool_ele( &pool, head->child ); /* left-child */
211224
while( FD_LIKELY( child ) ) { /* iterate over children */
212225
if( FD_LIKELY( child != newr ) ) { /* stop at new root */
213226
tail->next = fd_store_map_idx_remove( map, &child->key, null, fec0 ); /* remove node from map to reuse `.next` */
214-
tail = fd_store_pool_ele( &pool, tail->next ); /* push onto BFS queue (so descendants can be pruned) */
227+
tail = fd_store_pool_ele( &pool, tail->next ); /* push onto BFS queue (so descendants can be pruned) */
215228
tail->next = null; /* clear map next */
216229
}
217-
child = fd_store_pool_ele( &pool, child->sibling ); /* right-sibling */
230+
child = fd_store_pool_ele( &pool, child->sibling ); /* right-sibling */
218231
}
219232
fd_store_fec_t * next = fd_store_pool_ele( &pool, head->next ); /* pophead */
220233
int err = fd_store_pool_release( &pool, head, BLOCKING ); /* release */
@@ -231,12 +244,18 @@ fd_store_publish( fd_store_t * store,
231244

232245
fd_store_t *
233246
fd_store_clear( fd_store_t * store ) {
247+
234248
fd_store_map_t * map = fd_store_map( store );
235249
fd_store_pool_t pool = fd_store_pool( store );
236250
fd_store_fec_t * fec0 = fd_store_fec0( store );
237251

238252
fd_store_fec_t * head = fd_store_root( store );
239253
fd_store_fec_t * tail = head;
254+
255+
# if FD_STORE_USE_HANDHOLDING
256+
if ( FD_UNLIKELY( !head ) ) { FD_LOG_WARNING(( "calling clear on an empty store" )); return store; }
257+
# endif
258+
240259
for( fd_store_map_iter_t iter = fd_store_map_iter_init( map, fec0 );
241260
!fd_store_map_iter_done( iter, map, fec0 );
242261
iter = fd_store_map_iter_next( iter, map, fec0 ) ) {
@@ -283,6 +302,8 @@ fd_store_verify( fd_store_t * store ) {
283302
return -1;
284303
}
285304
}
305+
fd_store_pool_t pool = fd_store_pool_const( store );
306+
if( FD_UNLIKELY( fd_store_pool_verify( &pool )==-1 ) ) return -1;
286307
return fd_store_map_verify( map, store->fec_max, fec0 );
287308
}
288309

@@ -296,7 +317,7 @@ print( fd_store_t const * store, fd_store_fec_t const * fec, int space, const ch
296317

297318
if( space > 0 ) printf( "\n" );
298319
for( int i = 0; i < space; i++ ) printf( " " );
299-
printf( "%s%s", prefix, FD_BASE58_ENC_32_ALLOCA( &fec->key ) );
320+
printf( "%s%s", prefix, FD_BASE58_ENC_32_ALLOCA( &fec->key.mr ) );
300321

301322
fd_store_fec_t const * curr = fd_store_pool_ele_const( &pool, fec->child );
302323
char new_prefix[1024]; /* FIXME size this correctly */

src/disco/store/fd_store.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
#define MAP_KEY_HASH(key,seed) ((ulong)key->mr.ul[0]%seed + (key)->part*seed)
9595
```
9696
where `key` is a key type that includes the merkle root (32 bytes)
97-
and the partition index (4 bytes) that is equivalent to the Shred
97+
and the partition index (8 bytes) that is equivalent to the Shred
9898
tile index doing the insertion. seed, on initialization, is the
9999
number of chains/buckets in the map_chain divided by the number of
100100
partitions. In effect, seed is the size of each partition. For
@@ -126,7 +126,7 @@
126126
hash chain within that slot (which modifies what the head of the
127127
chain points to as well as the now-previous head in the hash chain's
128128
`.next` field, but does not touch application data). With fencing
129-
enabled (FD_MAP_INSERT_FENCING), it is guaranteed the consumer either
129+
enabled (MAP_INSERT_FENCE), it is guaranteed the consumer either
130130
reads the head before or after the update. If it reads before, that
131131
is safe, it would just check the key (if no match, iterate down the
132132
chain etc.) If it reads after, it is also safe because the new
@@ -171,15 +171,15 @@
171171
#define FD_STORE_DATA_MAX (63985UL) /* TODO fixed-32 */
172172

173173
/* fd_store_fec describes a store element (FEC set). The pointer fields
174-
  implement a left-child, right-sibling n-ary tree. */
174+
implement a left-child, right-sibling n-ary tree. */
175175

176176
struct __attribute__((packed)) fd_store_key {
177177
fd_hash_t mr;
178178
ulong part; /* partition index of the inserter */
179179
};
180180
typedef struct fd_store_key fd_store_key_t;
181181

182-
struct __attribute__((aligned(128UL))) fd_store_fec {
182+
struct __attribute__((aligned(FD_STORE_ALIGN))) fd_store_fec {
183183

184184
/* Keys */
185185

@@ -233,7 +233,7 @@ FD_PROTOTYPES_BEGIN
233233

234234
/* fd_store_{align,footprint} return the required alignment and
235235
footprint of a memory region suitable for use as store with up to
236-
fec_max elements. */
236+
fec_max elements. fec_max is an integer power-of-two. */
237237

238238
FD_FN_CONST static inline ulong
239239
fd_store_align( void ) {
@@ -242,6 +242,7 @@ fd_store_align( void ) {
242242

243243
FD_FN_CONST static inline ulong
244244
fd_store_footprint( ulong fec_max ) {
245+
if( FD_UNLIKELY( !fd_ulong_is_pow2( fec_max ) ) ) return 0UL;
245246
return FD_LAYOUT_FINI(
246247
FD_LAYOUT_APPEND(
247248
FD_LAYOUT_APPEND(
@@ -257,7 +258,8 @@ fd_store_footprint( ulong fec_max ) {
257258

258259
/* fd_store_new formats an unused memory region for use as a store.
259260
mem is a non-NULL pointer to this region in the local address space
260-
with the required footprint and alignment. */
261+
with the required footprint and alignment. fec_max is an integer
262+
power-of-two. */
261263

262264
void *
263265
fd_store_new( void * shmem, ulong fec_max, ulong part_cnt );
@@ -286,7 +288,7 @@ fd_store_leave( fd_store_t const * store );
286288
caller. */
287289

288290
void *
289-
fd_store_delete( void * store );
291+
fd_store_delete( void * shstore );
290292

291293
/* Accessors */
292294

@@ -451,7 +453,9 @@ fd_store_publish( fd_store_t * store,
451453
fd_hash_t * merkle_root );
452454

453455
/* fd_store_clear clears the store. All elements are removed from the
454-
map and released back into the pool. Does not zero-out fields. */
456+
map and released back into the pool. Does not zero-out fields.
457+
458+
IMPORTANT SAFETY TIP! the store must be non-empty. */
455459

456460
fd_store_t *
457461
fd_store_clear( fd_store_t * store );

0 commit comments

Comments
 (0)