Commit c99525f4 authored by Hallvard Furuseth's avatar Hallvard Furuseth
Browse files

ITS#7377 Invalidate txn on page-allocation errors

This should likely be reverted when all callers handle these errors.
parent 123b6e3c
......@@ -1405,6 +1405,8 @@ mdb_page_malloc(MDB_txn *txn, unsigned num)
memset((char *)ret + off, 0, psize);
ret->mp_pad = 0;
}
} else {
txn->mt_flags |= MDB_TXN_ERROR;
}
return ret;
}
......@@ -1725,8 +1727,10 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
*mp = NULL;
/* If our dirty list is already full, we can't do anything */
if (txn->mt_dirty_room == 0)
return MDB_TXN_FULL;
if (txn->mt_dirty_room == 0) {
rc = MDB_TXN_FULL;
goto fail;
}
for (op = MDB_FIRST;; op = MDB_NEXT) {
MDB_val key, data;
......@@ -1771,7 +1775,7 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
if (rc) {
if (rc == MDB_NOTFOUND)
break;
return rc;
goto fail;
}
last = *(txnid_t*)key.mv_data;
if (oldest <= last)
......@@ -1784,11 +1788,13 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
idl = (MDB_ID *) data.mv_data;
i = idl[0];
if (!mop) {
if (!(env->me_pghead = mop = mdb_midl_alloc(i)))
return ENOMEM;
if (!(env->me_pghead = mop = mdb_midl_alloc(i))) {
rc = ENOMEM;
goto fail;
}
} else {
if ((rc = mdb_midl_need(&env->me_pghead, i)) != 0)
return rc;
goto fail;
mop = env->me_pghead;
}
env->me_pglast = last;
......@@ -1817,15 +1823,18 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
pgno = txn->mt_next_pgno;
if (pgno + num >= env->me_maxpg) {
DPUTS("DB size maxed out");
return MDB_MAP_FULL;
rc = MDB_MAP_FULL;
goto fail;
}
search_done:
if (env->me_flags & MDB_WRITEMAP) {
np = (MDB_page *)(env->me_map + env->me_psize * pgno);
} else {
if (!(np = mdb_page_malloc(txn, num)))
return ENOMEM;
if (!(np = mdb_page_malloc(txn, num))) {
rc = ENOMEM;
goto fail;
}
}
if (i) {
mop[0] = mop_len -= num;
......@@ -1840,6 +1849,10 @@ search_done:
*mp = np;
return MDB_SUCCESS;
fail:
txn->mt_flags |= MDB_TXN_ERROR;
return rc;
}
/** Copy the used portions of a non-overflow page.
......@@ -1946,13 +1959,13 @@ mdb_page_touch(MDB_cursor *mc)
np = NULL;
rc = mdb_page_unspill(txn, mp, &np);
if (rc)
return rc;
goto fail;
if (np)
goto done;
}
if ((rc = mdb_midl_need(&txn->mt_free_pgs, 1)) ||
(rc = mdb_page_alloc(mc, 1, &np)))
return rc;
goto fail;
pgno = np->mp_pgno;
DPRINTF(("touched db %d page %"Z"u -> %"Z"u", DDBI(mc),
mp->mp_pgno, pgno));
......@@ -1977,6 +1990,7 @@ mdb_page_touch(MDB_cursor *mc)
if (x <= dl[0].mid && dl[x].mid == pgno) {
if (mp != dl[x].mptr) { /* bad cursor? */
mc->mc_flags &= ~(C_INITIALIZED|C_EOF);
txn->mt_flags |= MDB_TXN_ERROR;
return MDB_CORRUPTED;
}
return 0;
......@@ -2025,6 +2039,10 @@ done:
}
}
return 0;
fail:
txn->mt_flags |= MDB_TXN_ERROR;
return rc;
}
int
......
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