Commit 0e17ba43 authored by Hallvard Furuseth's avatar Hallvard Furuseth Committed by Howard Chu
Browse files

Verify final loose_count in mdb_txn_commit()

Mismatch may indicate that pages leaked or got used twice
in the same snapshot.
parent 4b7e4303
...@@ -3544,7 +3544,7 @@ mdb_freelist_save(MDB_txn *txn) ...@@ -3544,7 +3544,7 @@ mdb_freelist_save(MDB_txn *txn)
*/ */
MDB_cursor mc; MDB_cursor mc;
MDB_env *env = txn->mt_env; MDB_env *env = txn->mt_env;
int rc, maxfree_1pg = env->me_maxfree_1pg, more = 1; int rc, maxfree_1pg = env->me_maxfree_1pg, more = 1, lost_loose = 0;
txnid_t pglast = 0, head_id = 0; txnid_t pglast = 0, head_id = 0;
pgno_t freecnt = 0, *free_pgs, *mop; pgno_t freecnt = 0, *free_pgs, *mop;
ssize_t head_room = 0, total_room = 0, mop_len, clean_limit; ssize_t head_room = 0, total_room = 0, mop_len, clean_limit;
...@@ -3565,6 +3565,7 @@ mdb_freelist_save(MDB_txn *txn) ...@@ -3565,6 +3565,7 @@ mdb_freelist_save(MDB_txn *txn)
MDB_page *mp = txn->mt_loose_pgs; MDB_page *mp = txn->mt_loose_pgs;
if ((rc = mdb_midl_need(&txn->mt_free_pgs, txn->mt_loose_count)) != 0) if ((rc = mdb_midl_need(&txn->mt_free_pgs, txn->mt_loose_count)) != 0)
return rc; return rc;
lost_loose = txn->mt_loose_count;
for (; mp; mp = NEXT_LOOSE_PAGE(mp)) for (; mp; mp = NEXT_LOOSE_PAGE(mp))
mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno); mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno);
txn->mt_loose_pgs = NULL; txn->mt_loose_pgs = NULL;
...@@ -3682,6 +3683,7 @@ mdb_freelist_save(MDB_txn *txn) ...@@ -3682,6 +3683,7 @@ mdb_freelist_save(MDB_txn *txn)
/* Room for loose pages + temp IDL with same */ /* Room for loose pages + temp IDL with same */
if ((rc = mdb_midl_need(&env->me_pghead, 2*count+1)) != 0) if ((rc = mdb_midl_need(&env->me_pghead, 2*count+1)) != 0)
return rc; return rc;
lost_loose += count;
mop = env->me_pghead; mop = env->me_pghead;
loose = mop + MDB_IDL_ALLOCLEN(mop) - count; loose = mop + MDB_IDL_ALLOCLEN(mop) - count;
for (count = 0; mp; mp = NEXT_LOOSE_PAGE(mp)) for (count = 0; mp; mp = NEXT_LOOSE_PAGE(mp))
...@@ -3721,6 +3723,11 @@ mdb_freelist_save(MDB_txn *txn) ...@@ -3721,6 +3723,11 @@ mdb_freelist_save(MDB_txn *txn)
break; break;
} }
} }
/* Restore this so we can check vs. dirty_list after mdb_page_flush() */
if (! (txn->mt_flags & MDB_TXN_WRITEMAP))
txn->mt_loose_count += lost_loose;
return rc; return rc;
} }
...@@ -4156,6 +4163,10 @@ mdb_txn_commit(MDB_txn *txn) ...@@ -4156,6 +4163,10 @@ mdb_txn_commit(MDB_txn *txn)
if ((rc = mdb_page_flush(txn, 0))) if ((rc = mdb_page_flush(txn, 0)))
goto fail; goto fail;
if ((unsigned)txn->mt_loose_count != txn->mt_u.dirty_list[0].mid) {
rc = MDB_PROBLEM; /* mt_loose_pgs does not match dirty_list */
goto fail;
}
if (!F_ISSET(txn->mt_flags, MDB_TXN_NOSYNC) && if (!F_ISSET(txn->mt_flags, MDB_TXN_NOSYNC) &&
(rc = mdb_env_sync0(env, 0, txn->mt_next_pgno))) (rc = mdb_env_sync0(env, 0, txn->mt_next_pgno)))
goto fail; goto fail;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment