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 1082 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().

1085 {
1086  if (nseg == 0)
1087  {
1088  if (reln->md_num_open_segs[forknum] > 0)
1089  {
1090  pfree(reln->md_seg_fds[forknum]);
1091  reln->md_seg_fds[forknum] = NULL;
1092  }
1093  }
1094  else if (reln->md_num_open_segs[forknum] == 0)
1095  {
1096  reln->md_seg_fds[forknum] =
1097  MemoryContextAlloc(MdCxt, sizeof(MdfdVec) * nseg);
1098  }
1099  else
1100  {
1101  /*
1102  * It doesn't seem worthwhile complicating the code to amortize
1103  * repalloc() calls. Those are far faster than PathNameOpenFile() or
1104  * FileClose(), and the memory context internally will sometimes avoid
1105  * doing an actual reallocation.
1106  */
1107  reln->md_seg_fds[forknum] =
1108  repalloc(reln->md_seg_fds[forknum],
1109  sizeof(MdfdVec) * nseg);
1110  }
1111 
1112  reln->md_num_open_segs[forknum] = nseg;
1113 }
static MemoryContext MdCxt
Definition: md.c:88
void pfree(void *pointer)
Definition: mcxt.c:1169
Definition: md.c:82
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:68
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
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 1188 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().

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

◆ _mdfd_openseg()

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

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

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

◆ _mdfd_segpath()

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

Definition at line 1120 of file md.c.

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

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

1121 {
1122  char *path,
1123  *fullpath;
1124 
1125  path = relpath(reln->smgr_rnode, forknum);
1126 
1127  if (segno > 0)
1128  {
1129  fullpath = psprintf("%s.%u", path, segno);
1130  pfree(path);
1131  }
1132  else
1133  fullpath = path;
1134 
1135  return fullpath;
1136 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void pfree(void *pointer)
Definition: mcxt.c:1169
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 1313 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().

1314 {
1315  off_t len;
1316 
1317  len = FileSize(seg->mdfd_vfd);
1318  if (len < 0)
1319  ereport(ERROR,
1321  errmsg("could not seek to end of file \"%s\": %m",
1322  FilePathName(seg->mdfd_vfd))));
1323  /* note that this calculation will ignore any partial block at EOF */
1324  return (BlockNumber) (len / BLCKSZ);
1325 }
off_t FileSize(File file)
Definition: fd.c:2286
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2338
#define ERROR
Definition: elog.h:46
int errcode_for_file_access(void)
Definition: elog.c:721
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
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:641
int errcode_for_file_access(void)
Definition: elog.c:721
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ DropRelationFiles()

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

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

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

◆ ForgetDatabaseSyncRequests()

void ForgetDatabaseSyncRequests ( Oid  dbid)

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

1033 {
1034  FileTag tag;
1035  RelFileNode rnode;
1036 
1037  rnode.dbNode = dbid;
1038  rnode.spcNode = 0;
1039  rnode.relNode = 0;
1040 
1042 
1043  RegisterSyncRequest(&tag, SYNC_FILTER_REQUEST, true /* retryOnError */ );
1044 }
#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 533 of file md.c.

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

Referenced by mdexists().

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

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

◆ 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. (Note that this failure should be unreachable
430  * because of upstream checks in bufmgr.c.)
431  */
432  if (blocknum == InvalidBlockNumber)
433  ereport(ERROR,
434  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
435  errmsg("cannot extend file \"%s\" beyond %u blocks",
436  relpath(reln->smgr_rnode, forknum),
438 
439  v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_CREATE);
440 
441  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
442 
443  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
444 
445  if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ, seekpos, WAIT_EVENT_DATA_FILE_EXTEND)) != BLCKSZ)
446  {
447  if (nbytes < 0)
448  ereport(ERROR,
450  errmsg("could not extend file \"%s\": %m",
451  FilePathName(v->mdfd_vfd)),
452  errhint("Check free disk space.")));
453  /* short write: complain appropriately */
454  ereport(ERROR,
455  (errcode(ERRCODE_DISK_FULL),
456  errmsg("could not extend file \"%s\": wrote only %d of %d bytes at block %u",
458  nbytes, BLCKSZ, blocknum),
459  errhint("Check free disk space.")));
460  }
461 
462  if (!skipFsync && !SmgrIsTemp(reln))
463  register_dirty_segment(reln, forknum, v);
464 
465  Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber) RELSEG_SIZE));
466 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1188
int errhint(const char *fmt,...)
Definition: elog.c:1156
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:763
int errcode(int sqlerrcode)
Definition: elog.c:698
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:2338
#define SmgrIsTemp(smgr)
Definition: smgr.h:77
#define ERROR
Definition: elog.h:46
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
int errcode_for_file_access(void)
Definition: elog.c:721
int FileWrite(File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
Definition: fd.c:2167
Definition: md.c:82
#define ereport(elevel,...)
Definition: elog.h:157
#define EXTENSION_CREATE
Definition: md.c:108
#define Assert(condition)
Definition: c.h:804
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1313
#define InvalidBlockNumber
Definition: block.h:33
int errmsg(const char *fmt,...)
Definition: elog.c:909
#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:975

◆ mdfiletagmatches()

bool mdfiletagmatches ( const FileTag ftag,
const FileTag candidate 
)

Definition at line 1400 of file md.c.

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

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

◆ mdimmedsync()

void mdimmedsync ( SMgrRelation  reln,
ForkNumber  forknum 
)

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

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

◆ mdnblocks()

BlockNumber mdnblocks ( SMgrRelation  reln,
ForkNumber  forknum 
)

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

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

◆ mdopen()

void mdopen ( SMgrRelation  reln)

Definition at line 522 of file md.c.

References MAX_FORKNUM, and SMgrRelationData::md_num_open_segs.

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

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

◆ mdprefetch()

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

Definition at line 556 of file md.c.

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

557 {
558 #ifdef USE_PREFETCH
559  off_t seekpos;
560  MdfdVec *v;
561 
562  v = _mdfd_getseg(reln, forknum, blocknum, false,
564  if (v == NULL)
565  return false;
566 
567  seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
568 
569  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
570 
571  (void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ, WAIT_EVENT_DATA_FILE_PREFETCH);
572 #endif /* USE_PREFETCH */
573 
574  return true;
575 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1188
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
bool InRecovery
Definition: xlogutils.c:52
int FilePrefetch(File file, off_t offset, int amount, uint32 wait_event_info)
Definition: fd.c:2060
#define Assert(condition)
Definition: c.h:804
File mdfd_vfd
Definition: md.c:84

◆ mdread()

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

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

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

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

◆ mdtruncate()

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

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

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

◆ 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 1381 of file md.c.

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

1382 {
1383  char *p;
1384 
1385  /* Compute the path. */
1386  p = relpathperm(ftag->rnode, MAIN_FORKNUM);
1387  strlcpy(path, p, MAXPGPATH);
1388  pfree(p);
1389 
1390  /* Try to unlink the file. */
1391  return unlink(path);
1392 }
#define relpathperm(rnode, forknum)
Definition: relpath.h:83
RelFileNode rnode
Definition: sync.h:54
void pfree(void *pointer)
Definition: mcxt.c:1169
#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:1018
#define sprintf
Definition: port.h:219
void pfree(void *pointer)
Definition: mcxt.c:1169
static void register_unlink_segment(RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1001
int errcode_for_file_access(void)
Definition: elog.c:721
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:157
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define relpath(rnode, forknum)
Definition: relpath.h:87

◆ mdwrite()

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

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

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

◆ mdwriteback()

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

Definition at line 584 of file md.c.

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

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

References Assert, data_sync_elevel(), DEBUG1, ereport, errcode_for_file_access(), errmsg(), errmsg_internal(), 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().

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

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

Referenced by mdunlinkfork().

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

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

Referenced by mdunlinkfork().

1003 {
1004  FileTag tag;
1005 
1006  INIT_MD_FILETAG(tag, rnode.node, forknum, segno);
1007 
1008  /* Should never be used with temp relations */
1010 
1011  RegisterSyncRequest(&tag, SYNC_UNLINK_REQUEST, true /* retryOnError */ );
1012 }
#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:804
Definition: sync.h:50

Variable Documentation

◆ MdCxt

MemoryContext MdCxt
static

Definition at line 88 of file md.c.