From 91d8ad1d3c3364a667ed91cb8551327ea14ea8e0 Mon Sep 17 00:00:00 2001 From: Hallvard Furuseth Date: Sat, 28 Jun 2014 13:38:03 +0200 Subject: [PATCH] Fix mdb_page_loose() vs. mdb_page_flush(). Do not overwrite loose pages' mp_pgno with mp_next. mdb_page_flush() will use mp_pgno to rebuild dirty_list. --- libraries/liblmdb/mdb.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index c21f556..c5311fa 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -701,6 +701,9 @@ typedef struct MDB_page { /** The number of overflow pages needed to store the given size. */ #define OVPAGES(size, psize) ((PAGEHDRSZ-1 + (size)) / (psize) + 1) + /** Link in #MDB_txn.%mt_loose_pages list */ +#define NEXT_LOOSE_PAGE(p) (*(MDB_page **)METADATA(p)) + /** Header for a single key/data pair within a page. * Used in pages of type #P_BRANCH and #P_LEAF without #P_LEAF2. * We guarantee 2-byte alignment for 'MDB_node's. @@ -900,7 +903,7 @@ struct MDB_txn { */ MDB_IDL mt_free_pgs; /** The list of loose pages that became unused and may be reused - * in this transaction. + * in this transaction, linked through #NEXT_LOOSE_PAGE(page). */ MDB_page *mt_loose_pgs; /** The sorted list of dirty pages we temporarily wrote to disk @@ -1569,9 +1572,7 @@ mdb_page_loose(MDB_cursor *mc, MDB_page *mp) } } if (loose) { - pgno_t *pp = (pgno_t *)mp->mp_ptrs; - *pp = pgno; - mp->mp_next = mc->mc_txn->mt_loose_pgs; + NEXT_LOOSE_PAGE(mp) = mc->mc_txn->mt_loose_pgs; mc->mc_txn->mt_loose_pgs = mp; mp->mp_flags |= P_LOOSE; } else { @@ -1632,7 +1633,7 @@ mdb_pages_xkeep(MDB_cursor *mc, unsigned pflags, int all) } /* Loose pages shouldn't be spilled */ - for (dp = txn->mt_loose_pgs; dp; dp=dp->mp_next) { + for (dp = txn->mt_loose_pgs; dp; dp = NEXT_LOOSE_PAGE(dp)) { if ((dp->mp_flags & Mask) == pflags) dp->mp_flags ^= P_KEEP; } @@ -1866,11 +1867,8 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp) /* If there are any loose pages, just use them */ if (num == 1 && txn->mt_loose_pgs) { - pgno_t *pp; np = txn->mt_loose_pgs; - txn->mt_loose_pgs = np->mp_next; - pp = (pgno_t *)np->mp_ptrs; - np->mp_pgno = *pp; + txn->mt_loose_pgs = NEXT_LOOSE_PAGE(np); *mp = np; return MDB_SUCCESS; } @@ -2741,28 +2739,22 @@ mdb_freelist_save(MDB_txn *txn) */ if (txn->mt_loose_pgs) { MDB_page *mp = txn->mt_loose_pgs; - pgno_t *pp; /* Just return them to freeDB */ if (env->me_pghead) { int i, j; mop = env->me_pghead; - while(mp) { - pgno_t pg; - pp = (pgno_t *)mp->mp_ptrs; - pg = *pp; + for (; mp; mp = NEXT_LOOSE_PAGE(mp)) { + pgno_t pg = mp->mp_pgno; j = mop[0] + 1; for (i = mop[0]; i && mop[i] < pg; i--) mop[j--] = mop[i]; mop[j] = pg; mop[0] += 1; - mp = mp->mp_next; } } else { /* Oh well, they were wasted. Put on freelist */ - while(mp) { - pp = (pgno_t *)mp->mp_ptrs; - mdb_midl_append(&txn->mt_free_pgs, *pp); - mp = mp->mp_next; + for (; mp; mp = NEXT_LOOSE_PAGE(mp)) { + mdb_midl_append(&txn->mt_free_pgs, mp->mp_pgno); } } txn->mt_loose_pgs = NULL;