Full_Name: Hallvard B Furuseth Version: LMDB_0.9.8 OS: Linux x86_64 URL: Submission from: (NULL) (129.240.203.186) Submitted by: hallvard
mdb_env_open(,,MDB_WRITEMAP,) does not grow the data file to the mapsize if another process has it open without MDB_WRITEMAP. The new MDB_env gets Bus Error in mdb_page_alloc() if it tries to grow mt_next_pgno.
Broken by 2e7130cab0129e3b72a25d39c5d4e5a5c55cb353 "Allow mdb_env_set_mapsize() on an open environment". It made ftruncate() conditional on 'newsize'. To avoid mapsize wars between environments? Could do:
if (flags & MDB_WRITEMAP) { prot |= PROT_WRITE; if (!newsize) { off_t pos = lseek(env->me_fd, 0, SEEK_END); if (pos == (off_t)-1) return ErrCode(); if ((size_t)pos < env->me_mapsize) newsize = 1; } if (newsize && ftruncate(env->me_fd, env->me_mapsize) < 0) return ErrCode(); }
But that still has a race between processes mapping the environment at the same time, one process could shrink the map just after another grew it. And I'm unsure how env->me_mapsize would end up in this case.
Another way: Move ftruncate() to mdb_page_alloc(), which has no race. Grow to <new mt_next_pgno + 25%>. To avoid seeks, maintain me_txns->mti_next_pgno in mdb_page_alloc{MDB_WRITEMAP} and txn_reset(writer).