]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
Verify final loose_count in mdb_txn_commit()
authorHallvard Furuseth <hallvard@openldap.org>
Tue, 25 Jul 2017 19:27:36 +0000 (21:27 +0200)
committerHoward Chu <hyc@openldap.org>
Sat, 10 Oct 2020 11:57:36 +0000 (12:57 +0100)
Mismatch may indicate that pages leaked or got used twice
in the same snapshot.

libraries/liblmdb/mdb.c

index e2d3b5399824fe6673ba6c12f2839f9377b99874..3e0aa98340dd9e6d4c535d28dad5decf4a2698cb 100644 (file)
@@ -3544,7 +3544,7 @@ mdb_freelist_save(MDB_txn *txn)
         */
        MDB_cursor mc;
        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;
        pgno_t  freecnt = 0, *free_pgs, *mop;
        ssize_t head_room = 0, total_room = 0, mop_len, clean_limit;
@@ -3565,6 +3565,7 @@ mdb_freelist_save(MDB_txn *txn)
                MDB_page *mp = txn->mt_loose_pgs;
                if ((rc = mdb_midl_need(&txn->mt_free_pgs, txn->mt_loose_count)) != 0)
                        return rc;
+               lost_loose = txn->mt_loose_count;
                for (; mp; mp = NEXT_LOOSE_PAGE(mp))
                        mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno);
                txn->mt_loose_pgs = NULL;
@@ -3682,6 +3683,7 @@ mdb_freelist_save(MDB_txn *txn)
                /* Room for loose pages + temp IDL with same */
                if ((rc = mdb_midl_need(&env->me_pghead, 2*count+1)) != 0)
                        return rc;
+               lost_loose += count;
                mop = env->me_pghead;
                loose = mop + MDB_IDL_ALLOCLEN(mop) - count;
                for (count = 0; mp; mp = NEXT_LOOSE_PAGE(mp))
@@ -3721,6 +3723,11 @@ mdb_freelist_save(MDB_txn *txn)
                                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;
 }
 
@@ -4156,6 +4163,10 @@ mdb_txn_commit(MDB_txn *txn)
 
        if ((rc = mdb_page_flush(txn, 0)))
                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) &&
                (rc = mdb_env_sync0(env, 0, txn->mt_next_pgno)))
                goto fail;