Skip to content

Commit 97f804d

Browse files
committed
gossmap: routine gossmap_disable_mmap() to force read() calls.
And use this if we spot corruption in gossipd. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 89125ea commit 97f804d

File tree

3 files changed

+40
-15
lines changed

3 files changed

+40
-15
lines changed

common/gossmap.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -784,12 +784,9 @@ static bool load_gossip_store(struct gossmap *map, bool must_be_clean)
784784
map->local_announces = NULL;
785785
map->local_updates = NULL;
786786

787-
/* gossipd uses pwritev(), which is not consistent with mmap on OpenBSD! */
788-
#ifndef __OpenBSD__
789787
/* If this fails, we fall back to read */
790788
map->mmap = mmap(NULL, map->map_size, PROT_READ, MAP_SHARED, map->fd, 0);
791789
if (map->mmap == MAP_FAILED)
792-
#endif /* __OpenBSD__ */
793790
map->mmap = NULL;
794791

795792
/* We only support major version 0 */
@@ -1224,12 +1221,12 @@ bool gossmap_refresh(struct gossmap *map)
12241221
if (map->mmap)
12251222
munmap(map->mmap, map->map_size);
12261223
map->map_size = len;
1227-
/* gossipd uses pwritev(), which is not consistent with mmap on OpenBSD! */
1228-
#ifndef __OpenBSD__
1229-
map->mmap = mmap(NULL, map->map_size, PROT_READ, MAP_SHARED, map->fd, 0);
1230-
if (map->mmap == MAP_FAILED)
1231-
#endif /* __OpenBSD__ */
1232-
map->mmap = NULL;
1224+
1225+
if (map->mmap) {
1226+
map->mmap = mmap(NULL, map->map_size, PROT_READ, MAP_SHARED, map->fd, 0);
1227+
if (map->mmap == MAP_FAILED)
1228+
map->mmap = NULL;
1229+
}
12331230

12341231
map_catchup(map, false, &changed);
12351232
return changed;
@@ -1862,6 +1859,18 @@ int gossmap_fd(const struct gossmap *map)
18621859
return map->fd;
18631860
}
18641861

1862+
bool gossmap_has_mmap(const struct gossmap *map)
1863+
{
1864+
return map->mmap != NULL;
1865+
}
1866+
1867+
void gossmap_disable_mmap(struct gossmap *map)
1868+
{
1869+
if (map->mmap)
1870+
munmap(map->mmap, map->map_size);
1871+
map->mmap = NULL;
1872+
}
1873+
18651874
const u8 *gossmap_fetch_tail(const tal_t *ctx, const struct gossmap *map)
18661875
{
18671876
size_t len;

common/gossmap.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ struct gossmap *gossmap_load_(const tal_t *ctx,
7070
...),
7171
void *cb_arg);
7272

73+
/* Disable mmap. Noop if already disabled. */
74+
void gossmap_disable_mmap(struct gossmap *map);
75+
bool gossmap_has_mmap(const struct gossmap *map);
76+
7377
/* Call this before using to ensure it's up-to-date. Returns true if something
7478
* was updated. Note: this can scramble node and chan indexes! */
7579
bool gossmap_refresh(struct gossmap *map);

gossipd/gossmap_manage.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,10 +1419,12 @@ struct gossmap *gossmap_manage_get_gossmap(struct gossmap_manage *gm)
14191419
written_len = gossip_store_len_written(gm->gs);
14201420

14211421
if (map_size != written_len) {
1422-
status_broken("gossmap size %"PRIu64" != written size %"PRIu64,
1423-
map_size, written_len);
1424-
/* Push harder! */
1425-
gossip_store_fsync(gm->gs);
1422+
status_broken("gossmap size %"PRIu64" != written size %"PRIu64
1423+
": %s mmap!",
1424+
map_size, written_len,
1425+
gossmap_has_mmap(gm->raw_gossmap)
1426+
? "disabling": "ALREADY DISABLED");
1427+
gossmap_disable_mmap(gm->raw_gossmap);
14261428
gossmap_refresh(gm->raw_gossmap);
14271429

14281430
/* Sanity check that we see everything we wrote. */
@@ -1443,12 +1445,22 @@ struct gossmap *gossmap_manage_get_gossmap(struct gossmap_manage *gm)
14431445
remainder_fd = fetch_tail_fd(tmpctx,
14441446
gossmap_fd(gm->raw_gossmap),
14451447
map_used, map_size);
1446-
status_failed(STATUS_FAIL_INTERNAL_ERROR,
1447-
"Gossmap failed to process entire gossip_store: "
1448+
status_broken("Gossmap failed to process entire gossip_store, %s mmap: "
14481449
"at %"PRIu64" of %"PRIu64" remaining_mmap=%s remaining_fd=%s",
1450+
gossmap_has_mmap(gm->raw_gossmap)
1451+
? "disabling": "ALREADY DISABLED",
14491452
map_used, map_size,
14501453
tal_hex(tmpctx, remainder_mmap),
14511454
tal_hex(tmpctx, remainder_fd));
1455+
gossmap_disable_mmap(gm->raw_gossmap);
1456+
gossmap_refresh(gm->raw_gossmap);
1457+
1458+
map_used = gossmap_lengths(gm->raw_gossmap, &map_size);
1459+
if (map_size != map_used) {
1460+
status_failed(STATUS_FAIL_INTERNAL_ERROR,
1461+
"Gossmap map_used %"PRIu64" of %"PRIu64" with %"PRIu64" written",
1462+
map_used, map_size, written_len);
1463+
}
14521464
}
14531465

14541466
return gm->raw_gossmap;

0 commit comments

Comments
 (0)