8
8
* Portions Copyright (c) 1994, Regents of the University of California
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.62 2008/09/30 14:15:58 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.63 2008/10/01 08:12:14 heikki Exp $
12
12
*
13
13
*
14
14
* NOTES:
@@ -123,6 +123,8 @@ static int fsm_set_and_search(Relation rel, FSMAddress addr, uint16 slot,
123
123
static BlockNumber fsm_search (Relation rel , uint8 min_cat );
124
124
static uint8 fsm_vacuum_page (Relation rel , FSMAddress addr , bool * eof );
125
125
126
+ static void fsm_redo_truncate (xl_fsm_truncate * xlrec );
127
+
126
128
127
129
/******** Public API ********/
128
130
@@ -281,7 +283,7 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
281
283
* record, but that's not enough to zero out the last remaining FSM page.
282
284
* (if we didn't need to zero out anything above, we can skip this)
283
285
*/
284
- if (!rel -> rd_istemp && ! InRecovery && first_removed_slot != 0 )
286
+ if (!rel -> rd_istemp && first_removed_slot != 0 )
285
287
{
286
288
xl_fsm_truncate xlrec ;
287
289
XLogRecData rdata ;
@@ -310,8 +312,8 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
310
312
* Need to invalidate the relcache entry, because rd_fsm_nblocks_cache
311
313
* seen by other backends is no longer valid.
312
314
*/
313
- if (! InRecovery )
314
- CacheInvalidateRelcache ( rel );
315
+ CacheInvalidateRelcache ( rel );
316
+
315
317
rel -> rd_fsm_nblocks_cache = new_nfsmblocks ;
316
318
}
317
319
@@ -762,6 +764,43 @@ fsm_vacuum_page(Relation rel, FSMAddress addr, bool *eof_p)
762
764
763
765
/****** WAL-logging ******/
764
766
767
+ static void
768
+ fsm_redo_truncate (xl_fsm_truncate * xlrec )
769
+ {
770
+ FSMAddress first_removed_address ;
771
+ uint16 first_removed_slot ;
772
+ BlockNumber fsmblk ;
773
+ Buffer buf ;
774
+
775
+ /* Get the location in the FSM of the first removed heap block */
776
+ first_removed_address = fsm_get_location (xlrec -> nheapblocks ,
777
+ & first_removed_slot );
778
+ fsmblk = fsm_logical_to_physical (first_removed_address );
779
+
780
+ /*
781
+ * Zero out the tail of the last remaining FSM page. We rely on the
782
+ * replay of the smgr truncation record to remove completely unused
783
+ * pages.
784
+ */
785
+ buf = XLogReadBufferWithFork (xlrec -> node , FSM_FORKNUM , fsmblk , false);
786
+ if (BufferIsValid (buf ))
787
+ {
788
+ fsm_truncate_avail (BufferGetPage (buf ), first_removed_slot );
789
+ MarkBufferDirty (buf );
790
+ UnlockReleaseBuffer (buf );
791
+ }
792
+ else
793
+ {
794
+ /*
795
+ * The page doesn't exist. Because FSM extensions are not WAL-logged,
796
+ * it's normal to have a truncation record for a page that doesn't
797
+ * exist. Tell xlogutils.c not to PANIC at the end of recovery
798
+ * because of the missing page
799
+ */
800
+ XLogTruncateRelation (xlrec -> node , FSM_FORKNUM , fsmblk );
801
+ }
802
+ }
803
+
765
804
void
766
805
fsm_redo (XLogRecPtr lsn , XLogRecord * record )
767
806
{
@@ -770,15 +809,7 @@ fsm_redo(XLogRecPtr lsn, XLogRecord *record)
770
809
switch (info )
771
810
{
772
811
case XLOG_FSM_TRUNCATE :
773
- {
774
- xl_fsm_truncate * xlrec ;
775
- Relation rel ;
776
-
777
- xlrec = (xl_fsm_truncate * ) XLogRecGetData (record );
778
- rel = CreateFakeRelcacheEntry (xlrec -> node );
779
- FreeSpaceMapTruncateRel (rel , xlrec -> nheapblocks );
780
- FreeFakeRelcacheEntry (rel );
781
- }
812
+ fsm_redo_truncate ((xl_fsm_truncate * ) XLogRecGetData (record ));
782
813
break ;
783
814
default :
784
815
elog (PANIC , "fsm_redo: unknown op code %u" , info );
0 commit comments