src/backend/storage/freespace/freespace.c
BlockNumber
FreeSpaceMapPrepareTruncateRel(Relation rel, BlockNumber nblocks)
{
	BlockNumber new_nfsmblocks;
	FSMAddress	first_removed_address;
	uint16		first_removed_slot;
	Buffer		buf;

	/*
	 * If no FSM has been created yet for this relation, there's nothing to
	 * truncate.
	 */
	if (!smgrexists(RelationGetSmgr(rel), FSM_FORKNUM))
		return InvalidBlockNumber;

	/* Get the location in the FSM of the first removed heap block */
	first_removed_address = fsm_get_location(nblocks, &first_removed_slot);

	/*
	 * Zero out the tail of the last remaining FSM page. If the slot
	 * representing the first removed heap block is at a page boundary, as the
	 * first slot on the FSM page that first_removed_address points to, we can
	 * just truncate that page altogether.
	 */
	if (first_removed_slot > 0)
	{
		buf = fsm_readbuf(rel, first_removed_address, false);
		if (!BufferIsValid(buf))
			return InvalidBlockNumber;	/* nothing to do; the FSM was already
										 * smaller */
		LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);

		/* NO EREPORT(ERROR) from here till changes are logged */
		START_CRIT_SECTION();

		fsm_truncate_avail(BufferGetPage(buf), first_removed_slot);

		/*
		 * Truncation of a relation is WAL-logged at a higher-level, and we
		 * will be called at WAL replay. But if checksums are enabled, we need
		 * to still write a WAL record to protect against a torn page, if the
		 * page is flushed to disk before the truncation WAL record. We cannot
		 * use MarkBufferDirtyHint here, because that will not dirty the page
		 * during recovery.
		 */
		MarkBufferDirty(buf);
		if (!InRecovery && RelationNeedsWAL(rel) && XLogHintBitIsNeeded())
			log_newpage_buffer(buf, false);

		END_CRIT_SECTION();

		UnlockReleaseBuffer(buf);

		new_nfsmblocks = fsm_logical_to_physical(first_removed_address) + 1;
	}
	else
	{
		new_nfsmblocks = fsm_logical_to_physical(first_removed_address);
		if (smgrnblocks(RelationGetSmgr(rel), FSM_FORKNUM) <= new_nfsmblocks)
			return InvalidBlockNumber;	/* nothing to do; the FSM was already
										 * smaller */
	}

	return new_nfsmblocks;
}
/*
 * FreeSpaceMapPrepareTruncateRel - prepare for truncation of a relation.
 *
 * nblocks is the new size of the heap.
 *
 * Return the number of blocks of new FSM.
 * If it's InvalidBlockNumber, there is nothing to truncate;
 * otherwise the caller is responsible for calling smgrtruncate()
 * to truncate the FSM pages, and FreeSpaceMapVacuumRange()
 * to update upper-level pages in the FSM.
 */
prepare for truncation of a relation.
nblocks is the new size of the heap.

Return the number of blocks of new FSM.
If it's InvalidBlockNumber, there is nothing to truncate;
otherwise the caller is responsible for calling smgrtruncate()
to truncate the FSM pages, and FreeSpaceMapVacuumRange()
to update upper-level pages in the FSM.
prepare for truncation of a relation . nblocks is the new size of the heap . Return the number of blocks of new FSM . If it ' s InvalidBlockNumber there is nothing to truncate ; otherwise the caller is responsible for calling smgrtruncate () to truncate the FSM pages and FreeSpaceMapVacuumRange () to update upper - level pages in the FSM .
BlockNumber
FreeSpaceMapPrepareTruncateRel(Relation rel, BlockNumber nblocks)
{
	BlockNumber new_nfsmblocks;
	FSMAddress	first_removed_address;
	uint16		first_removed_slot;
	Buffer		buf;
	if (!smgrexists(RelationGetSmgr(rel), FSM_FORKNUM))
		return InvalidBlockNumber;
	first_removed_address = fsm_get_location(nblocks, &first_removed_slot);
	if (first_removed_slot > 0)
	{
		buf = fsm_readbuf(rel, first_removed_address, false);
		if (!BufferIsValid(buf))
			return InvalidBlockNumber;	
		LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
		START_CRIT_SECTION();
		fsm_truncate_avail(BufferGetPage(buf), first_removed_slot);
		MarkBufferDirty(buf);
		if (!InRecovery && RelationNeedsWAL(rel) && XLogHintBitIsNeeded())
			log_newpage_buffer(buf, false);
		END_CRIT_SECTION();
		UnlockReleaseBuffer(buf);
		new_nfsmblocks = fsm_logical_to_physical(first_removed_address) + 1;
	}
	else
	{
		new_nfsmblocks = fsm_logical_to_physical(first_removed_address);
		if (smgrnblocks(RelationGetSmgr(rel), FSM_FORKNUM) <= new_nfsmblocks)
			return InvalidBlockNumber;	
	}
	return new_nfsmblocks;
}
BlockNumber FreeSpaceMapPrepareTruncateRel ( Relation rel , BlockNumber nblocks ) { BlockNumber new_nfsmblocks ; FSMAddress first_removed_address ; uint16 first_removed_slot ; Buffer buf ; if ( ! smgrexists ( RelationGetSmgr ( rel ) , FSM_FORKNUM ) ) return InvalidBlockNumber ; first_removed_address = fsm_get_location ( nblocks , & first_removed_slot ) ; if ( first_removed_slot > 0 ) { buf = fsm_readbuf ( rel , first_removed_address , false ) ; if ( ! BufferIsValid ( buf ) ) return InvalidBlockNumber ; LockBuffer ( buf , BUFFER_LOCK_EXCLUSIVE ) ; START_CRIT_SECTION ( ) ; fsm_truncate_avail ( BufferGetPage ( buf ) , first_removed_slot ) ; MarkBufferDirty ( buf ) ; if ( ! InRecovery && RelationNeedsWAL ( rel ) && XLogHintBitIsNeeded ( ) ) log_newpage_buffer ( buf , false ) ; END_CRIT_SECTION ( ) ; UnlockReleaseBuffer ( buf ) ; new_nfsmblocks = fsm_logical_to_physical ( first_removed_address ) + 1 ; } else { new_nfsmblocks = fsm_logical_to_physical ( first_removed_address ) ; if ( smgrnblocks ( RelationGetSmgr ( rel ) , FSM_FORKNUM ) <= new_nfsmblocks ) return InvalidBlockNumber ; } return new_nfsmblocks ; }
FreeSpaceMapPrepareTruncateRel - prepare for truncation of a relation.
FreeSpaceMapPrepareTruncateRel - prepare for truncation of a relation .
/*
	 * If no FSM has been created yet for this relation, there's nothing to
	 * truncate.
	 */ /* Get the location in the FSM of the first removed heap block */ /*
	 * Zero out the tail of the last remaining FSM page. If the slot
	 * representing the first removed heap block is at a page boundary, as the
	 * first slot on the FSM page that first_removed_address points to, we can
	 * just truncate that page altogether.
	 */ /* nothing to do; the FSM was already
										 * smaller */ /* NO EREPORT(ERROR) from here till changes are logged */ /*
		 * Truncation of a relation is WAL-logged at a higher-level, and we
		 * will be called at WAL replay. But if checksums are enabled, we need
		 * to still write a WAL record to protect against a torn page, if the
		 * page is flushed to disk before the truncation WAL record. We cannot
		 * use MarkBufferDirtyHint here, because that will not dirty the page
		 * during recovery.
		 */ /* nothing to do; the FSM was already
										 * smaller */