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)
 
static int do_truncate (const char *path)
 
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 1081 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().

1084 {
1085  if (nseg == 0)
1086  {
1087  if (reln->md_num_open_segs[forknum] > 0)
1088  {
1089  pfree(reln->md_seg_fds[forknum]);
1090  reln->md_seg_fds[forknum] = NULL;
1091  }
1092  }
1093  else if (reln->md_num_open_segs[forknum] == 0)
1094  {
1095  reln->md_seg_fds[forknum] =
1096  MemoryContextAlloc(MdCxt, sizeof(MdfdVec) * nseg);
1097  }
1098  else
1099  {
1100  /*
1101  * It doesn't seem worthwhile complicating the code to amortize
1102  * repalloc() calls. Those are far faster than PathNameOpenFile() or
1103  * FileClose(), and the memory context internally will sometimes avoid
1104  * doing an actual reallocation.
1105  */
1106  reln->md_seg_fds[forknum] =
1107  repalloc(reln->md_seg_fds[forknum],
1108  sizeof(MdfdVec) * nseg);
1109  }
1110 
1111  reln->md_num_open_segs[forknum] = nseg;
1112 }
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 1187 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().

1189 {
1190  MdfdVec *v;
1191  BlockNumber targetseg;
1192  BlockNumber nextsegno;
1193 
1194  /* some way to handle non-existent segments needs to be specified */
1195  Assert(behavior &
1197 
1198  targetseg = blkno / ((BlockNumber) RELSEG_SIZE);
1199 
1200  /* if an existing and opened segment, we're done */
1201  if (targetseg < reln->md_num_open_segs[forknum])
1202  {
1203  v = &reln->md_seg_fds[forknum][targetseg];
1204  return v;
1205  }
1206 
1207  /*
1208  * The target segment is not yet open. Iterate over all the segments
1209  * between the last opened and the target segment. This way missing
1210  * segments either raise an error, or get created (according to
1211  * 'behavior'). Start with either the last opened, or the first segment if
1212  * none was opened before.
1213  */
1214  if (reln->md_num_open_segs[forknum] > 0)
1215  v = &reln->md_seg_fds[forknum][reln->md_num_open_segs[forknum] - 1];
1216  else
1217  {
1218  v = mdopenfork(reln, forknum, behavior);
1219  if (!v)
1220  return NULL; /* if behavior & EXTENSION_RETURN_NULL */
1221  }
1222 
1223  for (nextsegno = reln->md_num_open_segs[forknum];
1224  nextsegno <= targetseg; nextsegno++)
1225  {
1226  BlockNumber nblocks = _mdnblocks(reln, forknum, v);
1227  int flags = 0;
1228 
1229  Assert(nextsegno == v->mdfd_segno + 1);
1230 
1231  if (nblocks > ((BlockNumber) RELSEG_SIZE))
1232  elog(FATAL, "segment too big");
1233 
1234  if ((behavior & EXTENSION_CREATE) ||
1235  (InRecovery && (behavior & EXTENSION_CREATE_RECOVERY)))
1236  {
1237  /*
1238  * Normally we will create new segments only if authorized by the
1239  * caller (i.e., we are doing mdextend()). But when doing WAL
1240  * recovery, create segments anyway; this allows cases such as
1241  * replaying WAL data that has a write into a high-numbered
1242  * segment of a relation that was later deleted. We want to go
1243  * ahead and create the segments so we can finish out the replay.
1244  *
1245  * We have to maintain the invariant that segments before the last
1246  * active segment are of size RELSEG_SIZE; therefore, if
1247  * extending, pad them out with zeroes if needed. (This only
1248  * matters if in recovery, or if the caller is extending the
1249  * relation discontiguously, but that can happen in hash indexes.)
1250  */
1251  if (nblocks < ((BlockNumber) RELSEG_SIZE))
1252  {
1253  char *zerobuf = palloc0(BLCKSZ);
1254 
1255  mdextend(reln, forknum,
1256  nextsegno * ((BlockNumber) RELSEG_SIZE) - 1,
1257  zerobuf, skipFsync);
1258  pfree(zerobuf);
1259  }
1260  flags = O_CREAT;
1261  }
1262  else if (!(behavior & EXTENSION_DONT_CHECK_SIZE) &&
1263  nblocks < ((BlockNumber) RELSEG_SIZE))
1264  {
1265  /*
1266  * When not extending (or explicitly including truncated
1267  * segments), only open the next segment if the current one is
1268  * exactly RELSEG_SIZE. If not (this branch), either return NULL
1269  * or fail.
1270  */
1271  if (behavior & EXTENSION_RETURN_NULL)
1272  {
1273  /*
1274  * Some callers discern between reasons for _mdfd_getseg()
1275  * returning NULL based on errno. As there's no failing
1276  * syscall involved in this case, explicitly set errno to
1277  * ENOENT, as that seems the closest interpretation.
1278  */
1279  errno = ENOENT;
1280  return NULL;
1281  }
1282 
1283  ereport(ERROR,
1285  errmsg("could not open file \"%s\" (target block %u): previous segment is only %u blocks",
1286  _mdfd_segpath(reln, forknum, nextsegno),
1287  blkno, nblocks)));
1288  }
1289 
1290  v = _mdfd_openseg(reln, forknum, nextsegno, flags);
1291 
1292  if (v == NULL)
1293  {
1294  if ((behavior & EXTENSION_RETURN_NULL) &&
1295  FILE_POSSIBLY_DELETED(errno))
1296  return NULL;
1297  ereport(ERROR,
1299  errmsg("could not open file \"%s\" (target block %u): %m",
1300  _mdfd_segpath(reln, forknum, nextsegno),
1301  blkno)));
1302  }
1303  }
1304 
1305  return v;
1306 }
#define EXTENSION_DONT_CHECK_SIZE
Definition: md.c:118
BlockNumber mdfd_segno
Definition: md.c:85
bool InRecovery
Definition: xlog.c:206
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:414
void pfree(void *pointer)
Definition: mcxt.c:1057
static MdfdVec * mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
Definition: md.c:478
#define ERROR
Definition: elog.h:45
#define EXTENSION_RETURN_NULL
Definition: md.c:106
#define FATAL
Definition: elog.h:54
int errcode_for_file_access(void)
Definition: elog.c:727
#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:1142
#define ereport(elevel,...)
Definition: elog.h:155
#define EXTENSION_CREATE
Definition: md.c:108
#define Assert(condition)
Definition: c.h:792
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1312
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
int errmsg(const char *fmt,...)
Definition: elog.c:915
#define elog(elevel,...)
Definition: elog.h:228
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69
#define FILE_POSSIBLY_DELETED(err)
Definition: fd.h:70
static char * _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1119

◆ _mdfd_openseg()

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

Definition at line 1142 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().

1144 {
1145  MdfdVec *v;
1146  File fd;
1147  char *fullpath;
1148 
1149  fullpath = _mdfd_segpath(reln, forknum, segno);
1150 
1151  /* open the file */
1152  fd = PathNameOpenFile(fullpath, O_RDWR | PG_BINARY | oflags);
1153 
1154  pfree(fullpath);
1155 
1156  if (fd < 0)
1157  return NULL;
1158 
1159  /*
1160  * Segments are always opened in order from lowest to highest, so we must
1161  * be adding a new one at the end.
1162  */
1163  Assert(segno == reln->md_num_open_segs[forknum]);
1164 
1165  _fdvec_resize(reln, forknum, segno + 1);
1166 
1167  /* fill the entry */
1168  v = &reln->md_seg_fds[forknum][segno];
1169  v->mdfd_vfd = fd;
1170  v->mdfd_segno = segno;
1171 
1172  Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber) RELSEG_SIZE));
1173 
1174  /* all done */
1175  return v;
1176 }
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1465
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:1259
void pfree(void *pointer)
Definition: mcxt.c:1057
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1081
Definition: md.c:82
#define Assert(condition)
Definition: c.h:792
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1312
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:48
static char * _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1119

◆ _mdfd_segpath()

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

Definition at line 1119 of file md.c.

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

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

1120 {
1121  char *path,
1122  *fullpath;
1123 
1124  path = relpath(reln->smgr_rnode, forknum);
1125 
1126  if (segno > 0)
1127  {
1128  fullpath = psprintf("%s.%u", path, segno);
1129  pfree(path);
1130  }
1131  else
1132  fullpath = path;
1133 
1134  return fullpath;
1135 }
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 1312 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().

1313 {
1314  off_t len;
1315 
1316  len = FileSize(seg->mdfd_vfd);
1317  if (len < 0)
1318  ereport(ERROR,
1320  errmsg("could not seek to end of file \"%s\": %m",
1321  FilePathName(seg->mdfd_vfd))));
1322  /* note that this calculation will ignore any partial block at EOF */
1323  return (BlockNumber) (len / BLCKSZ);
1324 }
off_t FileSize(File file)
Definition: fd.c:2180
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2232
#define ERROR
Definition: elog.h:45
int errcode_for_file_access(void)
Definition: elog.c:727
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:915
File mdfd_vfd
Definition: md.c:84

◆ do_truncate()

static int do_truncate ( const char *  path)
static

Definition at line 293 of file md.c.

References ereport, errcode_for_file_access(), errmsg(), pg_truncate(), and WARNING.

Referenced by mdunlinkfork().

294 {
295  int save_errno;
296  int ret;
297 
298  ret = pg_truncate(path, 0);
299 
300  /* Log a warning here to avoid repetition in callers. */
301  if (ret < 0 && errno != ENOENT)
302  {
303  save_errno = errno;
306  errmsg("could not truncate file \"%s\": %m", path)));
307  errno = save_errno;
308  }
309 
310  return ret;
311 }
int pg_truncate(const char *path, off_t length)
Definition: fd.c:630
int errcode_for_file_access(void)
Definition: elog.c:727
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:915

◆ DropRelationFiles()

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

Definition at line 1049 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().

1050 {
1051  SMgrRelation *srels;
1052  int i;
1053 
1054  srels = palloc(sizeof(SMgrRelation) * ndelrels);
1055  for (i = 0; i < ndelrels; i++)
1056  {
1057  SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
1058 
1059  if (isRedo)
1060  {
1061  ForkNumber fork;
1062 
1063  for (fork = 0; fork <= MAX_FORKNUM; fork++)
1064  XLogDropRelation(delrels[i], fork);
1065  }
1066  srels[i] = srel;
1067  }
1068 
1069  smgrdounlinkall(srels, ndelrels, isRedo);
1070 
1071  for (i = 0; i < ndelrels; i++)
1072  smgrclose(srels[i]);
1073  pfree(srels);
1074 }
void smgrclose(SMgrRelation reln)
Definition: smgr.c:256
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition: smgr.c:384
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:613
void * palloc(Size size)
Definition: mcxt.c:950
int i

◆ ForgetDatabaseSyncRequests()

void ForgetDatabaseSyncRequests ( Oid  dbid)

Definition at line 1031 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().

1032 {
1033  FileTag tag;
1034  RelFileNode rnode;
1035 
1036  rnode.dbNode = dbid;
1037  rnode.spcNode = 0;
1038  rnode.relNode = 0;
1039 
1041 
1042  RegisterSyncRequest(&tag, SYNC_FILTER_REQUEST, true /* retryOnError */ );
1043 }
#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:553
#define InvalidBlockNumber
Definition: block.h:33
Definition: sync.h:50

◆ mdclose()

void mdclose ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 532 of file md.c.

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

Referenced by mdexists().

533 {
534  int nopensegs = reln->md_num_open_segs[forknum];
535 
536  /* No work if already closed */
537  if (nopensegs == 0)
538  return;
539 
540  /* close segments starting from the end */
541  while (nopensegs > 0)
542  {
543  MdfdVec *v = &reln->md_seg_fds[forknum][nopensegs - 1];
544 
545  FileClose(v->mdfd_vfd);
546  _fdvec_resize(reln, forknum, nopensegs - 1);
547  nopensegs--;
548  }
549 }
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1081
Definition: md.c:82
void FileClose(File file)
Definition: fd.c:1854
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:1465
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:1259
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:45
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:727
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1081
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:155
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:792
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:915
#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:48

◆ 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:478
#define EXTENSION_RETURN_NULL
Definition: md.c:106
void mdclose(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:532

◆ mdextend()

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

Definition at line 414 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().

416 {
417  off_t seekpos;
418  int nbytes;
419  MdfdVec *v;
420 
421  /* This assert is too expensive to have on normally ... */
422 #ifdef CHECK_WRITE_VS_EXTEND
423  Assert(blocknum >= mdnblocks(reln, forknum));
424 #endif
425 
426  /*
427  * If a relation manages to grow to 2^32-1 blocks, refuse to extend it any
428  * more --- we mustn't create a block whose number actually is
429  * InvalidBlockNumber.
430  */
431  if (blocknum == InvalidBlockNumber)
432  ereport(ERROR,
433  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
434  errmsg("cannot extend file \"%s\" beyond %u blocks",
435  relpath(reln->smgr_rnode, forknum),
437 
438  v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_CREATE);
439 
440  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
441 
442  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
443 
444  if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_EXTEND)) != BLCKSZ)
445  {
446  if (nbytes < 0)
447  ereport(ERROR,
449  errmsg("could not extend file \"%s\": %m",
450  FilePathName(v->mdfd_vfd)),
451  errhint("Check free disk space.")));
452  /* short write: complain appropriately */
453  ereport(ERROR,
454  (errcode(ERRCODE_DISK_FULL),
455  errmsg("could not extend file \"%s\": wrote only %d of %d bytes at block %u",
457  nbytes, BLCKSZ, blocknum),
458  errhint("Check free disk space.")));
459  }
460 
461  if (!skipFsync && !SmgrIsTemp(reln))
462  register_dirty_segment(reln, forknum, v);
463 
464  Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber) RELSEG_SIZE));
465 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1187
int errhint(const char *fmt,...)
Definition: elog.c:1162
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:762
int errcode(int sqlerrcode)
Definition: elog.c:704
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2232
#define SmgrIsTemp(smgr)
Definition: smgr.h:77
#define ERROR
Definition: elog.h:45
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:727
int FileWrite(File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
Definition: fd.c:2061
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:155
#define EXTENSION_CREATE
Definition: md.c:108
#define Assert(condition)
Definition: c.h:792
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1312
#define InvalidBlockNumber
Definition: block.h:33
int errmsg(const char *fmt,...)
Definition: elog.c:915
#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:974

◆ mdfiletagmatches()

bool mdfiletagmatches ( const FileTag ftag,
const FileTag candidate 
)

Definition at line 1399 of file md.c.

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

1400 {
1401  /*
1402  * For now we only use filter requests as a way to drop all scheduled
1403  * callbacks relating to a given database, when dropping the database.
1404  * We'll return true for all candidates that have the same database OID as
1405  * the ftag from the SYNC_FILTER_REQUEST request, so they're forgotten.
1406  */
1407  return ftag->rnode.dbNode == candidate->rnode.dbNode;
1408 }
RelFileNode rnode
Definition: sync.h:54

◆ mdimmedsync()

void mdimmedsync ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 921 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.

922 {
923  int segno;
924  int min_inactive_seg;
925 
926  /*
927  * NOTE: mdnblocks makes sure we have opened all active segments, so that
928  * fsync loop will get them all!
929  */
930  mdnblocks(reln, forknum);
931 
932  min_inactive_seg = segno = reln->md_num_open_segs[forknum];
933 
934  /*
935  * Temporarily open inactive segments, then close them after sync. There
936  * may be some inactive segments left opened after fsync() error, but that
937  * is harmless. We don't bother to clean them up and take a risk of
938  * further trouble. The next mdclose() will soon close them.
939  */
940  while (_mdfd_openseg(reln, forknum, segno, 0) != NULL)
941  segno++;
942 
943  while (segno > 0)
944  {
945  MdfdVec *v = &reln->md_seg_fds[forknum][segno - 1];
946 
950  errmsg("could not fsync file \"%s\": %m",
951  FilePathName(v->mdfd_vfd))));
952 
953  /* Close inactive segments immediately */
954  if (segno > min_inactive_seg)
955  {
956  FileClose(v->mdfd_vfd);
957  _fdvec_resize(reln, forknum, segno - 1);
958  }
959 
960  segno--;
961  }
962 }
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:762
char * FilePathName(File file)
Definition: fd.c:2232
#define ERROR
Definition: elog.h:45
int FileSync(File file, uint32 wait_event_info)
Definition: fd.c:2159
int errcode_for_file_access(void)
Definition: elog.c:727
int data_sync_elevel(int elevel)
Definition: fd.c:3635
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1081
Definition: md.c:82
static MdfdVec * _mdfd_openseg(SMgrRelation reln, ForkNumber forkno, BlockNumber segno, int oflags)
Definition: md.c:1142
#define ereport(elevel,...)
Definition: elog.h:155
void FileClose(File file)
Definition: fd.c:1854
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
int errmsg(const char *fmt,...)
Definition: elog.c:915
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 762 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().

763 {
764  MdfdVec *v;
765  BlockNumber nblocks;
766  BlockNumber segno;
767 
768  mdopenfork(reln, forknum, EXTENSION_FAIL);
769 
770  /* mdopen has opened the first segment */
771  Assert(reln->md_num_open_segs[forknum] > 0);
772 
773  /*
774  * Start from the last open segments, to avoid redundant seeks. We have
775  * previously verified that these segments are exactly RELSEG_SIZE long,
776  * and it's useless to recheck that each time.
777  *
778  * NOTE: this assumption could only be wrong if another backend has
779  * truncated the relation. We rely on higher code levels to handle that
780  * scenario by closing and re-opening the md fd, which is handled via
781  * relcache flush. (Since the checkpointer doesn't participate in
782  * relcache flush, it could have segment entries for inactive segments;
783  * that's OK because the checkpointer never needs to compute relation
784  * size.)
785  */
786  segno = reln->md_num_open_segs[forknum] - 1;
787  v = &reln->md_seg_fds[forknum][segno];
788 
789  for (;;)
790  {
791  nblocks = _mdnblocks(reln, forknum, v);
792  if (nblocks > ((BlockNumber) RELSEG_SIZE))
793  elog(FATAL, "segment too big");
794  if (nblocks < ((BlockNumber) RELSEG_SIZE))
795  return (segno * ((BlockNumber) RELSEG_SIZE)) + nblocks;
796 
797  /*
798  * If segment is exactly RELSEG_SIZE, advance to next one.
799  */
800  segno++;
801 
802  /*
803  * We used to pass O_CREAT here, but that has the disadvantage that it
804  * might create a segment which has vanished through some operating
805  * system misadventure. In such a case, creating the segment here
806  * undermines _mdfd_getseg's attempts to notice and report an error
807  * upon access to a missing segment.
808  */
809  v = _mdfd_openseg(reln, forknum, segno, 0);
810  if (v == NULL)
811  return segno * ((BlockNumber) RELSEG_SIZE);
812  }
813 }
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:478
#define FATAL
Definition: elog.h:54
Definition: md.c:82
static MdfdVec * _mdfd_openseg(SMgrRelation reln, ForkNumber forkno, BlockNumber segno, int oflags)
Definition: md.c:1142
#define Assert(condition)
Definition: c.h:792
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1312
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
#define elog(elevel,...)
Definition: elog.h:228
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:69

◆ mdopen()

void mdopen ( SMgrRelation  reln)

Definition at line 521 of file md.c.

References MAX_FORKNUM, and SMgrRelationData::md_num_open_segs.

522 {
523  /* mark it not open */
524  for (int forknum = 0; forknum <= MAX_FORKNUM; forknum++)
525  reln->md_num_open_segs[forknum] = 0;
526 }
#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 478 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().

479 {
480  MdfdVec *mdfd;
481  char *path;
482  File fd;
483 
484  /* No work if already open */
485  if (reln->md_num_open_segs[forknum] > 0)
486  return &reln->md_seg_fds[forknum][0];
487 
488  path = relpath(reln->smgr_rnode, forknum);
489 
490  fd = PathNameOpenFile(path, O_RDWR | PG_BINARY);
491 
492  if (fd < 0)
493  {
494  if ((behavior & EXTENSION_RETURN_NULL) &&
495  FILE_POSSIBLY_DELETED(errno))
496  {
497  pfree(path);
498  return NULL;
499  }
500  ereport(ERROR,
502  errmsg("could not open file \"%s\": %m", path)));
503  }
504 
505  pfree(path);
506 
507  _fdvec_resize(reln, forknum, 1);
508  mdfd = &reln->md_seg_fds[forknum][0];
509  mdfd->mdfd_vfd = fd;
510  mdfd->mdfd_segno = 0;
511 
512  Assert(_mdnblocks(reln, forknum, mdfd) <= ((BlockNumber) RELSEG_SIZE));
513 
514  return mdfd;
515 }
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1465
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:1259
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:45
#define EXTENSION_RETURN_NULL
Definition: md.c:106
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:727
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1081
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:792
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1312
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
int errmsg(const char *fmt,...)
Definition: elog.c:915
#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:48
#define FILE_POSSIBLY_DELETED(err)
Definition: fd.h:70

◆ mdprefetch()

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

Definition at line 555 of file md.c.

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

556 {
557 #ifdef USE_PREFETCH
558  off_t seekpos;
559  MdfdVec *v;
560 
561  v = _mdfd_getseg(reln, forknum, blocknum, false,
563  if (v == NULL)
564  return false;
565 
566  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
567 
568  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
569 
570  (void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ, WAIT_EVENT_DATA_FILE_PREFETCH);
571 #endif /* USE_PREFETCH */
572 
573  return true;
574 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1187
bool InRecovery
Definition: xlog.c:206
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:1954
#define Assert(condition)
Definition: c.h:792
File mdfd_vfd
Definition: md.c:84

◆ mdread()

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

Definition at line 632 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.

634 {
635  off_t seekpos;
636  int nbytes;
637  MdfdVec *v;
638 
639  TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum,
640  reln->smgr_rnode.node.spcNode,
641  reln->smgr_rnode.node.dbNode,
642  reln->smgr_rnode.node.relNode,
643  reln->smgr_rnode.backend);
644 
645  v = _mdfd_getseg(reln, forknum, blocknum, false,
647 
648  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
649 
650  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
651 
652  nbytes = FileRead(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_READ);
653 
654  TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum,
655  reln->smgr_rnode.node.spcNode,
656  reln->smgr_rnode.node.dbNode,
657  reln->smgr_rnode.node.relNode,
658  reln->smgr_rnode.backend,
659  nbytes,
660  BLCKSZ);
661 
662  if (nbytes != BLCKSZ)
663  {
664  if (nbytes < 0)
665  ereport(ERROR,
667  errmsg("could not read block %u in file \"%s\": %m",
668  blocknum, FilePathName(v->mdfd_vfd))));
669 
670  /*
671  * Short read: we are at or past EOF, or we read a partial block at
672  * EOF. Normally this is an error; upper levels should never try to
673  * read a nonexistent block. However, if zero_damaged_pages is ON or
674  * we are InRecovery, we should instead return zeroes without
675  * complaining. This allows, for example, the case of trying to
676  * update a block that was later truncated away.
677  */
679  MemSet(buffer, 0, BLCKSZ);
680  else
681  ereport(ERROR,
683  errmsg("could not read block %u in file \"%s\": read only %d of %d bytes",
684  blocknum, FilePathName(v->mdfd_vfd),
685  nbytes, BLCKSZ)));
686  }
687 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1187
bool InRecovery
Definition: xlog.c:206
int errcode(int sqlerrcode)
Definition: elog.c:704
#define MemSet(start, val, len)
Definition: c.h:996
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2232
#define EXTENSION_FAIL
Definition: md.c:104
#define ERROR
Definition: elog.h:45
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:727
#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:155
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:792
BackendId backend
Definition: relfilenode.h:75
int errmsg(const char *fmt,...)
Definition: elog.c:915
int FileRead(File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
Definition: fd.c:2005
File mdfd_vfd
Definition: md.c:84
bool zero_damaged_pages
Definition: bufmgr.c:132

◆ mdsyncfiletag()

int mdsyncfiletag ( const FileTag ftag,
char *  path 
)

Definition at line 1333 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.

1334 {
1336  File file;
1337  bool need_to_close;
1338  int result,
1339  save_errno;
1340 
1341  /* See if we already have the file open, or need to open it. */
1342  if (ftag->segno < reln->md_num_open_segs[ftag->forknum])
1343  {
1344  file = reln->md_seg_fds[ftag->forknum][ftag->segno].mdfd_vfd;
1345  strlcpy(path, FilePathName(file), MAXPGPATH);
1346  need_to_close = false;
1347  }
1348  else
1349  {
1350  char *p;
1351 
1352  p = _mdfd_segpath(reln, ftag->forknum, ftag->segno);
1353  strlcpy(path, p, MAXPGPATH);
1354  pfree(p);
1355 
1356  file = PathNameOpenFile(path, O_RDWR | PG_BINARY);
1357  if (file < 0)
1358  return -1;
1359  need_to_close = true;
1360  }
1361 
1362  /* Sync the file. */
1363  result = FileSync(file, WAIT_EVENT_DATA_FILE_SYNC);
1364  save_errno = errno;
1365 
1366  if (need_to_close)
1367  FileClose(file);
1368 
1369  errno = save_errno;
1370  return result;
1371 }
uint32 segno
Definition: sync.h:55
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1465
int16 forknum
Definition: sync.h:53
RelFileNode rnode
Definition: sync.h:54
char * FilePathName(File file)
Definition: fd.c:2232
#define PG_BINARY
Definition: c.h:1259
void pfree(void *pointer)
Definition: mcxt.c:1057
#define MAXPGPATH
int FileSync(File file, uint32 wait_event_info)
Definition: fd.c:2159
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:1854
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:48
static char * _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1119

◆ mdtruncate()

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

Definition at line 819 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.

820 {
821  BlockNumber curnblk;
822  BlockNumber priorblocks;
823  int curopensegs;
824 
825  /*
826  * NOTE: mdnblocks makes sure we have opened all active segments, so that
827  * truncation loop will get them all!
828  */
829  curnblk = mdnblocks(reln, forknum);
830  if (nblocks > curnblk)
831  {
832  /* Bogus request ... but no complaint if InRecovery */
833  if (InRecovery)
834  return;
835  ereport(ERROR,
836  (errmsg("could not truncate file \"%s\" to %u blocks: it's only %u blocks now",
837  relpath(reln->smgr_rnode, forknum),
838  nblocks, curnblk)));
839  }
840  if (nblocks == curnblk)
841  return; /* no work */
842 
843  /*
844  * Truncate segments, starting at the last one. Starting at the end makes
845  * managing the memory for the fd array easier, should there be errors.
846  */
847  curopensegs = reln->md_num_open_segs[forknum];
848  while (curopensegs > 0)
849  {
850  MdfdVec *v;
851 
852  priorblocks = (curopensegs - 1) * RELSEG_SIZE;
853 
854  v = &reln->md_seg_fds[forknum][curopensegs - 1];
855 
856  if (priorblocks > nblocks)
857  {
858  /*
859  * This segment is no longer active. We truncate the file, but do
860  * not delete it, for reasons explained in the header comments.
861  */
863  ereport(ERROR,
865  errmsg("could not truncate file \"%s\": %m",
866  FilePathName(v->mdfd_vfd))));
867 
868  if (!SmgrIsTemp(reln))
869  register_dirty_segment(reln, forknum, v);
870 
871  /* we never drop the 1st segment */
872  Assert(v != &reln->md_seg_fds[forknum][0]);
873 
874  FileClose(v->mdfd_vfd);
875  _fdvec_resize(reln, forknum, curopensegs - 1);
876  }
877  else if (priorblocks + ((BlockNumber) RELSEG_SIZE) > nblocks)
878  {
879  /*
880  * This is the last segment we want to keep. Truncate the file to
881  * the right length. NOTE: if nblocks is exactly a multiple K of
882  * RELSEG_SIZE, we will truncate the K+1st segment to 0 length but
883  * keep it. This adheres to the invariant given in the header
884  * comments.
885  */
886  BlockNumber lastsegblocks = nblocks - priorblocks;
887 
888  if (FileTruncate(v->mdfd_vfd, (off_t) lastsegblocks * BLCKSZ, WAIT_EVENT_DATA_FILE_TRUNCATE) < 0)
889  ereport(ERROR,
891  errmsg("could not truncate file \"%s\" to %u blocks: %m",
893  nblocks)));
894  if (!SmgrIsTemp(reln))
895  register_dirty_segment(reln, forknum, v);
896  }
897  else
898  {
899  /*
900  * We still need this segment, so nothing to do for this and any
901  * earlier segment.
902  */
903  break;
904  }
905  curopensegs--;
906  }
907 }
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:762
bool InRecovery
Definition: xlog.c:206
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2232
#define SmgrIsTemp(smgr)
Definition: smgr.h:77
#define ERROR
Definition: elog.h:45
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:727
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1081
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:155
void FileClose(File file)
Definition: fd.c:1854
#define Assert(condition)
Definition: c.h:792
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
int errmsg(const char *fmt,...)
Definition: elog.c:915
#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:2197
File mdfd_vfd
Definition: md.c:84
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:974

◆ 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:314
#define MAX_FORKNUM
Definition: relpath.h:55

◆ mdunlinkfiletag()

int mdunlinkfiletag ( const FileTag ftag,
char *  path 
)

Definition at line 1380 of file md.c.

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

1381 {
1382  char *p;
1383 
1384  /* Compute the path. */
1385  p = relpathperm(ftag->rnode, MAIN_FORKNUM);
1386  strlcpy(path, p, MAXPGPATH);
1387  pfree(p);
1388 
1389  /* Try to unlink the file. */
1390  return unlink(path);
1391 }
#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 314 of file md.c.

References do_truncate(), ereport, errcode_for_file_access(), errmsg(), MAIN_FORKNUM, palloc(), pfree(), register_forget_request(), register_unlink_segment(), RelFileNodeBackendIsTemp, relpath, sprintf, and WARNING.

Referenced by mdunlink().

315 {
316  char *path;
317  int ret;
318 
319  path = relpath(rnode, forkNum);
320 
321  /*
322  * Delete or truncate the first segment.
323  */
324  if (isRedo || forkNum != MAIN_FORKNUM || RelFileNodeBackendIsTemp(rnode))
325  {
326  if (!RelFileNodeBackendIsTemp(rnode))
327  {
328  /* Prevent other backends' fds from holding on to the disk space */
329  ret = do_truncate(path);
330 
331  /* Forget any pending sync requests for the first segment */
332  register_forget_request(rnode, forkNum, 0 /* first seg */ );
333  }
334  else
335  ret = 0;
336 
337  /* Next unlink the file, unless it was already found to be missing */
338  if (ret == 0 || errno != ENOENT)
339  {
340  ret = unlink(path);
341  if (ret < 0 && errno != ENOENT)
344  errmsg("could not remove file \"%s\": %m", path)));
345  }
346  }
347  else
348  {
349  /* Prevent other backends' fds from holding on to the disk space */
350  ret = do_truncate(path);
351 
352  /* Register request to unlink first segment later */
353  register_unlink_segment(rnode, forkNum, 0 /* first seg */ );
354  }
355 
356  /*
357  * Delete any additional segments.
358  */
359  if (ret >= 0)
360  {
361  char *segpath = (char *) palloc(strlen(path) + 12);
362  BlockNumber segno;
363 
364  /*
365  * Note that because we loop until getting ENOENT, we will correctly
366  * remove all inactive segments as well as active ones.
367  */
368  for (segno = 1;; segno++)
369  {
370  sprintf(segpath, "%s.%u", path, segno);
371 
372  if (!RelFileNodeBackendIsTemp(rnode))
373  {
374  /*
375  * Prevent other backends' fds from holding on to the disk
376  * space.
377  */
378  if (do_truncate(segpath) < 0 && errno == ENOENT)
379  break;
380 
381  /*
382  * Forget any pending sync requests for this segment before we
383  * try to unlink.
384  */
385  register_forget_request(rnode, forkNum, segno);
386  }
387 
388  if (unlink(segpath) < 0)
389  {
390  /* ENOENT is expected after the last segment... */
391  if (errno != ENOENT)
394  errmsg("could not remove file \"%s\": %m", segpath)));
395  break;
396  }
397  }
398  pfree(segpath);
399  }
400 
401  pfree(path);
402 }
#define RelFileNodeBackendIsTemp(rnode)
Definition: relfilenode.h:78
static int do_truncate(const char *path)
Definition: md.c:293
uint32 BlockNumber
Definition: block.h:31
static void register_forget_request(RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1017
#define sprintf
Definition: port.h:217
void pfree(void *pointer)
Definition: mcxt.c:1057
static void register_unlink_segment(RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1000
int errcode_for_file_access(void)
Definition: elog.c:727
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:155
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:915
#define relpath(rnode, forknum)
Definition: relpath.h:87

◆ mdwrite()

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

Definition at line 697 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.

699 {
700  off_t seekpos;
701  int nbytes;
702  MdfdVec *v;
703 
704  /* This assert is too expensive to have on normally ... */
705 #ifdef CHECK_WRITE_VS_EXTEND
706  Assert(blocknum < mdnblocks(reln, forknum));
707 #endif
708 
709  TRACE_POSTGRESQL_SMGR_MD_WRITE_START(forknum, blocknum,
710  reln->smgr_rnode.node.spcNode,
711  reln->smgr_rnode.node.dbNode,
712  reln->smgr_rnode.node.relNode,
713  reln->smgr_rnode.backend);
714 
715  v = _mdfd_getseg(reln, forknum, blocknum, skipFsync,
717 
718  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
719 
720  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
721 
722  nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_WRITE);
723 
724  TRACE_POSTGRESQL_SMGR_MD_WRITE_DONE(forknum, blocknum,
725  reln->smgr_rnode.node.spcNode,
726  reln->smgr_rnode.node.dbNode,
727  reln->smgr_rnode.node.relNode,
728  reln->smgr_rnode.backend,
729  nbytes,
730  BLCKSZ);
731 
732  if (nbytes != BLCKSZ)
733  {
734  if (nbytes < 0)
735  ereport(ERROR,
737  errmsg("could not write block %u in file \"%s\": %m",
738  blocknum, FilePathName(v->mdfd_vfd))));
739  /* short write: complain appropriately */
740  ereport(ERROR,
741  (errcode(ERRCODE_DISK_FULL),
742  errmsg("could not write block %u in file \"%s\": wrote only %d of %d bytes",
743  blocknum,
745  nbytes, BLCKSZ),
746  errhint("Check free disk space.")));
747  }
748 
749  if (!skipFsync && !SmgrIsTemp(reln))
750  register_dirty_segment(reln, forknum, v);
751 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1187
int errhint(const char *fmt,...)
Definition: elog.c:1162
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:762
int errcode(int sqlerrcode)
Definition: elog.c:704
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2232
#define EXTENSION_FAIL
Definition: md.c:104
#define SmgrIsTemp(smgr)
Definition: smgr.h:77
#define ERROR
Definition: elog.h:45
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:727
#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:2061
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:155
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:792
BackendId backend
Definition: relfilenode.h:75
int errmsg(const char *fmt,...)
Definition: elog.c:915
File mdfd_vfd
Definition: md.c:84
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:974

◆ mdwriteback()

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

Definition at line 583 of file md.c.

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

585 {
586  /*
587  * Issue flush requests in as few requests as possible; have to split at
588  * segment boundaries though, since those are actually separate files.
589  */
590  while (nblocks > 0)
591  {
592  BlockNumber nflush = nblocks;
593  off_t seekpos;
594  MdfdVec *v;
595  int segnum_start,
596  segnum_end;
597 
598  v = _mdfd_getseg(reln, forknum, blocknum, true /* not used */ ,
600 
601  /*
602  * We might be flushing buffers of already removed relations, that's
603  * ok, just ignore that case.
604  */
605  if (!v)
606  return;
607 
608  /* compute offset inside the current segment */
609  segnum_start = blocknum / RELSEG_SIZE;
610 
611  /* compute number of desired writes within the current segment */
612  segnum_end = (blocknum + nblocks - 1) / RELSEG_SIZE;
613  if (segnum_start != segnum_end)
614  nflush = RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE));
615 
616  Assert(nflush >= 1);
617  Assert(nflush <= nblocks);
618 
619  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
620 
621  FileWriteback(v->mdfd_vfd, seekpos, (off_t) BLCKSZ * nflush, WAIT_EVENT_DATA_FILE_FLUSH);
622 
623  nblocks -= nflush;
624  blocknum += nflush;
625  }
626 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1187
uint32 BlockNumber
Definition: block.h:31
#define EXTENSION_RETURN_NULL
Definition: md.c:106
Definition: md.c:82
#define Assert(condition)
Definition: c.h:792
void FileWriteback(File file, off_t offset, off_t nbytes, uint32 wait_event_info)
Definition: fd.c:1982
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 974 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().

975 {
976  FileTag tag;
977 
978  INIT_MD_FILETAG(tag, reln->smgr_rnode.node, forknum, seg->mdfd_segno);
979 
980  /* Temp relations should never be fsync'd */
981  Assert(!SmgrIsTemp(reln));
982 
983  if (!RegisterSyncRequest(&tag, SYNC_REQUEST, false /* retryOnError */ ))
984  {
985  ereport(DEBUG1,
986  (errmsg("could not forward fsync request because request queue is full")));
987 
991  errmsg("could not fsync file \"%s\": %m",
992  FilePathName(seg->mdfd_vfd))));
993  }
994 }
#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:2232
#define SmgrIsTemp(smgr)
Definition: smgr.h:77
#define ERROR
Definition: elog.h:45
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int FileSync(File file, uint32 wait_event_info)
Definition: fd.c:2159
int errcode_for_file_access(void)
Definition: elog.c:727
int data_sync_elevel(int elevel)
Definition: fd.c:3635
bool RegisterSyncRequest(const FileTag *ftag, SyncRequestType type, bool retryOnError)
Definition: sync.c:553
#define ereport(elevel,...)
Definition: elog.h:155
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:792
int errmsg(const char *fmt,...)
Definition: elog.c:915
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 1017 of file md.c.

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

Referenced by mdunlinkfork().

1019 {
1020  FileTag tag;
1021 
1022  INIT_MD_FILETAG(tag, rnode.node, forknum, segno);
1023 
1024  RegisterSyncRequest(&tag, SYNC_FORGET_REQUEST, true /* retryOnError */ );
1025 }
#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:553
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 1000 of file md.c.

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

Referenced by mdunlinkfork().

1002 {
1003  FileTag tag;
1004 
1005  INIT_MD_FILETAG(tag, rnode.node, forknum, segno);
1006 
1007  /* Should never be used with temp relations */
1009 
1010  RegisterSyncRequest(&tag, SYNC_UNLINK_REQUEST, true /* retryOnError */ );
1011 }
#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:553
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:792
Definition: sync.h:50

Variable Documentation

◆ MdCxt

MemoryContext MdCxt
static

Definition at line 88 of file md.c.