For ITS#7789: Ensure mapsize >= pages in use.

Check new mapsizes against mm_last_pg.  Move
mdb_env_init_meta0() so it can set mm_last_pg earlier.
vl32b
Hallvard Furuseth 10 years ago committed by Hallvard Furuseth
parent c306423adf
commit 3e6ac6ef6b
  1. 35
      libraries/liblmdb/mdb.c

@ -3507,6 +3507,7 @@ mdb_env_read_header(MDB_env *env, MDB_meta *meta)
return 0; return 0;
} }
/** Fill in most of the zeroed #MDB_meta for an empty database environment */
static void ESECT static void ESECT
mdb_env_init_meta0(MDB_env *env, MDB_meta *meta) mdb_env_init_meta0(MDB_env *env, MDB_meta *meta)
{ {
@ -3523,7 +3524,7 @@ mdb_env_init_meta0(MDB_env *env, MDB_meta *meta)
/** Write the environment parameters of a freshly created DB environment. /** Write the environment parameters of a freshly created DB environment.
* @param[in] env the environment handle * @param[in] env the environment handle
* @param[out] meta address of where to store the meta information * @param[in] meta the #MDB_meta to write
* @return 0 on success, non-zero on failure. * @return 0 on success, non-zero on failure.
*/ */
static int ESECT static int ESECT
@ -3550,8 +3551,6 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
psize = env->me_psize; psize = env->me_psize;
mdb_env_init_meta0(env, meta);
p = calloc(2, psize); p = calloc(2, psize);
p->mp_pgno = 0; p->mp_pgno = 0;
p->mp_flags = P_META; p->mp_flags = P_META;
@ -3825,16 +3824,16 @@ mdb_env_set_mapsize(MDB_env *env, size_t size)
*/ */
if (env->me_map) { if (env->me_map) {
int rc; int rc;
MDB_meta *meta;
void *old; void *old;
if (env->me_txn) if (env->me_txn)
return EINVAL; return EINVAL;
meta = env->me_metas[mdb_env_pick_meta(env)];
if (!size) if (!size)
size = env->me_metas[mdb_env_pick_meta(env)]->mm_mapsize; size = meta->mm_mapsize;
else if (size < env->me_mapsize) { {
/* If the configured size is smaller, make sure it's /* Silently round up to minimum if the size is too small */
* still big enough. Silently round up to minimum if not. size_t minsize = (meta->mm_last_pg + 1) * env->me_psize;
*/
size_t minsize = (env->me_metas[mdb_env_pick_meta(env)]->mm_last_pg + 1) * env->me_psize;
if (size < minsize) if (size < minsize)
size = minsize; size = minsize;
} }
@ -3917,8 +3916,6 @@ mdb_env_open2(MDB_env *env)
env->me_pidquery = PROCESS_QUERY_INFORMATION; env->me_pidquery = PROCESS_QUERY_INFORMATION;
#endif /* _WIN32 */ #endif /* _WIN32 */
memset(&meta, 0, sizeof(meta));
if ((i = mdb_env_read_header(env, &meta)) != 0) { if ((i = mdb_env_read_header(env, &meta)) != 0) {
if (i != ENOENT) if (i != ENOENT)
return i; return i;
@ -3927,24 +3924,26 @@ mdb_env_open2(MDB_env *env)
env->me_psize = env->me_os_psize; env->me_psize = env->me_os_psize;
if (env->me_psize > MAX_PAGESIZE) if (env->me_psize > MAX_PAGESIZE)
env->me_psize = MAX_PAGESIZE; env->me_psize = MAX_PAGESIZE;
memset(&meta, 0, sizeof(meta));
mdb_env_init_meta0(env, &meta);
meta.mm_mapsize = DEFAULT_MAPSIZE;
} else { } else {
env->me_psize = meta.mm_psize; env->me_psize = meta.mm_psize;
} }
/* Was a mapsize configured? */ /* Was a mapsize configured? */
if (!env->me_mapsize) { if (!env->me_mapsize) {
/* If this is a new environment, take the default, env->me_mapsize = meta.mm_mapsize;
* else use the size recorded in the existing env. }
*/ {
env->me_mapsize = newenv ? DEFAULT_MAPSIZE : meta.mm_mapsize; /* Make sure mapsize >= committed data size. Even when using
} else if (env->me_mapsize < meta.mm_mapsize) { * mm_mapsize, which could be broken in old files (ITS#7789).
/* If the configured size is smaller, make sure it's
* still big enough. Silently round up to minimum if not.
*/ */
size_t minsize = (meta.mm_last_pg + 1) * meta.mm_psize; size_t minsize = (meta.mm_last_pg + 1) * meta.mm_psize;
if (env->me_mapsize < minsize) if (env->me_mapsize < minsize)
env->me_mapsize = minsize; env->me_mapsize = minsize;
} }
meta.mm_mapsize = env->me_mapsize;
rc = mdb_env_map(env, (flags & MDB_FIXEDMAP) ? meta.mm_address : NULL); rc = mdb_env_map(env, (flags & MDB_FIXEDMAP) ? meta.mm_address : NULL);
if (rc) if (rc)

Loading…
Cancel
Save