From: Robert Haas Date: Wed, 19 Feb 2014 22:54:35 +0000 (-0500) Subject: More hacking. X-Git-Url: http://git.postgresql.org/gitweb/static/developers.postgresql.org?a=commitdiff_plain;h=7364518dcba965fe32eb032ffa305e2dc7f9b287;p=users%2Frhaas%2Fpostgres.git More hacking. --- diff --git a/src/backend/utils/mmgr/freepage.c b/src/backend/utils/mmgr/freepage.c index cb6c8690f5..2e4dda83fc 100644 --- a/src/backend/utils/mmgr/freepage.c +++ b/src/backend/utils/mmgr/freepage.c @@ -90,6 +90,8 @@ static bool FreePageManagerGetInternal(FreePageManager *fpm, Size npages, static void FreePageBtreeRecycle(FreePageManager *fpm, Size pageno); static void FreePageBtreeRemove(FreePageManager *fpm, FreePageBtree *btp, Size index); +static void FreePagePushSpanLeader(FreePageManager *fpm, Size first_page, + Size npages); static bool FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages, bool soft); static void FreePageBtreeRemove(FreePageManager *fpm, FreePageBtree *btp, @@ -365,14 +367,35 @@ FreePageManagerGetInternal(FreePageManager *fpm, Size npages, Size *first_page) if (next != NULL) relptr_copy(next->prev, victim->prev); - /* Remove span from btree. */ + /* + * If the span we found is exactly the right size, remove it from the + * btree completely. Otherwise, adjust the btree entry to reflect the + * still-unallocated portion of the span, and put that portion on the + * appropriate free list. + */ FreePageBtreeSearch(fpm, victim_page, &result); Assert(result.page_exact != NULL); - FreePageBtreeRemove(fpm, result.page_exact, result.index_exact); - - /* XXX. But the span we found might have been oversized ... we - * need to put the rest back! */ + if (victim->npages == npages) + FreePageBtreeRemove(fpm, result.page_exact, result.index_exact); + else + { + FreePageBtreeLeafKey *key; + + /* Adjust btree to reflect remaining pages. */ + Assert(victim->npages > npages); + key = &result.page_exact->u.leaf_key[result.index_exact]; + Assert(key->npages == victim->npages); + key->first_page += npages; + key->npages -= npages; + if (result.index_exact == 0) + FreePageBtreeAdjustAncestorKeys(fpm, result.page_exact); + + /* Put the unallocated pages back on the appropriate free list. */ + FreePagePushSpanLeader(fpm, victim_page + npages, + victim->npages - npages); + } + /* Return results to caller. */ *first_page = fpm_pointer_to_page(base, victim); return true; }