@@ -163,23 +163,29 @@ static CycleCtr mdsync_cycle_ctr = 0;
163
163
static CycleCtr mdckpt_cycle_ctr = 0 ;
164
164
165
165
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
+
177
184
178
185
/* local routines */
179
186
static void mdunlinkfork (RelFileNodeBackend rnode , ForkNumber forkNum ,
180
187
bool isRedo );
181
- static MdfdVec * mdopen (SMgrRelation reln , ForkNumber forknum ,
182
- ExtensionBehavior behavior );
188
+ static MdfdVec * mdopen (SMgrRelation reln , ForkNumber forknum , int behavior );
183
189
static void register_dirty_segment (SMgrRelation reln , ForkNumber forknum ,
184
190
MdfdVec * seg );
185
191
static void register_unlink (RelFileNodeBackend rnode );
@@ -189,7 +195,7 @@ static char *_mdfd_segpath(SMgrRelation reln, ForkNumber forknum,
189
195
static MdfdVec * _mdfd_openseg (SMgrRelation reln , ForkNumber forkno ,
190
196
BlockNumber segno , int oflags );
191
197
static MdfdVec * _mdfd_getseg (SMgrRelation reln , ForkNumber forkno ,
192
- BlockNumber blkno , bool skipFsync , ExtensionBehavior behavior );
198
+ BlockNumber blkno , bool skipFsync , int behavior );
193
199
static BlockNumber _mdnblocks (SMgrRelation reln , ForkNumber forknum ,
194
200
MdfdVec * seg );
195
201
@@ -570,7 +576,7 @@ mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
570
576
* invent one out of whole cloth.
571
577
*/
572
578
static MdfdVec *
573
- mdopen (SMgrRelation reln , ForkNumber forknum , ExtensionBehavior behavior )
579
+ mdopen (SMgrRelation reln , ForkNumber forknum , int behavior )
574
580
{
575
581
MdfdVec * mdfd ;
576
582
char * path ;
@@ -596,8 +602,7 @@ mdopen(SMgrRelation reln, ForkNumber forknum, ExtensionBehavior behavior)
596
602
fd = PathNameOpenFile (path , O_RDWR | O_CREAT | O_EXCL | PG_BINARY , 0600 );
597
603
if (fd < 0 )
598
604
{
599
- if ((behavior == EXTENSION_RETURN_NULL ||
600
- behavior == EXTENSION_REALLY_RETURN_NULL ) &&
605
+ if ((behavior & EXTENSION_RETURN_NULL ) &&
601
606
FILE_POSSIBLY_DELETED (errno ))
602
607
{
603
608
pfree (path );
@@ -690,8 +695,8 @@ mdwriteback(SMgrRelation reln, ForkNumber forknum,
690
695
int segnum_start ,
691
696
segnum_end ;
692
697
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 );
695
700
696
701
/*
697
702
* We might be flushing buffers of already removed relations, that's
@@ -737,7 +742,8 @@ mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
737
742
reln -> smgr_rnode .node .relNode ,
738
743
reln -> smgr_rnode .backend );
739
744
740
- v = _mdfd_getseg (reln , forknum , blocknum , false, EXTENSION_FAIL );
745
+ v = _mdfd_getseg (reln , forknum , blocknum , false,
746
+ EXTENSION_FAIL | EXTENSION_CREATE_RECOVERY );
741
747
742
748
seekpos = (off_t ) BLCKSZ * (blocknum % ((BlockNumber ) RELSEG_SIZE ));
743
749
@@ -812,7 +818,8 @@ mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
812
818
reln -> smgr_rnode .node .relNode ,
813
819
reln -> smgr_rnode .backend );
814
820
815
- v = _mdfd_getseg (reln , forknum , blocknum , skipFsync , EXTENSION_FAIL );
821
+ v = _mdfd_getseg (reln , forknum , blocknum , skipFsync ,
822
+ EXTENSION_FAIL | EXTENSION_CREATE_RECOVERY );
816
823
817
824
seekpos = (off_t ) BLCKSZ * (blocknum % ((BlockNumber ) RELSEG_SIZE ));
818
825
@@ -1219,7 +1226,9 @@ mdsync(void)
1219
1226
/* Attempt to open and fsync the target segment */
1220
1227
seg = _mdfd_getseg (reln , forknum ,
1221
1228
(BlockNumber ) segno * (BlockNumber ) RELSEG_SIZE ,
1222
- false, EXTENSION_RETURN_NULL );
1229
+ false,
1230
+ EXTENSION_RETURN_NULL
1231
+ | EXTENSION_DONT_CHECK_SIZE );
1223
1232
1224
1233
INSTR_TIME_SET_CURRENT (sync_start );
1225
1234
@@ -1773,14 +1782,18 @@ _mdfd_openseg(SMgrRelation reln, ForkNumber forknum, BlockNumber segno,
1773
1782
*/
1774
1783
static MdfdVec *
1775
1784
_mdfd_getseg (SMgrRelation reln , ForkNumber forknum , BlockNumber blkno ,
1776
- bool skipFsync , ExtensionBehavior behavior )
1785
+ bool skipFsync , int behavior )
1777
1786
{
1778
1787
MdfdVec * v = mdopen (reln , forknum , behavior );
1779
1788
BlockNumber targetseg ;
1780
1789
BlockNumber nextsegno ;
1781
1790
1791
+ /* some way to handle non-existant segments needs to be specified */
1792
+ Assert (behavior &
1793
+ (EXTENSION_FAIL | EXTENSION_CREATE | EXTENSION_RETURN_NULL ));
1794
+
1782
1795
if (!v )
1783
- return NULL ; /* if EXTENSION_(REALLY_)RETURN_NULL */
1796
+ return NULL ; /* if behavior & EXTENSION_RETURN_NULL */
1784
1797
1785
1798
targetseg = blkno / ((BlockNumber ) RELSEG_SIZE );
1786
1799
for (nextsegno = 1 ; nextsegno <= targetseg ; nextsegno ++ )
@@ -1795,8 +1808,8 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
1795
1808
if (nblocks > ((BlockNumber ) RELSEG_SIZE ))
1796
1809
elog (FATAL , "segment too big" );
1797
1810
1798
- if (behavior == EXTENSION_CREATE ||
1799
- (InRecovery && behavior != EXTENSION_REALLY_RETURN_NULL ))
1811
+ if (( behavior & EXTENSION_CREATE ) ||
1812
+ (InRecovery && ( behavior & EXTENSION_CREATE_RECOVERY ) ))
1800
1813
{
1801
1814
/*
1802
1815
* Normally we will create new segments only if authorized by
@@ -1827,15 +1840,16 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
1827
1840
}
1828
1841
flags = O_CREAT ;
1829
1842
}
1830
- else if (nblocks < ((BlockNumber ) RELSEG_SIZE ))
1843
+ else if (!(behavior & EXTENSION_DONT_CHECK_SIZE ) &&
1844
+ nblocks < ((BlockNumber ) RELSEG_SIZE ))
1831
1845
{
1832
1846
/*
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.
1836
1851
*/
1837
- if (behavior == EXTENSION_RETURN_NULL ||
1838
- behavior == EXTENSION_REALLY_RETURN_NULL )
1852
+ if (behavior & EXTENSION_RETURN_NULL )
1839
1853
{
1840
1854
/*
1841
1855
* Some callers discern between reasons for _mdfd_getseg()
@@ -1858,8 +1872,7 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
1858
1872
1859
1873
if (v -> mdfd_chain == NULL )
1860
1874
{
1861
- if ((behavior == EXTENSION_RETURN_NULL ||
1862
- behavior == EXTENSION_REALLY_RETURN_NULL ) &&
1875
+ if ((behavior & EXTENSION_RETURN_NULL ) &&
1863
1876
FILE_POSSIBLY_DELETED (errno ))
1864
1877
return NULL ;
1865
1878
ereport (ERROR ,
0 commit comments