[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
(ITS#7688) MDB_WRITEMAP + non-writemap process broken
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).