mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-03-07 14:18:15 +08:00
Fixes for loose pages
mdb_txn_commit(child): Give loose pages to parent. Use a pointer beyond the page header instead of mp_next, so we will not need to save/restore mp_pgno. This avoids a crash caused by references to mp_pgno.
This commit is contained in:
parent
b3e8c71dc7
commit
6ed295b256
@ -655,7 +655,7 @@ typedef struct MDB_page {
|
||||
#define mp_next mp_p.p_next
|
||||
union {
|
||||
pgno_t p_pgno; /**< page number */
|
||||
void * p_next; /**< for in-memory list of freed structs */
|
||||
struct MDB_page *p_next; /**< for in-memory list of freed pages */
|
||||
} mp_p;
|
||||
uint16_t mp_pad;
|
||||
/** @defgroup mdb_page Page Flags
|
||||
@ -731,7 +731,7 @@ typedef struct MDB_page {
|
||||
#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))
|
||||
#define NEXT_LOOSE_PAGE(p) (*(MDB_page **)((p) + 2))
|
||||
|
||||
/** Header for a single key/data pair within a page.
|
||||
* Used in pages of type #P_BRANCH and #P_LEAF without #P_LEAF2.
|
||||
@ -1601,6 +1601,8 @@ mdb_page_loose(MDB_cursor *mc, MDB_page *mp)
|
||||
}
|
||||
}
|
||||
if (loose) {
|
||||
DPRINTF(("loosen db %d page %"Z"u", DDBI(mc),
|
||||
mp->mp_pgno));
|
||||
NEXT_LOOSE_PAGE(mp) = mc->mc_txn->mt_loose_pgs;
|
||||
mc->mc_txn->mt_loose_pgs = mp;
|
||||
mp->mp_flags |= P_LOOSE;
|
||||
@ -1623,7 +1625,7 @@ mdb_page_loose(MDB_cursor *mc, MDB_page *mp)
|
||||
static int
|
||||
mdb_pages_xkeep(MDB_cursor *mc, unsigned pflags, int all)
|
||||
{
|
||||
enum { Mask = P_SUBP|P_DIRTY|P_KEEP };
|
||||
enum { Mask = P_SUBP|P_DIRTY|P_LOOSE|P_KEEP };
|
||||
MDB_txn *txn = mc->mc_txn;
|
||||
MDB_cursor *m3;
|
||||
MDB_xcursor *mx;
|
||||
@ -1661,12 +1663,6 @@ mdb_pages_xkeep(MDB_cursor *mc, unsigned pflags, int all)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Loose pages shouldn't be spilled */
|
||||
for (dp = txn->mt_loose_pgs; dp; dp = NEXT_LOOSE_PAGE(dp)) {
|
||||
if ((dp->mp_flags & Mask) == pflags)
|
||||
dp->mp_flags ^= P_KEEP;
|
||||
}
|
||||
|
||||
if (all) {
|
||||
/* Mark dirty root pages */
|
||||
for (i=0; i<txn->mt_numdbs; i++) {
|
||||
@ -1780,7 +1776,7 @@ mdb_page_spill(MDB_cursor *m0, MDB_val *key, MDB_val *data)
|
||||
for (i=dl[0].mid; i && need; i--) {
|
||||
MDB_ID pn = dl[i].mid << 1;
|
||||
dp = dl[i].mptr;
|
||||
if (dp->mp_flags & P_KEEP)
|
||||
if (dp->mp_flags & (P_LOOSE|P_KEEP))
|
||||
continue;
|
||||
/* Can't spill twice, make sure it's not already in a parent's
|
||||
* spill list.
|
||||
@ -1898,6 +1894,8 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
||||
if (num == 1 && txn->mt_loose_pgs) {
|
||||
np = txn->mt_loose_pgs;
|
||||
txn->mt_loose_pgs = NEXT_LOOSE_PAGE(np);
|
||||
DPRINTF(("db %d use loose page %"Z"u", DDBI(mc),
|
||||
np->mp_pgno));
|
||||
*mp = np;
|
||||
return MDB_SUCCESS;
|
||||
}
|
||||
@ -2951,8 +2949,8 @@ mdb_page_flush(MDB_txn *txn, int keep)
|
||||
while (++i <= pagecount) {
|
||||
dp = dl[i].mptr;
|
||||
/* Don't flush this page yet */
|
||||
if (dp->mp_flags & P_KEEP) {
|
||||
dp->mp_flags ^= P_KEEP;
|
||||
if (dp->mp_flags & (P_LOOSE|P_KEEP)) {
|
||||
dp->mp_flags &= ~P_KEEP;
|
||||
dl[++j] = dl[i];
|
||||
continue;
|
||||
}
|
||||
@ -2966,8 +2964,8 @@ mdb_page_flush(MDB_txn *txn, int keep)
|
||||
if (++i <= pagecount) {
|
||||
dp = dl[i].mptr;
|
||||
/* Don't flush this page yet */
|
||||
if (dp->mp_flags & P_KEEP) {
|
||||
dp->mp_flags ^= P_KEEP;
|
||||
if (dp->mp_flags & (P_LOOSE|P_KEEP)) {
|
||||
dp->mp_flags &= ~P_KEEP;
|
||||
dl[i].mid = 0;
|
||||
continue;
|
||||
}
|
||||
@ -3096,6 +3094,7 @@ mdb_txn_commit(MDB_txn *txn)
|
||||
|
||||
if (txn->mt_parent) {
|
||||
MDB_txn *parent = txn->mt_parent;
|
||||
MDB_page **lp;
|
||||
MDB_ID2L dst, src;
|
||||
MDB_IDL pspill;
|
||||
unsigned x, y, len, ps_len;
|
||||
@ -3193,6 +3192,11 @@ mdb_txn_commit(MDB_txn *txn)
|
||||
}
|
||||
}
|
||||
|
||||
/* Append our loose page list to parent's */
|
||||
for (lp = &parent->mt_loose_pgs; *lp; lp = &NEXT_LOOSE_PAGE(lp))
|
||||
;
|
||||
*lp = txn->mt_loose_pgs;
|
||||
|
||||
parent->mt_child = NULL;
|
||||
mdb_midl_free(((MDB_ntxn *)txn)->mnt_pgstate.mf_pghead);
|
||||
free(txn);
|
||||
|
Loading…
Reference in New Issue
Block a user