Clear the local map when not used.

After commit b0eaa4c51b, we use a local map of pages to find the required
space for small relations.  We do clear this map when we have found a block
with enough free space, when we extend the relation, or on transaction
abort so that it can be used next time.  However, we miss to clear it when
we didn't find any pages to try from the map which leads to an assertion
failure when we later tried to use it after relation extension.

In the passing, I have improved some comments in this area.

Reported-by: Tom Lane based on buildfarm results
Author: Amit Kapila
Reviewed-by: John Naylor
Tested-by: Kuntal Ghosh
Discussion: https://postgr.es/m/32368.1551114120@sss.pgh.pa.us
This commit is contained in:
Amit Kapila 2019-03-01 07:38:47 +05:30
parent 0f3cdf873e
commit 9c32e4c350
2 changed files with 19 additions and 5 deletions

View File

@ -675,10 +675,7 @@ loop:
*/
RelationSetTargetBlock(relation, BufferGetBlockNumber(buffer));
/*
* In case we used an in-memory map of available blocks, reset it for next
* use.
*/
/* This should already be cleared by now, but make sure it is. */
FSMClearLocalMap();
return buffer;

View File

@ -97,7 +97,16 @@ typedef struct
/* Address of the root page. */
static const FSMAddress FSM_ROOT_ADDRESS = {FSM_ROOT_LEVEL, 0};
/* Local map of block numbers for small heaps with no FSM. */
/*
* For small relations, we don't create FSM to save space, instead we use
* local in-memory map of pages to try. To locate free space, we simply try
* pages directly without knowing ahead of time how much free space they have.
*
* Note that this map is used to the find the block with required free space
* for any given relation. We clear this map when we have found a block with
* enough free space, when we extend the relation, or on transaction abort.
* See src/backend/storage/freespace/README for further details.
*/
typedef struct
{
BlockNumber nblocks;
@ -1175,5 +1184,13 @@ fsm_local_search(void)
return target_block;
} while (target_block > 0);
/*
* If we didn't find any available block to try in the local map, then
* clear it. This prevents us from using the map again without setting it
* first, which would otherwise lead to the same conclusion again and
* again.
*/
FSMClearLocalMap();
return InvalidBlockNumber;
}