@@ -163,23 +163,29 @@ static CycleCtr mdsync_cycle_ctr = 0;
163163static CycleCtr mdckpt_cycle_ctr = 0 ;
164164
165165
166- typedef enum /* behavior for mdopen & _mdfd_getseg */
167- {
168- /* ereport if segment not present, create in recovery */
169- EXTENSION_FAIL ,
170- /* return NULL if not present, create in recovery */
171- EXTENSION_RETURN_NULL ,
172- /* return NULL if not present */
173- EXTENSION_REALLY_RETURN_NULL ,
174- /* create new segments as needed */
175- EXTENSION_CREATE
176- }ExtensionBehavior ;
166+ /*** behavior for mdopen & _mdfd_getseg ***/
167+ /* ereport if segment not present */
168+ #define EXTENSION_FAIL (1 << 0)
169+ /* return NULL if segment not present */
170+ #define EXTENSION_RETURN_NULL (1 << 1)
171+ /* create new segments as needed */
172+ #define EXTENSION_CREATE (1 << 2)
173+ /* create new segments if needed during recovery */
174+ #define EXTENSION_CREATE_RECOVERY (1 << 3)
175+ /*
176+ * Allow opening segments which are preceded by segments smaller than
177+ * RELSEG_SIZE, e.g. inactive segments (see above). Note that this is breaks
178+ * mdnblocks() and related functionality henceforth - which currently is ok,
179+ * because this is only required in the checkpointer which never uses
180+ * mdnblocks().
181+ */
182+ #define EXTENSION_DONT_CHECK_SIZE (1 << 4)
183+
177184
178185/* local routines */
179186static void mdunlinkfork (RelFileNodeBackend rnode ,ForkNumber forkNum ,
180187bool isRedo );
181- static MdfdVec * mdopen (SMgrRelation reln ,ForkNumber forknum ,
182- ExtensionBehavior behavior );
188+ static MdfdVec * mdopen (SMgrRelation reln ,ForkNumber forknum ,int behavior );
183189static void register_dirty_segment (SMgrRelation reln ,ForkNumber forknum ,
184190MdfdVec * seg );
185191static void register_unlink (RelFileNodeBackend rnode );
@@ -189,7 +195,7 @@ static char *_mdfd_segpath(SMgrRelation reln, ForkNumber forknum,
189195static MdfdVec * _mdfd_openseg (SMgrRelation reln ,ForkNumber forkno ,
190196BlockNumber segno ,int oflags );
191197static MdfdVec * _mdfd_getseg (SMgrRelation reln ,ForkNumber forkno ,
192- BlockNumber blkno ,bool skipFsync ,ExtensionBehavior behavior );
198+ BlockNumber blkno ,bool skipFsync ,int behavior );
193199static BlockNumber _mdnblocks (SMgrRelation reln ,ForkNumber forknum ,
194200MdfdVec * seg );
195201
@@ -570,7 +576,7 @@ mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
570576 * invent one out of whole cloth.
571577 */
572578static MdfdVec *
573- mdopen (SMgrRelation reln ,ForkNumber forknum ,ExtensionBehavior behavior )
579+ mdopen (SMgrRelation reln ,ForkNumber forknum ,int behavior )
574580{
575581MdfdVec * mdfd ;
576582char * path ;
@@ -596,8 +602,7 @@ mdopen(SMgrRelation reln, ForkNumber forknum, ExtensionBehavior behavior)
596602fd = PathNameOpenFile (path ,O_RDWR |O_CREAT |O_EXCL |PG_BINARY ,0600 );
597603if (fd < 0 )
598604{
599- if ((behavior == EXTENSION_RETURN_NULL ||
600- behavior == EXTENSION_REALLY_RETURN_NULL )&&
605+ if ((behavior & EXTENSION_RETURN_NULL )&&
601606FILE_POSSIBLY_DELETED (errno ))
602607{
603608pfree (path );
@@ -690,8 +695,8 @@ mdwriteback(SMgrRelation reln, ForkNumber forknum,
690695int segnum_start ,
691696segnum_end ;
692697
693- v = _mdfd_getseg (reln ,forknum ,blocknum ,false ,
694- EXTENSION_REALLY_RETURN_NULL );
698+ v = _mdfd_getseg (reln ,forknum ,blocknum ,true /* not used */ ,
699+ EXTENSION_RETURN_NULL );
695700
696701/*
697702 * We might be flushing buffers of already removed relations, that's
@@ -737,7 +742,8 @@ mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
737742reln -> smgr_rnode .node .relNode ,
738743reln -> smgr_rnode .backend );
739744
740- v = _mdfd_getseg (reln ,forknum ,blocknum , false,EXTENSION_FAIL );
745+ v = _mdfd_getseg (reln ,forknum ,blocknum , false,
746+ EXTENSION_FAIL |EXTENSION_CREATE_RECOVERY );
741747
742748seekpos = (off_t )BLCKSZ * (blocknum % ((BlockNumber )RELSEG_SIZE ));
743749
@@ -812,7 +818,8 @@ mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
812818reln -> smgr_rnode .node .relNode ,
813819reln -> smgr_rnode .backend );
814820
815- v = _mdfd_getseg (reln ,forknum ,blocknum ,skipFsync ,EXTENSION_FAIL );
821+ v = _mdfd_getseg (reln ,forknum ,blocknum ,skipFsync ,
822+ EXTENSION_FAIL |EXTENSION_CREATE_RECOVERY );
816823
817824seekpos = (off_t )BLCKSZ * (blocknum % ((BlockNumber )RELSEG_SIZE ));
818825
@@ -1219,7 +1226,9 @@ mdsync(void)
12191226/* Attempt to open and fsync the target segment */
12201227seg = _mdfd_getseg (reln ,forknum ,
12211228 (BlockNumber )segno * (BlockNumber )RELSEG_SIZE ,
1222- false,EXTENSION_RETURN_NULL );
1229+ false,
1230+ EXTENSION_RETURN_NULL
1231+ |EXTENSION_DONT_CHECK_SIZE );
12231232
12241233INSTR_TIME_SET_CURRENT (sync_start );
12251234
@@ -1773,14 +1782,18 @@ _mdfd_openseg(SMgrRelation reln, ForkNumber forknum, BlockNumber segno,
17731782 */
17741783static MdfdVec *
17751784_mdfd_getseg (SMgrRelation reln ,ForkNumber forknum ,BlockNumber blkno ,
1776- bool skipFsync ,ExtensionBehavior behavior )
1785+ bool skipFsync ,int behavior )
17771786{
17781787MdfdVec * v = mdopen (reln ,forknum ,behavior );
17791788BlockNumber targetseg ;
17801789BlockNumber nextsegno ;
17811790
1791+ /* some way to handle non-existant segments needs to be specified */
1792+ Assert (behavior &
1793+ (EXTENSION_FAIL |EXTENSION_CREATE |EXTENSION_RETURN_NULL ));
1794+
17821795if (!v )
1783- return NULL ;/* ifEXTENSION_(REALLY_)RETURN_NULL */
1796+ return NULL ;/* ifbehavior & EXTENSION_RETURN_NULL */
17841797
17851798targetseg = blkno / ((BlockNumber )RELSEG_SIZE );
17861799for (nextsegno = 1 ;nextsegno <=targetseg ;nextsegno ++ )
@@ -1795,8 +1808,8 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
17951808if (nblocks > ((BlockNumber )RELSEG_SIZE ))
17961809elog (FATAL ,"segment too big" );
17971810
1798- if (behavior == EXTENSION_CREATE ||
1799- (InRecovery && behavior != EXTENSION_REALLY_RETURN_NULL ))
1811+ if (( behavior & EXTENSION_CREATE ) ||
1812+ (InRecovery && ( behavior & EXTENSION_CREATE_RECOVERY ) ))
18001813{
18011814/*
18021815 * Normally we will create new segments only if authorized by
@@ -1827,15 +1840,16 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
18271840}
18281841flags = O_CREAT ;
18291842}
1830- else if (nblocks < ((BlockNumber )RELSEG_SIZE ))
1843+ else if (!(behavior & EXTENSION_DONT_CHECK_SIZE )&&
1844+ nblocks < ((BlockNumber )RELSEG_SIZE ))
18311845{
18321846/*
1833- * When not extending, only open the next segment if the
1834- * current one is exactly RELSEG_SIZE. If not (this branch),
1835- * either return NULL or fail.
1847+ * When not extending (or explicitly including truncated
1848+ * segments), only open the next segment if the current one is
1849+ * exactly RELSEG_SIZE. If not (this branch), either return
1850+ * NULL or fail.
18361851 */
1837- if (behavior == EXTENSION_RETURN_NULL ||
1838- behavior == EXTENSION_REALLY_RETURN_NULL )
1852+ if (behavior & EXTENSION_RETURN_NULL )
18391853{
18401854/*
18411855 * Some callers discern between reasons for _mdfd_getseg()
@@ -1858,8 +1872,7 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
18581872
18591873if (v -> mdfd_chain == NULL )
18601874{
1861- if ((behavior == EXTENSION_RETURN_NULL ||
1862- behavior == EXTENSION_REALLY_RETURN_NULL )&&
1875+ if ((behavior & EXTENSION_RETURN_NULL )&&
18631876FILE_POSSIBLY_DELETED (errno ))
18641877return NULL ;
18651878ereport (ERROR ,