ITS#7230 check and strip 0 length IDLs from freelist
authorHoward Chu <hyc@openldap.org>
Mon, 9 Apr 2012 11:44:08 +0000 (04:44 -0700)
committerHoward Chu <hyc@openldap.org>
Mon, 9 Apr 2012 11:44:08 +0000 (04:44 -0700)
libraries/libmdb/mdb.c

index e70e46d..954690e 100644 (file)
@@ -1224,7 +1224,9 @@ mdb_page_alloc(MDB_cursor *mc, int num)
                                last = *kptr;
                        } else {
                                MDB_val key;
-                               int rc, exact = 0;
+                               int rc, exact;
+again:
+                               exact = 0;
                                last = txn->mt_env->me_pglast + 1;
                                leaf = NULL;
                                key.mv_data = &last;
@@ -1254,13 +1256,17 @@ mdb_page_alloc(MDB_cursor *mc, int num)
                                if (!txn->mt_env->me_pgfirst) {
                                        mdb_node_read(txn, leaf, &data);
                                }
+                               txn->mt_env->me_pglast = last;
+                               if (!txn->mt_env->me_pgfirst)
+                                       txn->mt_env->me_pgfirst = last;
                                idl = (ID *) data.mv_data;
+                               /* We might have a zero-length IDL due to freelist growth
+                                * during a prior commit
+                                */
+                               if (!idl[0]) goto again;
                                mop = malloc(sizeof(MDB_oldpages) + MDB_IDL_SIZEOF(idl) - sizeof(pgno_t));
                                mop->mo_next = txn->mt_env->me_pghead;
                                mop->mo_txnid = last;
-                               txn->mt_env->me_pglast = last;
-                               if (!txn->mt_env->me_pgfirst)
-                                       txn->mt_env->me_pgfirst = last;
                                txn->mt_env->me_pghead = mop;
                                memcpy(mop->mo_pages, idl, MDB_IDL_SIZEOF(idl));