2121#include "storage/bufmgr.h"
2222#include "storage/proc.h"
2323#include "storage/procarray.h"
24- #include "storage/read_stream.h"
2524#include "storage/smgr.h"
2625#include "utils/rel.h"
2726#include "utils/snapmgr.h"
@@ -42,17 +41,6 @@ typedef struct corrupt_items
4241ItemPointer tids ;
4342}corrupt_items ;
4443
45- /* for collect_corrupt_items_read_stream_next_block */
46- struct collect_corrupt_items_read_stream_private
47- {
48- bool all_frozen ;
49- bool all_visible ;
50- BlockNumber current_blocknum ;
51- BlockNumber last_exclusive ;
52- Relation rel ;
53- Buffer vmbuffer ;
54- };
55-
5644PG_FUNCTION_INFO_V1 (pg_visibility_map );
5745PG_FUNCTION_INFO_V1 (pg_visibility_map_rel );
5846PG_FUNCTION_INFO_V1 (pg_visibility );
@@ -490,8 +478,6 @@ collect_visibility_data(Oid relid, bool include_pd)
490478BlockNumber blkno ;
491479Buffer vmbuffer = InvalidBuffer ;
492480BufferAccessStrategy bstrategy = GetAccessStrategy (BAS_BULKREAD );
493- BlockRangeReadStreamPrivate p ;
494- ReadStream * stream = NULL ;
495481
496482rel = relation_open (relid ,AccessShareLock );
497483
@@ -503,20 +489,6 @@ collect_visibility_data(Oid relid, bool include_pd)
503489info -> next = 0 ;
504490info -> count = nblocks ;
505491
506- /* Create a stream if reading main fork. */
507- if (include_pd )
508- {
509- p .current_blocknum = 0 ;
510- p .last_exclusive = nblocks ;
511- stream = read_stream_begin_relation (READ_STREAM_FULL ,
512- bstrategy ,
513- rel ,
514- MAIN_FORKNUM ,
515- block_range_read_stream_cb ,
516- & p ,
517- 0 );
518- }
519-
520492for (blkno = 0 ;blkno < nblocks ;++ blkno )
521493{
522494int32 mapbits ;
@@ -541,7 +513,8 @@ collect_visibility_data(Oid relid, bool include_pd)
541513Buffer buffer ;
542514Page page ;
543515
544- buffer = read_stream_next_buffer (stream ,NULL );
516+ buffer = ReadBufferExtended (rel ,MAIN_FORKNUM ,blkno ,RBM_NORMAL ,
517+ bstrategy );
545518LockBuffer (buffer ,BUFFER_LOCK_SHARE );
546519
547520page = BufferGetPage (buffer );
@@ -552,12 +525,6 @@ collect_visibility_data(Oid relid, bool include_pd)
552525}
553526}
554527
555- if (include_pd )
556- {
557- Assert (read_stream_next_buffer (stream ,NULL )== InvalidBuffer );
558- read_stream_end (stream );
559- }
560-
561528/* Clean up. */
562529if (vmbuffer != InvalidBuffer )
563530ReleaseBuffer (vmbuffer );
@@ -643,38 +610,6 @@ GetStrictOldestNonRemovableTransactionId(Relation rel)
643610}
644611}
645612
646- /*
647- * Callback function to get next block for read stream object used in
648- * collect_corrupt_items() function.
649- */
650- static BlockNumber
651- collect_corrupt_items_read_stream_next_block (ReadStream * stream ,
652- void * callback_private_data ,
653- void * per_buffer_data )
654- {
655- struct collect_corrupt_items_read_stream_private * p = callback_private_data ;
656-
657- for (;p -> current_blocknum < p -> last_exclusive ;p -> current_blocknum ++ )
658- {
659- bool check_frozen = false;
660- bool check_visible = false;
661-
662- /* Make sure we are interruptible. */
663- CHECK_FOR_INTERRUPTS ();
664-
665- if (p -> all_frozen && VM_ALL_FROZEN (p -> rel ,p -> current_blocknum ,& p -> vmbuffer ))
666- check_frozen = true;
667- if (p -> all_visible && VM_ALL_VISIBLE (p -> rel ,p -> current_blocknum ,& p -> vmbuffer ))
668- check_visible = true;
669- if (!check_visible && !check_frozen )
670- continue ;
671-
672- return p -> current_blocknum ++ ;
673- }
674-
675- return InvalidBlockNumber ;
676- }
677-
678613/*
679614 * Returns a list of items whose visibility map information does not match
680615 * the status of the tuples on the page.
@@ -693,13 +628,12 @@ static corrupt_items *
693628collect_corrupt_items (Oid relid ,bool all_visible ,bool all_frozen )
694629{
695630Relation rel ;
631+ BlockNumber nblocks ;
696632corrupt_items * items ;
633+ BlockNumber blkno ;
697634Buffer vmbuffer = InvalidBuffer ;
698635BufferAccessStrategy bstrategy = GetAccessStrategy (BAS_BULKREAD );
699636TransactionId OldestXmin = InvalidTransactionId ;
700- struct collect_corrupt_items_read_stream_private p ;
701- ReadStream * stream ;
702- Buffer buffer ;
703637
704638rel = relation_open (relid ,AccessShareLock );
705639
@@ -709,6 +643,8 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
709643if (all_visible )
710644OldestXmin = GetStrictOldestNonRemovableTransactionId (rel );
711645
646+ nblocks = RelationGetNumberOfBlocks (rel );
647+
712648/*
713649 * Guess an initial array size. We don't expect many corrupted tuples, so
714650 * start with a small array. This function uses the "next" field to track
@@ -722,46 +658,42 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
722658items -> count = 64 ;
723659items -> tids = palloc (items -> count * sizeof (ItemPointerData ));
724660
725- p .current_blocknum = 0 ;
726- p .last_exclusive = RelationGetNumberOfBlocks (rel );
727- p .rel = rel ;
728- p .vmbuffer = InvalidBuffer ;
729- p .all_frozen = all_frozen ;
730- p .all_visible = all_visible ;
731- stream = read_stream_begin_relation (READ_STREAM_FULL ,
732- bstrategy ,
733- rel ,
734- MAIN_FORKNUM ,
735- collect_corrupt_items_read_stream_next_block ,
736- & p ,
737- 0 );
738-
739661/* Loop over every block in the relation. */
740- while (( buffer = read_stream_next_buffer ( stream , NULL )) != InvalidBuffer )
662+ for ( blkno = 0 ; blkno < nblocks ; ++ blkno )
741663{
742664bool check_frozen = false;
743665bool check_visible = false;
666+ Buffer buffer ;
744667Page page ;
745668OffsetNumber offnum ,
746669maxoff ;
747- BlockNumber blkno ;
748670
749671/* Make sure we are interruptible. */
750672CHECK_FOR_INTERRUPTS ();
751673
674+ /* Use the visibility map to decide whether to check this page. */
675+ if (all_frozen && VM_ALL_FROZEN (rel ,blkno ,& vmbuffer ))
676+ check_frozen = true;
677+ if (all_visible && VM_ALL_VISIBLE (rel ,blkno ,& vmbuffer ))
678+ check_visible = true;
679+ if (!check_visible && !check_frozen )
680+ continue ;
681+
682+ /* Read and lock the page. */
683+ buffer = ReadBufferExtended (rel ,MAIN_FORKNUM ,blkno ,RBM_NORMAL ,
684+ bstrategy );
752685LockBuffer (buffer ,BUFFER_LOCK_SHARE );
753686
754687page = BufferGetPage (buffer );
755688maxoff = PageGetMaxOffsetNumber (page );
756- blkno = BufferGetBlockNumber (buffer );
757689
758690/*
759691 * The visibility map bits might have changed while we were acquiring
760692 * the page lock. Recheck to avoid returning spurious results.
761693 */
762- if (all_frozen && !VM_ALL_FROZEN (rel ,blkno ,& vmbuffer ))
694+ if (check_frozen && !VM_ALL_FROZEN (rel ,blkno ,& vmbuffer ))
763695check_frozen = false;
764- if (all_visible && !VM_ALL_VISIBLE (rel ,blkno ,& vmbuffer ))
696+ if (check_visible && !VM_ALL_VISIBLE (rel ,blkno ,& vmbuffer ))
765697check_visible = false;
766698if (!check_visible && !check_frozen )
767699{
@@ -846,13 +778,10 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
846778
847779UnlockReleaseBuffer (buffer );
848780}
849- read_stream_end (stream );
850781
851782/* Clean up. */
852783if (vmbuffer != InvalidBuffer )
853784ReleaseBuffer (vmbuffer );
854- if (p .vmbuffer != InvalidBuffer )
855- ReleaseBuffer (p .vmbuffer );
856785relation_close (rel ,AccessShareLock );
857786
858787/*