PostgreSQL Source Code  git master
md.c File Reference
#include "postgres.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>
#include "access/xlog.h"
#include "access/xlogutils.h"
#include "commands/tablespace.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "pgstat.h"
#include "postmaster/bgwriter.h"
#include "storage/bufmgr.h"
#include "storage/fd.h"
#include "storage/md.h"
#include "storage/relfilenode.h"
#include "storage/smgr.h"
#include "storage/sync.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
Include dependency graph for md.c:

Go to the source code of this file.

Data Structures

struct  _MdfdVec
 

Macros

#define INIT_MD_FILETAG(a, xx_rnode, xx_forknum, xx_segno)
 
#define EXTENSION_FAIL   (1 << 0)
 
#define EXTENSION_RETURN_NULL   (1 << 1)
 
#define EXTENSION_CREATE   (1 << 2)
 
#define EXTENSION_CREATE_RECOVERY   (1 << 3)
 
#define EXTENSION_DONT_CHECK_SIZE   (1 << 4)
 

Typedefs

typedef struct _MdfdVec MdfdVec
 

Functions

static void mdunlinkfork (RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
 
static MdfdVecmdopenfork (SMgrRelation reln, ForkNumber forknum, int behavior)
 
static void register_dirty_segment (SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
 
static void register_unlink_segment (RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno)
 
static void register_forget_request (RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno)
 
static void _fdvec_resize (SMgrRelation reln, ForkNumber forknum, int nseg)
 
static char * _mdfd_segpath (SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
 
static MdfdVec_mdfd_openseg (SMgrRelation reln, ForkNumber forkno, BlockNumber segno, int oflags)
 
static MdfdVec_mdfd_getseg (SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
 
static BlockNumber _mdnblocks (SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
 
void mdinit (void)
 
bool mdexists (SMgrRelation reln, ForkNumber forkNum)
 
void mdcreate (SMgrRelation reln, ForkNumber forkNum, bool isRedo)
 
void mdunlink (RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
 
void mdextend (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
 
void mdopen (SMgrRelation reln)
 
void mdclose (SMgrRelation reln, ForkNumber forknum)
 
bool mdprefetch (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
 
void mdwriteback (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
 
void mdread (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
 
void mdwrite (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
 
BlockNumber mdnblocks (SMgrRelation reln, ForkNumber forknum)
 
void mdtruncate (SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
 
void mdimmedsync (SMgrRelation reln, ForkNumber forknum)
 
void ForgetDatabaseSyncRequests (Oid dbid)
 
void DropRelationFiles (RelFileNode *delrels, int ndelrels, bool isRedo)
 
int mdsyncfiletag (const FileTag *ftag, char *path)
 
int mdunlinkfiletag (const FileTag *ftag, char *path)
 
bool mdfiletagmatches (const FileTag *ftag, const FileTag *candidate)
 

Variables

static MemoryContext MdCxt
 

Macro Definition Documentation

◆ EXTENSION_CREATE

#define EXTENSION_CREATE   (1 << 2)

Definition at line 108 of file md.c.

Referenced by _mdfd_getseg(), and mdextend().

◆ EXTENSION_CREATE_RECOVERY

#define EXTENSION_CREATE_RECOVERY   (1 << 3)

Definition at line 110 of file md.c.

Referenced by _mdfd_getseg(), mdread(), and mdwrite().

◆ EXTENSION_DONT_CHECK_SIZE

#define EXTENSION_DONT_CHECK_SIZE   (1 << 4)

Definition at line 118 of file md.c.

Referenced by _mdfd_getseg().

◆ EXTENSION_FAIL

#define EXTENSION_FAIL   (1 << 0)

Definition at line 104 of file md.c.

Referenced by _mdfd_getseg(), mdnblocks(), mdprefetch(), mdread(), and mdwrite().

◆ EXTENSION_RETURN_NULL

#define EXTENSION_RETURN_NULL   (1 << 1)

Definition at line 106 of file md.c.

Referenced by _mdfd_getseg(), mdexists(), mdopenfork(), mdprefetch(), and mdwriteback().

◆ INIT_MD_FILETAG

#define INIT_MD_FILETAG (   a,
  xx_rnode,
  xx_forknum,
  xx_segno 
)
Value:
( \
memset(&(a), 0, sizeof(FileTag)), \
(a).handler = SYNC_HANDLER_MD, \
(a).rnode = (xx_rnode), \
(a).forknum = (xx_forknum), \
(a).segno = (xx_segno) \
)
Definition: sync.h:50

Definition at line 92 of file md.c.

Referenced by ForgetDatabaseSyncRequests(), register_dirty_segment(), register_forget_request(), and register_unlink_segment().

Typedef Documentation

◆ MdfdVec

typedef struct _MdfdVec MdfdVec

Function Documentation

◆ _fdvec_resize()

static void _fdvec_resize ( SMgrRelation  reln,
ForkNumber  forknum,
int  nseg 
)
static

Definition at line 1054 of file md.c.

References SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, MemoryContextAlloc(), pfree(), and repalloc().

Referenced by _mdfd_openseg(), mdclose(), mdcreate(), mdimmedsync(), mdopenfork(), and mdtruncate().

1057 {
1058  if (nseg == 0)
1059  {
1060  if (reln->md_num_open_segs[forknum] > 0)
1061  {
1062  pfree(reln->md_seg_fds[forknum]);
1063  reln->md_seg_fds[forknum] = NULL;
1064  }
1065  }
1066  else if (reln->md_num_open_segs[forknum] == 0)
1067  {
1068  reln->md_seg_fds[forknum] =
1069  MemoryContextAlloc(MdCxt, sizeof(MdfdVec) * nseg);
1070  }
1071  else
1072  {
1073  /*
1074  * It doesn't seem worthwhile complicating the code to amortize
1075  * repalloc() calls. Those are far faster than PathNameOpenFile() or
1076  * FileClose(), and the memory context internally will sometimes avoid
1077  * doing an actual reallocation.
1078  */
1079  reln->md_seg_fds[forknum] =
1080  repalloc(reln->md_seg_fds[forknum],
1081  sizeof(MdfdVec) * nseg);
1082  }
1083 
1084  reln->md_num_open_segs[forknum] = nseg;
1085 }
static MemoryContext MdCxt
Definition: md.c:88
void pfree(void *pointer)
Definition: mcxt.c:1057
Definition: md.c:82
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69

◆ _mdfd_getseg()

static MdfdVec * _mdfd_getseg ( SMgrRelation  reln,
ForkNumber  forkno,
BlockNumber  blkno,
bool  skipFsync,
int  behavior 
)
static

Definition at line 1160 of file md.c.

References _mdfd_openseg(), _mdfd_segpath(), _mdnblocks(), Assert, elog, ereport, errcode_for_file_access(), errmsg(), ERROR, EXTENSION_CREATE, EXTENSION_CREATE_RECOVERY, EXTENSION_DONT_CHECK_SIZE, EXTENSION_FAIL, EXTENSION_RETURN_NULL, FATAL, FILE_POSSIBLY_DELETED, InRecovery, SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, mdextend(), _MdfdVec::mdfd_segno, mdopenfork(), palloc0(), and pfree().

Referenced by mdextend(), mdprefetch(), mdread(), mdwrite(), and mdwriteback().

1162 {
1163  MdfdVec *v;
1164  BlockNumber targetseg;
1165  BlockNumber nextsegno;
1166 
1167  /* some way to handle non-existent segments needs to be specified */
1168  Assert(behavior &
1170 
1171  targetseg = blkno / ((BlockNumber) RELSEG_SIZE);
1172 
1173  /* if an existing and opened segment, we're done */
1174  if (targetseg < reln->md_num_open_segs[forknum])
1175  {
1176  v = &reln->md_seg_fds[forknum][targetseg];
1177  return v;
1178  }
1179 
1180  /*
1181  * The target segment is not yet open. Iterate over all the segments
1182  * between the last opened and the target segment. This way missing
1183  * segments either raise an error, or get created (according to
1184  * 'behavior'). Start with either the last opened, or the first segment if
1185  * none was opened before.
1186  */
1187  if (reln->md_num_open_segs[forknum] > 0)
1188  v = &reln->md_seg_fds[forknum][reln->md_num_open_segs[forknum] - 1];
1189  else
1190  {
1191  v = mdopenfork(reln, forknum, behavior);
1192  if (!v)
1193  return NULL; /* if behavior & EXTENSION_RETURN_NULL */
1194  }
1195 
1196  for (nextsegno = reln->md_num_open_segs[forknum];
1197  nextsegno <= targetseg; nextsegno++)
1198  {
1199  BlockNumber nblocks = _mdnblocks(reln, forknum, v);
1200  int flags = 0;
1201 
1202  Assert(nextsegno == v->mdfd_segno + 1);
1203 
1204  if (nblocks > ((BlockNumber) RELSEG_SIZE))
1205  elog(FATAL, "segment too big");
1206 
1207  if ((behavior & EXTENSION_CREATE) ||
1208  (InRecovery && (behavior & EXTENSION_CREATE_RECOVERY)))
1209  {
1210  /*
1211  * Normally we will create new segments only if authorized by the
1212  * caller (i.e., we are doing mdextend()). But when doing WAL
1213  * recovery, create segments anyway; this allows cases such as
1214  * replaying WAL data that has a write into a high-numbered
1215  * segment of a relation that was later deleted. We want to go
1216  * ahead and create the segments so we can finish out the replay.
1217  *
1218  * We have to maintain the invariant that segments before the last
1219  * active segment are of size RELSEG_SIZE; therefore, if
1220  * extending, pad them out with zeroes if needed. (This only
1221  * matters if in recovery, or if the caller is extending the
1222  * relation discontiguously, but that can happen in hash indexes.)
1223  */
1224  if (nblocks < ((BlockNumber) RELSEG_SIZE))
1225  {
1226  char *zerobuf = palloc0(BLCKSZ);
1227 
1228  mdextend(reln, forknum,
1229  nextsegno * ((BlockNumber) RELSEG_SIZE) - 1,
1230  zerobuf, skipFsync);
1231  pfree(zerobuf);
1232  }
1233  flags = O_CREAT;
1234  }
1235  else if (!(behavior & EXTENSION_DONT_CHECK_SIZE) &&
1236  nblocks < ((BlockNumber) RELSEG_SIZE))
1237  {
1238  /*
1239  * When not extending (or explicitly including truncated
1240  * segments), only open the next segment if the current one is
1241  * exactly RELSEG_SIZE. If not (this branch), either return NULL
1242  * or fail.
1243  */
1244  if (behavior & EXTENSION_RETURN_NULL)
1245  {
1246  /*
1247  * Some callers discern between reasons for _mdfd_getseg()
1248  * returning NULL based on errno. As there's no failing
1249  * syscall involved in this case, explicitly set errno to
1250  * ENOENT, as that seems the closest interpretation.
1251  */
1252  errno = ENOENT;
1253  return NULL;
1254  }
1255 
1256  ereport(ERROR,
1258  errmsg("could not open file \"%s\" (target block %u): previous segment is only %u blocks",
1259  _mdfd_segpath(reln, forknum, nextsegno),
1260  blkno, nblocks)));
1261  }
1262 
1263  v = _mdfd_openseg(reln, forknum, nextsegno, flags);
1264 
1265  if (v == NULL)
1266  {
1267  if ((behavior & EXTENSION_RETURN_NULL) &&
1268  FILE_POSSIBLY_DELETED(errno))
1269  return NULL;
1270  ereport(ERROR,
1272  errmsg("could not open file \"%s\" (target block %u): %m",
1273  _mdfd_segpath(reln, forknum, nextsegno),
1274  blkno)));
1275  }
1276  }
1277 
1278  return v;
1279 }
#define EXTENSION_DONT_CHECK_SIZE
Definition: md.c:118
BlockNumber mdfd_segno
Definition: md.c:85
bool InRecovery
Definition: xlog.c:205
uint32 BlockNumber
Definition: block.h:31
#define EXTENSION_FAIL
Definition: md.c:104
void mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: md.c:387
void pfree(void *pointer)
Definition: mcxt.c:1057
static MdfdVec * mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
Definition: md.c:451
#define ERROR
Definition: elog.h:43
#define EXTENSION_RETURN_NULL
Definition: md.c:106
#define FATAL
Definition: elog.h:52
int errcode_for_file_access(void)
Definition: elog.c:633
#define EXTENSION_CREATE_RECOVERY
Definition: md.c:110
void * palloc0(Size size)
Definition: mcxt.c:981
Definition: md.c:82
static MdfdVec * _mdfd_openseg(SMgrRelation reln, ForkNumber forkno, BlockNumber segno, int oflags)
Definition: md.c:1115
#define ereport(elevel,...)
Definition: elog.h:144
#define EXTENSION_CREATE
Definition: md.c:108
#define Assert(condition)
Definition: c.h:746
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1285
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define elog(elevel,...)
Definition: elog.h:214
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69
#define FILE_POSSIBLY_DELETED(err)
Definition: fd.h:69
static char * _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1092

◆ _mdfd_openseg()

static MdfdVec * _mdfd_openseg ( SMgrRelation  reln,
ForkNumber  forkno,
BlockNumber  segno,
int  oflags 
)
static

Definition at line 1115 of file md.c.

References _fdvec_resize(), _mdfd_segpath(), _mdnblocks(), Assert, fd(), SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, _MdfdVec::mdfd_segno, _MdfdVec::mdfd_vfd, PathNameOpenFile(), pfree(), and PG_BINARY.

Referenced by _mdfd_getseg(), mdimmedsync(), and mdnblocks().

1117 {
1118  MdfdVec *v;
1119  File fd;
1120  char *fullpath;
1121 
1122  fullpath = _mdfd_segpath(reln, forknum, segno);
1123 
1124  /* open the file */
1125  fd = PathNameOpenFile(fullpath, O_RDWR | PG_BINARY | oflags);
1126 
1127  pfree(fullpath);
1128 
1129  if (fd < 0)
1130  return NULL;
1131 
1132  /*
1133  * Segments are always opened in order from lowest to highest, so we must
1134  * be adding a new one at the end.
1135  */
1136  Assert(segno == reln->md_num_open_segs[forknum]);
1137 
1138  _fdvec_resize(reln, forknum, segno + 1);
1139 
1140  /* fill the entry */
1141  v = &reln->md_seg_fds[forknum][segno];
1142  v->mdfd_vfd = fd;
1143  v->mdfd_segno = segno;
1144 
1145  Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber) RELSEG_SIZE));
1146 
1147  /* all done */
1148  return v;
1149 }
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1437
BlockNumber mdfd_segno
Definition: md.c:85
uint32 BlockNumber
Definition: block.h:31
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1213
void pfree(void *pointer)
Definition: mcxt.c:1057
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1054
Definition: md.c:82
#define Assert(condition)
Definition: c.h:746
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1285
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69
File mdfd_vfd
Definition: md.c:84
int File
Definition: fd.h:49
static char * _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1092

◆ _mdfd_segpath()

static char * _mdfd_segpath ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  segno 
)
static

Definition at line 1092 of file md.c.

References pfree(), psprintf(), relpath, and SMgrRelationData::smgr_rnode.

Referenced by _mdfd_getseg(), _mdfd_openseg(), and mdsyncfiletag().

1093 {
1094  char *path,
1095  *fullpath;
1096 
1097  path = relpath(reln->smgr_rnode, forknum);
1098 
1099  if (segno > 0)
1100  {
1101  fullpath = psprintf("%s.%u", path, segno);
1102  pfree(path);
1103  }
1104  else
1105  fullpath = path;
1106 
1107  return fullpath;
1108 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void pfree(void *pointer)
Definition: mcxt.c:1057
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
#define relpath(rnode, forknum)
Definition: relpath.h:87

◆ _mdnblocks()

static BlockNumber _mdnblocks ( SMgrRelation  reln,
ForkNumber  forknum,
MdfdVec seg 
)
static

Definition at line 1285 of file md.c.

References ereport, errcode_for_file_access(), errmsg(), ERROR, FilePathName(), FileSize(), and _MdfdVec::mdfd_vfd.

Referenced by _mdfd_getseg(), _mdfd_openseg(), mdextend(), mdnblocks(), and mdopenfork().

1286 {
1287  off_t len;
1288 
1289  len = FileSize(seg->mdfd_vfd);
1290  if (len < 0)
1291  ereport(ERROR,
1293  errmsg("could not seek to end of file \"%s\": %m",
1294  FilePathName(seg->mdfd_vfd))));
1295  /* note that this calculation will ignore any partial block at EOF */
1296  return (BlockNumber) (len / BLCKSZ);
1297 }
off_t FileSize(File file)
Definition: fd.c:2148
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2200
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:633
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:821
File mdfd_vfd
Definition: md.c:84

◆ DropRelationFiles()

void DropRelationFiles ( RelFileNode delrels,
int  ndelrels,
bool  isRedo 
)

Definition at line 1022 of file md.c.

References i, InvalidBackendId, MAX_FORKNUM, palloc(), pfree(), smgrclose(), smgrdounlinkall(), smgropen(), and XLogDropRelation().

Referenced by FinishPreparedTransaction(), xact_redo_abort(), and xact_redo_commit().

1023 {
1024  SMgrRelation *srels;
1025  int i;
1026 
1027  srels = palloc(sizeof(SMgrRelation) * ndelrels);
1028  for (i = 0; i < ndelrels; i++)
1029  {
1030  SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
1031 
1032  if (isRedo)
1033  {
1034  ForkNumber fork;
1035 
1036  for (fork = 0; fork <= MAX_FORKNUM; fork++)
1037  XLogDropRelation(delrels[i], fork);
1038  }
1039  srels[i] = srel;
1040  }
1041 
1042  smgrdounlinkall(srels, ndelrels, isRedo);
1043 
1044  for (i = 0; i < ndelrels; i++)
1045  smgrclose(srels[i]);
1046  pfree(srels);
1047 }
void smgrclose(SMgrRelation reln)
Definition: smgr.c:257
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition: smgr.c:385
void pfree(void *pointer)
Definition: mcxt.c:1057
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:146
ForkNumber
Definition: relpath.h:40
#define InvalidBackendId
Definition: backendid.h:23
#define MAX_FORKNUM
Definition: relpath.h:55
void XLogDropRelation(RelFileNode rnode, ForkNumber forknum)
Definition: xlogutils.c:614
void * palloc(Size size)
Definition: mcxt.c:950
int i

◆ ForgetDatabaseSyncRequests()

void ForgetDatabaseSyncRequests ( Oid  dbid)

Definition at line 1004 of file md.c.

References RelFileNode::dbNode, INIT_MD_FILETAG, InvalidBlockNumber, InvalidForkNumber, RegisterSyncRequest(), RelFileNode::relNode, RelFileNode::spcNode, and SYNC_FILTER_REQUEST.

Referenced by dbase_redo(), and dropdb().

1005 {
1006  FileTag tag;
1007  RelFileNode rnode;
1008 
1009  rnode.dbNode = dbid;
1010  rnode.spcNode = 0;
1011  rnode.relNode = 0;
1012 
1014 
1015  RegisterSyncRequest(&tag, SYNC_FILTER_REQUEST, true /* retryOnError */ );
1016 }
#define INIT_MD_FILETAG(a, xx_rnode, xx_forknum, xx_segno)
Definition: md.c:92
bool RegisterSyncRequest(const FileTag *ftag, SyncRequestType type, bool retryOnError)
Definition: sync.c:554
#define InvalidBlockNumber
Definition: block.h:33
Definition: sync.h:50

◆ mdclose()

void mdclose ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 505 of file md.c.

References _fdvec_resize(), FileClose(), SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, and _MdfdVec::mdfd_vfd.

Referenced by mdexists().

506 {
507  int nopensegs = reln->md_num_open_segs[forknum];
508 
509  /* No work if already closed */
510  if (nopensegs == 0)
511  return;
512 
513  /* close segments starting from the end */
514  while (nopensegs > 0)
515  {
516  MdfdVec *v = &reln->md_seg_fds[forknum][nopensegs - 1];
517 
518  FileClose(v->mdfd_vfd);
519  _fdvec_resize(reln, forknum, nopensegs - 1);
520  nopensegs--;
521  }
522 }
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1054
Definition: md.c:82
void FileClose(File file)
Definition: fd.c:1826
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69
File mdfd_vfd
Definition: md.c:84

◆ mdcreate()

void mdcreate ( SMgrRelation  reln,
ForkNumber  forkNum,
bool  isRedo 
)

Definition at line 178 of file md.c.

References _fdvec_resize(), Assert, RelFileNode::dbNode, ereport, errcode_for_file_access(), errmsg(), ERROR, fd(), SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, _MdfdVec::mdfd_segno, _MdfdVec::mdfd_vfd, RelFileNodeBackend::node, PathNameOpenFile(), pfree(), PG_BINARY, relpath, SMgrRelationData::smgr_rnode, RelFileNode::spcNode, and TablespaceCreateDbspace().

179 {
180  MdfdVec *mdfd;
181  char *path;
182  File fd;
183 
184  if (isRedo && reln->md_num_open_segs[forkNum] > 0)
185  return; /* created and opened already... */
186 
187  Assert(reln->md_num_open_segs[forkNum] == 0);
188 
189  /*
190  * We may be using the target table space for the first time in this
191  * database, so create a per-database subdirectory if needed.
192  *
193  * XXX this is a fairly ugly violation of module layering, but this seems
194  * to be the best place to put the check. Maybe TablespaceCreateDbspace
195  * should be here and not in commands/tablespace.c? But that would imply
196  * importing a lot of stuff that smgr.c oughtn't know, either.
197  */
199  reln->smgr_rnode.node.dbNode,
200  isRedo);
201 
202  path = relpath(reln->smgr_rnode, forkNum);
203 
204  fd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
205 
206  if (fd < 0)
207  {
208  int save_errno = errno;
209 
210  if (isRedo)
211  fd = PathNameOpenFile(path, O_RDWR | PG_BINARY);
212  if (fd < 0)
213  {
214  /* be sure to report the error reported by create, not open */
215  errno = save_errno;
216  ereport(ERROR,
218  errmsg("could not create file \"%s\": %m", path)));
219  }
220  }
221 
222  pfree(path);
223 
224  _fdvec_resize(reln, forkNum, 1);
225  mdfd = &reln->md_seg_fds[forkNum][0];
226  mdfd->mdfd_vfd = fd;
227  mdfd->mdfd_segno = 0;
228 }
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1437
BlockNumber mdfd_segno
Definition: md.c:85
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1213
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:633
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1054
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:144
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:746
void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
Definition: tablespace.c:115
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define relpath(rnode, forknum)
Definition: relpath.h:87
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69
File mdfd_vfd
Definition: md.c:84
int File
Definition: fd.h:49

◆ mdexists()

bool mdexists ( SMgrRelation  reln,
ForkNumber  forkNum 
)

Definition at line 161 of file md.c.

References EXTENSION_RETURN_NULL, mdclose(), and mdopenfork().

162 {
163  /*
164  * Close it first, to ensure that we notice if the fork has been unlinked
165  * since we opened it.
166  */
167  mdclose(reln, forkNum);
168 
169  return (mdopenfork(reln, forkNum, EXTENSION_RETURN_NULL) != NULL);
170 }
static MdfdVec * mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
Definition: md.c:451
#define EXTENSION_RETURN_NULL
Definition: md.c:106
void mdclose(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:505

◆ mdextend()

void mdextend ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer,
bool  skipFsync 
)

Definition at line 387 of file md.c.

References _mdfd_getseg(), _mdnblocks(), Assert, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, EXTENSION_CREATE, FilePathName(), FileWrite(), InvalidBlockNumber, _MdfdVec::mdfd_vfd, mdnblocks(), register_dirty_segment(), relpath, SMgrRelationData::smgr_rnode, SmgrIsTemp, and WAIT_EVENT_DATA_FILE_EXTEND.

Referenced by _mdfd_getseg().

389 {
390  off_t seekpos;
391  int nbytes;
392  MdfdVec *v;
393 
394  /* This assert is too expensive to have on normally ... */
395 #ifdef CHECK_WRITE_VS_EXTEND
396  Assert(blocknum >= mdnblocks(reln, forknum));
397 #endif
398 
399  /*
400  * If a relation manages to grow to 2^32-1 blocks, refuse to extend it any
401  * more --- we mustn't create a block whose number actually is
402  * InvalidBlockNumber.
403  */
404  if (blocknum == InvalidBlockNumber)
405  ereport(ERROR,
406  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
407  errmsg("cannot extend file \"%s\" beyond %u blocks",
408  relpath(reln->smgr_rnode, forknum),
410 
411  v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_CREATE);
412 
413  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
414 
415  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
416 
417  if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_EXTEND)) != BLCKSZ)
418  {
419  if (nbytes < 0)
420  ereport(ERROR,
422  errmsg("could not extend file \"%s\": %m",
423  FilePathName(v->mdfd_vfd)),
424  errhint("Check free disk space.")));
425  /* short write: complain appropriately */
426  ereport(ERROR,
427  (errcode(ERRCODE_DISK_FULL),
428  errmsg("could not extend file \"%s\": wrote only %d of %d bytes at block %u",
430  nbytes, BLCKSZ, blocknum),
431  errhint("Check free disk space.")));
432  }
433 
434  if (!skipFsync && !SmgrIsTemp(reln))
435  register_dirty_segment(reln, forknum, v);
436 
437  Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber) RELSEG_SIZE));
438 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1160
int errhint(const char *fmt,...)
Definition: elog.c:1068
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:735
int errcode(int sqlerrcode)
Definition: elog.c:610
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2200
#define SmgrIsTemp(smgr)
Definition: smgr.h:77
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:633
int FileWrite(File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
Definition: fd.c:2029
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:144
#define EXTENSION_CREATE
Definition: md.c:108
#define Assert(condition)
Definition: c.h:746
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1285
#define InvalidBlockNumber
Definition: block.h:33
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define relpath(rnode, forknum)
Definition: relpath.h:87
File mdfd_vfd
Definition: md.c:84
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:947

◆ mdfiletagmatches()

bool mdfiletagmatches ( const FileTag ftag,
const FileTag candidate 
)

Definition at line 1372 of file md.c.

References RelFileNode::dbNode, and FileTag::rnode.

1373 {
1374  /*
1375  * For now we only use filter requests as a way to drop all scheduled
1376  * callbacks relating to a given database, when dropping the database.
1377  * We'll return true for all candidates that have the same database OID as
1378  * the ftag from the SYNC_FILTER_REQUEST request, so they're forgotten.
1379  */
1380  return ftag->rnode.dbNode == candidate->rnode.dbNode;
1381 }
RelFileNode rnode
Definition: sync.h:54

◆ mdimmedsync()

void mdimmedsync ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 894 of file md.c.

References _fdvec_resize(), _mdfd_openseg(), data_sync_elevel(), ereport, errcode_for_file_access(), errmsg(), ERROR, FileClose(), FilePathName(), FileSync(), SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, _MdfdVec::mdfd_vfd, mdnblocks(), and WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC.

895 {
896  int segno;
897  int min_inactive_seg;
898 
899  /*
900  * NOTE: mdnblocks makes sure we have opened all active segments, so that
901  * fsync loop will get them all!
902  */
903  mdnblocks(reln, forknum);
904 
905  min_inactive_seg = segno = reln->md_num_open_segs[forknum];
906 
907  /*
908  * Temporarily open inactive segments, then close them after sync. There
909  * may be some inactive segments left opened after fsync() error, but that
910  * is harmless. We don't bother to clean them up and take a risk of
911  * further trouble. The next mdclose() will soon close them.
912  */
913  while (_mdfd_openseg(reln, forknum, segno, 0) != NULL)
914  segno++;
915 
916  while (segno > 0)
917  {
918  MdfdVec *v = &reln->md_seg_fds[forknum][segno - 1];
919 
923  errmsg("could not fsync file \"%s\": %m",
924  FilePathName(v->mdfd_vfd))));
925 
926  /* Close inactive segments immediately */
927  if (segno > min_inactive_seg)
928  {
929  FileClose(v->mdfd_vfd);
930  _fdvec_resize(reln, forknum, segno - 1);
931  }
932 
933  segno--;
934  }
935 }
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:735
char * FilePathName(File file)
Definition: fd.c:2200
#define ERROR
Definition: elog.h:43
int FileSync(File file, uint32 wait_event_info)
Definition: fd.c:2127
int errcode_for_file_access(void)
Definition: elog.c:633
int data_sync_elevel(int elevel)
Definition: fd.c:3603
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1054
Definition: md.c:82
static MdfdVec * _mdfd_openseg(SMgrRelation reln, ForkNumber forkno, BlockNumber segno, int oflags)
Definition: md.c:1115
#define ereport(elevel,...)
Definition: elog.h:144
void FileClose(File file)
Definition: fd.c:1826
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
int errmsg(const char *fmt,...)
Definition: elog.c:821
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69
File mdfd_vfd
Definition: md.c:84

◆ mdinit()

void mdinit ( void  )

Definition at line 148 of file md.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, and TopMemoryContext.

149 {
151  "MdSmgr",
153 }
#define AllocSetContextCreate
Definition: memutils.h:170
static MemoryContext MdCxt
Definition: md.c:88
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
MemoryContext TopMemoryContext
Definition: mcxt.c:44

◆ mdnblocks()

BlockNumber mdnblocks ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 735 of file md.c.

References _mdfd_openseg(), _mdnblocks(), Assert, elog, EXTENSION_FAIL, FATAL, SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, and mdopenfork().

Referenced by mdextend(), mdimmedsync(), mdtruncate(), and mdwrite().

736 {
737  MdfdVec *v;
738  BlockNumber nblocks;
739  BlockNumber segno;
740 
741  mdopenfork(reln, forknum, EXTENSION_FAIL);
742 
743  /* mdopen has opened the first segment */
744  Assert(reln->md_num_open_segs[forknum] > 0);
745 
746  /*
747  * Start from the last open segments, to avoid redundant seeks. We have
748  * previously verified that these segments are exactly RELSEG_SIZE long,
749  * and it's useless to recheck that each time.
750  *
751  * NOTE: this assumption could only be wrong if another backend has
752  * truncated the relation. We rely on higher code levels to handle that
753  * scenario by closing and re-opening the md fd, which is handled via
754  * relcache flush. (Since the checkpointer doesn't participate in
755  * relcache flush, it could have segment entries for inactive segments;
756  * that's OK because the checkpointer never needs to compute relation
757  * size.)
758  */
759  segno = reln->md_num_open_segs[forknum] - 1;
760  v = &reln->md_seg_fds[forknum][segno];
761 
762  for (;;)
763  {
764  nblocks = _mdnblocks(reln, forknum, v);
765  if (nblocks > ((BlockNumber) RELSEG_SIZE))
766  elog(FATAL, "segment too big");
767  if (nblocks < ((BlockNumber) RELSEG_SIZE))
768  return (segno * ((BlockNumber) RELSEG_SIZE)) + nblocks;
769 
770  /*
771  * If segment is exactly RELSEG_SIZE, advance to next one.
772  */
773  segno++;
774 
775  /*
776  * We used to pass O_CREAT here, but that has the disadvantage that it
777  * might create a segment which has vanished through some operating
778  * system misadventure. In such a case, creating the segment here
779  * undermines _mdfd_getseg's attempts to notice and report an error
780  * upon access to a missing segment.
781  */
782  v = _mdfd_openseg(reln, forknum, segno, 0);
783  if (v == NULL)
784  return segno * ((BlockNumber) RELSEG_SIZE);
785  }
786 }
uint32 BlockNumber
Definition: block.h:31
#define EXTENSION_FAIL
Definition: md.c:104
static MdfdVec * mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
Definition: md.c:451
#define FATAL
Definition: elog.h:52
Definition: md.c:82
static MdfdVec * _mdfd_openseg(SMgrRelation reln, ForkNumber forkno, BlockNumber segno, int oflags)
Definition: md.c:1115
#define Assert(condition)
Definition: c.h:746
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1285
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
#define elog(elevel,...)
Definition: elog.h:214
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69

◆ mdopen()

void mdopen ( SMgrRelation  reln)

Definition at line 494 of file md.c.

References MAX_FORKNUM, and SMgrRelationData::md_num_open_segs.

495 {
496  /* mark it not open */
497  for (int forknum = 0; forknum <= MAX_FORKNUM; forknum++)
498  reln->md_num_open_segs[forknum] = 0;
499 }
#define MAX_FORKNUM
Definition: relpath.h:55
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68

◆ mdopenfork()

static MdfdVec * mdopenfork ( SMgrRelation  reln,
ForkNumber  forknum,
int  behavior 
)
static

Definition at line 451 of file md.c.

References _fdvec_resize(), _mdnblocks(), Assert, ereport, errcode_for_file_access(), errmsg(), ERROR, EXTENSION_RETURN_NULL, fd(), FILE_POSSIBLY_DELETED, SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, _MdfdVec::mdfd_segno, _MdfdVec::mdfd_vfd, PathNameOpenFile(), pfree(), PG_BINARY, relpath, and SMgrRelationData::smgr_rnode.

Referenced by _mdfd_getseg(), mdexists(), and mdnblocks().

452 {
453  MdfdVec *mdfd;
454  char *path;
455  File fd;
456 
457  /* No work if already open */
458  if (reln->md_num_open_segs[forknum] > 0)
459  return &reln->md_seg_fds[forknum][0];
460 
461  path = relpath(reln->smgr_rnode, forknum);
462 
463  fd = PathNameOpenFile(path, O_RDWR | PG_BINARY);
464 
465  if (fd < 0)
466  {
467  if ((behavior & EXTENSION_RETURN_NULL) &&
468  FILE_POSSIBLY_DELETED(errno))
469  {
470  pfree(path);
471  return NULL;
472  }
473  ereport(ERROR,
475  errmsg("could not open file \"%s\": %m", path)));
476  }
477 
478  pfree(path);
479 
480  _fdvec_resize(reln, forknum, 1);
481  mdfd = &reln->md_seg_fds[forknum][0];
482  mdfd->mdfd_vfd = fd;
483  mdfd->mdfd_segno = 0;
484 
485  Assert(_mdnblocks(reln, forknum, mdfd) <= ((BlockNumber) RELSEG_SIZE));
486 
487  return mdfd;
488 }
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1437
BlockNumber mdfd_segno
Definition: md.c:85
uint32 BlockNumber
Definition: block.h:31
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1213
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:43
#define EXTENSION_RETURN_NULL
Definition: md.c:106
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:633
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1054
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:746
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1285
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define relpath(rnode, forknum)
Definition: relpath.h:87
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69
File mdfd_vfd
Definition: md.c:84
int File
Definition: fd.h:49
#define FILE_POSSIBLY_DELETED(err)
Definition: fd.h:69

◆ mdprefetch()

bool mdprefetch ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum 
)

Definition at line 528 of file md.c.

References _mdfd_getseg(), Assert, EXTENSION_FAIL, EXTENSION_RETURN_NULL, FilePrefetch(), InRecovery, _MdfdVec::mdfd_vfd, and WAIT_EVENT_DATA_FILE_PREFETCH.

529 {
530 #ifdef USE_PREFETCH
531  off_t seekpos;
532  MdfdVec *v;
533 
534  v = _mdfd_getseg(reln, forknum, blocknum, false,
536  if (v == NULL)
537  return false;
538 
539  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
540 
541  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
542 
543  (void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ, WAIT_EVENT_DATA_FILE_PREFETCH);
544 #endif /* USE_PREFETCH */
545 
546  return true;
547 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1160
bool InRecovery
Definition: xlog.c:205
uint32 BlockNumber
Definition: block.h:31
#define EXTENSION_FAIL
Definition: md.c:104
#define EXTENSION_RETURN_NULL
Definition: md.c:106
Definition: md.c:82
int FilePrefetch(File file, off_t offset, int amount, uint32 wait_event_info)
Definition: fd.c:1922
#define Assert(condition)
Definition: c.h:746
File mdfd_vfd
Definition: md.c:84

◆ mdread()

void mdread ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer 
)

Definition at line 605 of file md.c.

References _mdfd_getseg(), Assert, RelFileNodeBackend::backend, RelFileNode::dbNode, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errcode_for_file_access(), errmsg(), ERROR, EXTENSION_CREATE_RECOVERY, EXTENSION_FAIL, FilePathName(), FileRead(), InRecovery, _MdfdVec::mdfd_vfd, MemSet, RelFileNodeBackend::node, RelFileNode::relNode, SMgrRelationData::smgr_rnode, RelFileNode::spcNode, WAIT_EVENT_DATA_FILE_READ, and zero_damaged_pages.

607 {
608  off_t seekpos;
609  int nbytes;
610  MdfdVec *v;
611 
612  TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum,
613  reln->smgr_rnode.node.spcNode,
614  reln->smgr_rnode.node.dbNode,
615  reln->smgr_rnode.node.relNode,
616  reln->smgr_rnode.backend);
617 
618  v = _mdfd_getseg(reln, forknum, blocknum, false,
620 
621  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
622 
623  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
624 
625  nbytes = FileRead(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_READ);
626 
627  TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum,
628  reln->smgr_rnode.node.spcNode,
629  reln->smgr_rnode.node.dbNode,
630  reln->smgr_rnode.node.relNode,
631  reln->smgr_rnode.backend,
632  nbytes,
633  BLCKSZ);
634 
635  if (nbytes != BLCKSZ)
636  {
637  if (nbytes < 0)
638  ereport(ERROR,
640  errmsg("could not read block %u in file \"%s\": %m",
641  blocknum, FilePathName(v->mdfd_vfd))));
642 
643  /*
644  * Short read: we are at or past EOF, or we read a partial block at
645  * EOF. Normally this is an error; upper levels should never try to
646  * read a nonexistent block. However, if zero_damaged_pages is ON or
647  * we are InRecovery, we should instead return zeroes without
648  * complaining. This allows, for example, the case of trying to
649  * update a block that was later truncated away.
650  */
652  MemSet(buffer, 0, BLCKSZ);
653  else
654  ereport(ERROR,
656  errmsg("could not read block %u in file \"%s\": read only %d of %d bytes",
657  blocknum, FilePathName(v->mdfd_vfd),
658  nbytes, BLCKSZ)));
659  }
660 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1160
bool InRecovery
Definition: xlog.c:205
int errcode(int sqlerrcode)
Definition: elog.c:610
#define MemSet(start, val, len)
Definition: c.h:950
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2200
#define EXTENSION_FAIL
Definition: md.c:104
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:633
#define EXTENSION_CREATE_RECOVERY
Definition: md.c:110
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:45
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:144
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:746
BackendId backend
Definition: relfilenode.h:75
int errmsg(const char *fmt,...)
Definition: elog.c:821
int FileRead(File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
Definition: fd.c:1973
File mdfd_vfd
Definition: md.c:84
bool zero_damaged_pages
Definition: bufmgr.c:124

◆ mdsyncfiletag()

int mdsyncfiletag ( const FileTag ftag,
char *  path 
)

Definition at line 1306 of file md.c.

References _mdfd_segpath(), FileClose(), FilePathName(), FileSync(), FileTag::forknum, InvalidBackendId, MAXPGPATH, SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, _MdfdVec::mdfd_vfd, PathNameOpenFile(), pfree(), PG_BINARY, FileTag::rnode, FileTag::segno, smgropen(), strlcpy(), and WAIT_EVENT_DATA_FILE_SYNC.

1307 {
1309  File file;
1310  bool need_to_close;
1311  int result,
1312  save_errno;
1313 
1314  /* See if we already have the file open, or need to open it. */
1315  if (ftag->segno < reln->md_num_open_segs[ftag->forknum])
1316  {
1317  file = reln->md_seg_fds[ftag->forknum][ftag->segno].mdfd_vfd;
1318  strlcpy(path, FilePathName(file), MAXPGPATH);
1319  need_to_close = false;
1320  }
1321  else
1322  {
1323  char *p;
1324 
1325  p = _mdfd_segpath(reln, ftag->forknum, ftag->segno);
1326  strlcpy(path, p, MAXPGPATH);
1327  pfree(p);
1328 
1329  file = PathNameOpenFile(path, O_RDWR | PG_BINARY);
1330  if (file < 0)
1331  return -1;
1332  need_to_close = true;
1333  }
1334 
1335  /* Sync the file. */
1336  result = FileSync(file, WAIT_EVENT_DATA_FILE_SYNC);
1337  save_errno = errno;
1338 
1339  if (need_to_close)
1340  FileClose(file);
1341 
1342  errno = save_errno;
1343  return result;
1344 }
uint32 segno
Definition: sync.h:55
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1437
int16 forknum
Definition: sync.h:53
RelFileNode rnode
Definition: sync.h:54
char * FilePathName(File file)
Definition: fd.c:2200
#define PG_BINARY
Definition: c.h:1213
void pfree(void *pointer)
Definition: mcxt.c:1057
#define MAXPGPATH
int FileSync(File file, uint32 wait_event_info)
Definition: fd.c:2127
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:146
#define InvalidBackendId
Definition: backendid.h:23
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
void FileClose(File file)
Definition: fd.c:1826
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69
File mdfd_vfd
Definition: md.c:84
int File
Definition: fd.h:49
static char * _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1092

◆ mdtruncate()

void mdtruncate ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  nblocks 
)

Definition at line 792 of file md.c.

References _fdvec_resize(), Assert, ereport, errcode_for_file_access(), errmsg(), ERROR, FileClose(), FilePathName(), FileTruncate(), InRecovery, SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, _MdfdVec::mdfd_vfd, mdnblocks(), register_dirty_segment(), relpath, SMgrRelationData::smgr_rnode, SmgrIsTemp, and WAIT_EVENT_DATA_FILE_TRUNCATE.

793 {
794  BlockNumber curnblk;
795  BlockNumber priorblocks;
796  int curopensegs;
797 
798  /*
799  * NOTE: mdnblocks makes sure we have opened all active segments, so that
800  * truncation loop will get them all!
801  */
802  curnblk = mdnblocks(reln, forknum);
803  if (nblocks > curnblk)
804  {
805  /* Bogus request ... but no complaint if InRecovery */
806  if (InRecovery)
807  return;
808  ereport(ERROR,
809  (errmsg("could not truncate file \"%s\" to %u blocks: it's only %u blocks now",
810  relpath(reln->smgr_rnode, forknum),
811  nblocks, curnblk)));
812  }
813  if (nblocks == curnblk)
814  return; /* no work */
815 
816  /*
817  * Truncate segments, starting at the last one. Starting at the end makes
818  * managing the memory for the fd array easier, should there be errors.
819  */
820  curopensegs = reln->md_num_open_segs[forknum];
821  while (curopensegs > 0)
822  {
823  MdfdVec *v;
824 
825  priorblocks = (curopensegs - 1) * RELSEG_SIZE;
826 
827  v = &reln->md_seg_fds[forknum][curopensegs - 1];
828 
829  if (priorblocks > nblocks)
830  {
831  /*
832  * This segment is no longer active. We truncate the file, but do
833  * not delete it, for reasons explained in the header comments.
834  */
836  ereport(ERROR,
838  errmsg("could not truncate file \"%s\": %m",
839  FilePathName(v->mdfd_vfd))));
840 
841  if (!SmgrIsTemp(reln))
842  register_dirty_segment(reln, forknum, v);
843 
844  /* we never drop the 1st segment */
845  Assert(v != &reln->md_seg_fds[forknum][0]);
846 
847  FileClose(v->mdfd_vfd);
848  _fdvec_resize(reln, forknum, curopensegs - 1);
849  }
850  else if (priorblocks + ((BlockNumber) RELSEG_SIZE) > nblocks)
851  {
852  /*
853  * This is the last segment we want to keep. Truncate the file to
854  * the right length. NOTE: if nblocks is exactly a multiple K of
855  * RELSEG_SIZE, we will truncate the K+1st segment to 0 length but
856  * keep it. This adheres to the invariant given in the header
857  * comments.
858  */
859  BlockNumber lastsegblocks = nblocks - priorblocks;
860 
861  if (FileTruncate(v->mdfd_vfd, (off_t) lastsegblocks * BLCKSZ, WAIT_EVENT_DATA_FILE_TRUNCATE) < 0)
862  ereport(ERROR,
864  errmsg("could not truncate file \"%s\" to %u blocks: %m",
866  nblocks)));
867  if (!SmgrIsTemp(reln))
868  register_dirty_segment(reln, forknum, v);
869  }
870  else
871  {
872  /*
873  * We still need this segment, so nothing to do for this and any
874  * earlier segment.
875  */
876  break;
877  }
878  curopensegs--;
879  }
880 }
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:735
bool InRecovery
Definition: xlog.c:205
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2200
#define SmgrIsTemp(smgr)
Definition: smgr.h:77
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:633
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1054
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:144
void FileClose(File file)
Definition: fd.c:1826
#define Assert(condition)
Definition: c.h:746
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define relpath(rnode, forknum)
Definition: relpath.h:87
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69
int FileTruncate(File file, off_t offset, uint32 wait_event_info)
Definition: fd.c:2165
File mdfd_vfd
Definition: md.c:84
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:947

◆ mdunlink()

void mdunlink ( RelFileNodeBackend  rnode,
ForkNumber  forkNum,
bool  isRedo 
)

Definition at line 277 of file md.c.

References InvalidForkNumber, MAX_FORKNUM, and mdunlinkfork().

278 {
279  /* Now do the per-fork work */
280  if (forkNum == InvalidForkNumber)
281  {
282  for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
283  mdunlinkfork(rnode, forkNum, isRedo);
284  }
285  else
286  mdunlinkfork(rnode, forkNum, isRedo);
287 }
static void mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
Definition: md.c:290
#define MAX_FORKNUM
Definition: relpath.h:55

◆ mdunlinkfiletag()

int mdunlinkfiletag ( const FileTag ftag,
char *  path 
)

Definition at line 1353 of file md.c.

References MAIN_FORKNUM, MAXPGPATH, pfree(), relpathperm, FileTag::rnode, and strlcpy().

1354 {
1355  char *p;
1356 
1357  /* Compute the path. */
1358  p = relpathperm(ftag->rnode, MAIN_FORKNUM);
1359  strlcpy(path, p, MAXPGPATH);
1360  pfree(p);
1361 
1362  /* Try to unlink the file. */
1363  return unlink(path);
1364 }
#define relpathperm(rnode, forknum)
Definition: relpath.h:83
RelFileNode rnode
Definition: sync.h:54
void pfree(void *pointer)
Definition: mcxt.c:1057
#define MAXPGPATH
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45

◆ mdunlinkfork()

static void mdunlinkfork ( RelFileNodeBackend  rnode,
ForkNumber  forkNum,
bool  isRedo 
)
static

Definition at line 290 of file md.c.

References CloseTransientFile(), ereport, errcode_for_file_access(), errmsg(), fd(), ftruncate, MAIN_FORKNUM, OpenTransientFile(), palloc(), pfree(), PG_BINARY, register_forget_request(), register_unlink_segment(), RelFileNodeBackendIsTemp, relpath, sprintf, and WARNING.

Referenced by mdunlink().

291 {
292  char *path;
293  int ret;
294 
295  path = relpath(rnode, forkNum);
296 
297  /*
298  * Delete or truncate the first segment.
299  */
300  if (isRedo || forkNum != MAIN_FORKNUM || RelFileNodeBackendIsTemp(rnode))
301  {
302  /* First, forget any pending sync requests for the first segment */
303  if (!RelFileNodeBackendIsTemp(rnode))
304  register_forget_request(rnode, forkNum, 0 /* first seg */ );
305 
306  /* Next unlink the file */
307  ret = unlink(path);
308  if (ret < 0 && errno != ENOENT)
311  errmsg("could not remove file \"%s\": %m", path)));
312  }
313  else
314  {
315  /* truncate(2) would be easier here, but Windows hasn't got it */
316  int fd;
317 
318  fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
319  if (fd >= 0)
320  {
321  int save_errno;
322 
323  ret = ftruncate(fd, 0);
324  save_errno = errno;
325  CloseTransientFile(fd);
326  errno = save_errno;
327  }
328  else
329  ret = -1;
330  if (ret < 0 && errno != ENOENT)
333  errmsg("could not truncate file \"%s\": %m", path)));
334 
335  /* Register request to unlink first segment later */
336  register_unlink_segment(rnode, forkNum, 0 /* first seg */ );
337  }
338 
339  /*
340  * Delete any additional segments.
341  */
342  if (ret >= 0)
343  {
344  char *segpath = (char *) palloc(strlen(path) + 12);
345  BlockNumber segno;
346 
347  /*
348  * Note that because we loop until getting ENOENT, we will correctly
349  * remove all inactive segments as well as active ones.
350  */
351  for (segno = 1;; segno++)
352  {
353  /*
354  * Forget any pending sync requests for this segment before we try
355  * to unlink.
356  */
357  if (!RelFileNodeBackendIsTemp(rnode))
358  register_forget_request(rnode, forkNum, segno);
359 
360  sprintf(segpath, "%s.%u", path, segno);
361  if (unlink(segpath) < 0)
362  {
363  /* ENOENT is expected after the last segment... */
364  if (errno != ENOENT)
367  errmsg("could not remove file \"%s\": %m", segpath)));
368  break;
369  }
370  }
371  pfree(segpath);
372  }
373 
374  pfree(path);
375 }
#define RelFileNodeBackendIsTemp(rnode)
Definition: relfilenode.h:78
uint32 BlockNumber
Definition: block.h:31
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1213
static void register_forget_request(RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno)
Definition: md.c:990
#define sprintf
Definition: port.h:217
void pfree(void *pointer)
Definition: mcxt.c:1057
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2372
static void register_unlink_segment(RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno)
Definition: md.c:973
int errcode_for_file_access(void)
Definition: elog.c:633
int CloseTransientFile(int fd)
Definition: fd.c:2549
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:144
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define relpath(rnode, forknum)
Definition: relpath.h:87
#define ftruncate(a, b)
Definition: win32_port.h:65

◆ mdwrite()

void mdwrite ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer,
bool  skipFsync 
)

Definition at line 670 of file md.c.

References _mdfd_getseg(), Assert, RelFileNodeBackend::backend, RelFileNode::dbNode, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, EXTENSION_CREATE_RECOVERY, EXTENSION_FAIL, FilePathName(), FileWrite(), _MdfdVec::mdfd_vfd, mdnblocks(), RelFileNodeBackend::node, register_dirty_segment(), RelFileNode::relNode, SMgrRelationData::smgr_rnode, SmgrIsTemp, RelFileNode::spcNode, and WAIT_EVENT_DATA_FILE_WRITE.

672 {
673  off_t seekpos;
674  int nbytes;
675  MdfdVec *v;
676 
677  /* This assert is too expensive to have on normally ... */
678 #ifdef CHECK_WRITE_VS_EXTEND
679  Assert(blocknum < mdnblocks(reln, forknum));
680 #endif
681 
682  TRACE_POSTGRESQL_SMGR_MD_WRITE_START(forknum, blocknum,
683  reln->smgr_rnode.node.spcNode,
684  reln->smgr_rnode.node.dbNode,
685  reln->smgr_rnode.node.relNode,
686  reln->smgr_rnode.backend);
687 
688  v = _mdfd_getseg(reln, forknum, blocknum, skipFsync,
690 
691  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
692 
693  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
694 
695  nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_WRITE);
696 
697  TRACE_POSTGRESQL_SMGR_MD_WRITE_DONE(forknum, blocknum,
698  reln->smgr_rnode.node.spcNode,
699  reln->smgr_rnode.node.dbNode,
700  reln->smgr_rnode.node.relNode,
701  reln->smgr_rnode.backend,
702  nbytes,
703  BLCKSZ);
704 
705  if (nbytes != BLCKSZ)
706  {
707  if (nbytes < 0)
708  ereport(ERROR,
710  errmsg("could not write block %u in file \"%s\": %m",
711  blocknum, FilePathName(v->mdfd_vfd))));
712  /* short write: complain appropriately */
713  ereport(ERROR,
714  (errcode(ERRCODE_DISK_FULL),
715  errmsg("could not write block %u in file \"%s\": wrote only %d of %d bytes",
716  blocknum,
718  nbytes, BLCKSZ),
719  errhint("Check free disk space.")));
720  }
721 
722  if (!skipFsync && !SmgrIsTemp(reln))
723  register_dirty_segment(reln, forknum, v);
724 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1160
int errhint(const char *fmt,...)
Definition: elog.c:1068
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:735
int errcode(int sqlerrcode)
Definition: elog.c:610
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2200
#define EXTENSION_FAIL
Definition: md.c:104
#define SmgrIsTemp(smgr)
Definition: smgr.h:77
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:633
#define EXTENSION_CREATE_RECOVERY
Definition: md.c:110
int FileWrite(File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
Definition: fd.c:2029
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:144
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:746
BackendId backend
Definition: relfilenode.h:75
int errmsg(const char *fmt,...)
Definition: elog.c:821
File mdfd_vfd
Definition: md.c:84
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:947

◆ mdwriteback()

void mdwriteback ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
BlockNumber  nblocks 
)

Definition at line 556 of file md.c.

References _mdfd_getseg(), Assert, EXTENSION_RETURN_NULL, FileWriteback(), _MdfdVec::mdfd_vfd, and WAIT_EVENT_DATA_FILE_FLUSH.

558 {
559  /*
560  * Issue flush requests in as few requests as possible; have to split at
561  * segment boundaries though, since those are actually separate files.
562  */
563  while (nblocks > 0)
564  {
565  BlockNumber nflush = nblocks;
566  off_t seekpos;
567  MdfdVec *v;
568  int segnum_start,
569  segnum_end;
570 
571  v = _mdfd_getseg(reln, forknum, blocknum, true /* not used */ ,
573 
574  /*
575  * We might be flushing buffers of already removed relations, that's
576  * ok, just ignore that case.
577  */
578  if (!v)
579  return;
580 
581  /* compute offset inside the current segment */
582  segnum_start = blocknum / RELSEG_SIZE;
583 
584  /* compute number of desired writes within the current segment */
585  segnum_end = (blocknum + nblocks - 1) / RELSEG_SIZE;
586  if (segnum_start != segnum_end)
587  nflush = RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE));
588 
589  Assert(nflush >= 1);
590  Assert(nflush <= nblocks);
591 
592  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
593 
594  FileWriteback(v->mdfd_vfd, seekpos, (off_t) BLCKSZ * nflush, WAIT_EVENT_DATA_FILE_FLUSH);
595 
596  nblocks -= nflush;
597  blocknum += nflush;
598  }
599 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1160
uint32 BlockNumber
Definition: block.h:31
#define EXTENSION_RETURN_NULL
Definition: md.c:106
Definition: md.c:82
#define Assert(condition)
Definition: c.h:746
void FileWriteback(File file, off_t offset, off_t nbytes, uint32 wait_event_info)
Definition: fd.c:1950
File mdfd_vfd
Definition: md.c:84

◆ register_dirty_segment()

static void register_dirty_segment ( SMgrRelation  reln,
ForkNumber  forknum,
MdfdVec seg 
)
static

Definition at line 947 of file md.c.

References Assert, data_sync_elevel(), DEBUG1, ereport, errcode_for_file_access(), errmsg(), ERROR, FilePathName(), FileSync(), INIT_MD_FILETAG, _MdfdVec::mdfd_segno, _MdfdVec::mdfd_vfd, RelFileNodeBackend::node, RegisterSyncRequest(), SMgrRelationData::smgr_rnode, SmgrIsTemp, SYNC_REQUEST, and WAIT_EVENT_DATA_FILE_SYNC.

Referenced by mdextend(), mdtruncate(), and mdwrite().

948 {
949  FileTag tag;
950 
951  INIT_MD_FILETAG(tag, reln->smgr_rnode.node, forknum, seg->mdfd_segno);
952 
953  /* Temp relations should never be fsync'd */
954  Assert(!SmgrIsTemp(reln));
955 
956  if (!RegisterSyncRequest(&tag, SYNC_REQUEST, false /* retryOnError */ ))
957  {
958  ereport(DEBUG1,
959  (errmsg("could not forward fsync request because request queue is full")));
960 
964  errmsg("could not fsync file \"%s\": %m",
965  FilePathName(seg->mdfd_vfd))));
966  }
967 }
#define DEBUG1
Definition: elog.h:25
BlockNumber mdfd_segno
Definition: md.c:85
#define INIT_MD_FILETAG(a, xx_rnode, xx_forknum, xx_segno)
Definition: md.c:92
char * FilePathName(File file)
Definition: fd.c:2200
#define SmgrIsTemp(smgr)
Definition: smgr.h:77
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int FileSync(File file, uint32 wait_event_info)
Definition: fd.c:2127
int errcode_for_file_access(void)
Definition: elog.c:633
int data_sync_elevel(int elevel)
Definition: fd.c:3603
bool RegisterSyncRequest(const FileTag *ftag, SyncRequestType type, bool retryOnError)
Definition: sync.c:554
#define ereport(elevel,...)
Definition: elog.h:144
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:746
int errmsg(const char *fmt,...)
Definition: elog.c:821
File mdfd_vfd
Definition: md.c:84
Definition: sync.h:50

◆ register_forget_request()

static void register_forget_request ( RelFileNodeBackend  rnode,
ForkNumber  forknum,
BlockNumber  segno 
)
static

Definition at line 990 of file md.c.

References INIT_MD_FILETAG, RelFileNodeBackend::node, RegisterSyncRequest(), and SYNC_FORGET_REQUEST.

Referenced by mdunlinkfork().

992 {
993  FileTag tag;
994 
995  INIT_MD_FILETAG(tag, rnode.node, forknum, segno);
996 
997  RegisterSyncRequest(&tag, SYNC_FORGET_REQUEST, true /* retryOnError */ );
998 }
#define INIT_MD_FILETAG(a, xx_rnode, xx_forknum, xx_segno)
Definition: md.c:92
bool RegisterSyncRequest(const FileTag *ftag, SyncRequestType type, bool retryOnError)
Definition: sync.c:554
RelFileNode node
Definition: relfilenode.h:74
Definition: sync.h:50

◆ register_unlink_segment()

static void register_unlink_segment ( RelFileNodeBackend  rnode,
ForkNumber  forknum,
BlockNumber  segno 
)
static

Definition at line 973 of file md.c.

References Assert, INIT_MD_FILETAG, RelFileNodeBackend::node, RegisterSyncRequest(), RelFileNodeBackendIsTemp, and SYNC_UNLINK_REQUEST.

Referenced by mdunlinkfork().

975 {
976  FileTag tag;
977 
978  INIT_MD_FILETAG(tag, rnode.node, forknum, segno);
979 
980  /* Should never be used with temp relations */
982 
983  RegisterSyncRequest(&tag, SYNC_UNLINK_REQUEST, true /* retryOnError */ );
984 }
#define RelFileNodeBackendIsTemp(rnode)
Definition: relfilenode.h:78
#define INIT_MD_FILETAG(a, xx_rnode, xx_forknum, xx_segno)
Definition: md.c:92
bool RegisterSyncRequest(const FileTag *ftag, SyncRequestType type, bool retryOnError)
Definition: sync.c:554
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:746
Definition: sync.h:50

Variable Documentation

◆ MdCxt

MemoryContext MdCxt
static

Definition at line 88 of file md.c.