92 #define INIT_MD_FILETAG(a,xx_rnode,xx_forknum,xx_segno) \
94 memset(&(a), 0, sizeof(FileTag)), \
95 (a).handler = SYNC_HANDLER_MD, \
96 (a).rnode = (xx_rnode), \
97 (a).forknum = (xx_forknum), \
98 (a).segno = (xx_segno) \
104 #define EXTENSION_FAIL (1 << 0)
106 #define EXTENSION_RETURN_NULL (1 << 1)
108 #define EXTENSION_CREATE (1 << 2)
110 #define EXTENSION_CREATE_RECOVERY (1 << 3)
118 #define EXTENSION_DONT_CHECK_SIZE (1 << 4)
120 #define EXTENSION_DONT_OPEN (1 << 5)
212 int save_errno = errno;
222 errmsg(
"could not create file \"%s\": %m", path)));
286 for (forkNum = 0; forkNum <=
MAX_FORKNUM; forkNum++)
305 if (ret < 0 && errno != ENOENT)
310 errmsg(
"could not truncate file \"%s\": %m", path)));
323 path =
relpath(rnode, forkNum);
342 if (ret == 0 || errno != ENOENT)
345 if (ret < 0 && errno != ENOENT)
348 errmsg(
"could not remove file \"%s\": %m", path)));
365 char *segpath = (
char *)
palloc(strlen(path) + 12);
372 for (segno = 1;; segno++)
374 sprintf(segpath,
"%s.%u", path, segno);
392 if (unlink(segpath) < 0)
398 errmsg(
"could not remove file \"%s\": %m", segpath)));
419 char *buffer,
bool skipFsync)
426 #ifdef CHECK_WRITE_VS_EXTEND
438 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
439 errmsg(
"cannot extend file \"%s\" beyond %u blocks",
445 seekpos = (off_t) BLCKSZ * (blocknum % ((
BlockNumber) RELSEG_SIZE));
447 Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
454 errmsg(
"could not extend file \"%s\": %m",
456 errhint(
"Check free disk space.")));
460 errmsg(
"could not extend file \"%s\": wrote only %d of %d bytes at block %u",
462 nbytes, BLCKSZ, blocknum),
463 errhint(
"Check free disk space.")));
507 errmsg(
"could not open file \"%s\": %m", path)));
529 for (
int forknum = 0; forknum <=
MAX_FORKNUM; forknum++)
546 while (nopensegs > 0)
571 seekpos = (off_t) BLCKSZ * (blocknum % ((
BlockNumber) RELSEG_SIZE));
573 Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
617 segnum_start = blocknum / RELSEG_SIZE;
620 segnum_end = (blocknum + nblocks - 1) / RELSEG_SIZE;
621 if (segnum_start != segnum_end)
622 nflush = RELSEG_SIZE - (blocknum % ((
BlockNumber) RELSEG_SIZE));
625 Assert(nflush <= nblocks);
627 seekpos = (off_t) BLCKSZ * (blocknum % ((
BlockNumber) RELSEG_SIZE));
647 TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum,
656 seekpos = (off_t) BLCKSZ * (blocknum % ((
BlockNumber) RELSEG_SIZE));
658 Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
662 TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum,
670 if (nbytes != BLCKSZ)
675 errmsg(
"could not read block %u in file \"%s\": %m",
687 MemSet(buffer, 0, BLCKSZ);
691 errmsg(
"could not read block %u in file \"%s\": read only %d of %d bytes",
706 char *buffer,
bool skipFsync)
713 #ifdef CHECK_WRITE_VS_EXTEND
717 TRACE_POSTGRESQL_SMGR_MD_WRITE_START(forknum, blocknum,
726 seekpos = (off_t) BLCKSZ * (blocknum % ((
BlockNumber) RELSEG_SIZE));
728 Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
732 TRACE_POSTGRESQL_SMGR_MD_WRITE_DONE(forknum, blocknum,
740 if (nbytes != BLCKSZ)
745 errmsg(
"could not write block %u in file \"%s\": %m",
750 errmsg(
"could not write block %u in file \"%s\": wrote only %d of %d bytes",
754 errhint(
"Check free disk space.")));
803 return (segno * ((
BlockNumber) RELSEG_SIZE)) + nblocks;
838 if (nblocks > curnblk)
844 (
errmsg(
"could not truncate file \"%s\" to %u blocks: it's only %u blocks now",
848 if (nblocks == curnblk)
856 while (curopensegs > 0)
860 priorblocks = (curopensegs - 1) * RELSEG_SIZE;
862 v = &reln->
md_seg_fds[forknum][curopensegs - 1];
864 if (priorblocks > nblocks)
873 errmsg(
"could not truncate file \"%s\": %m",
885 else if (priorblocks + ((
BlockNumber) RELSEG_SIZE) > nblocks)
899 errmsg(
"could not truncate file \"%s\" to %u blocks: %m",
932 int min_inactive_seg;
958 errmsg(
"could not fsync file \"%s\": %m",
962 if (segno > min_inactive_seg)
994 (
errmsg_internal(
"could not forward fsync request because request queue is full")));
999 errmsg(
"could not fsync file \"%s\": %m",
1063 for (
i = 0;
i < ndelrels;
i++)
1079 for (
i = 0;
i < ndelrels;
i++)
1136 fullpath =
psprintf(
"%s.%u", path, segno);
1196 bool skipFsync,
int behavior)
1210 if (targetseg < reln->md_num_open_segs[forknum])
1237 nextsegno <= targetseg; nextsegno++)
1266 char *zerobuf =
palloc0(BLCKSZ);
1270 zerobuf, skipFsync);
1298 errmsg(
"could not open file \"%s\" (target block %u): previous segment is only %u blocks",
1312 errmsg(
"could not open file \"%s\" (target block %u): %m",
1333 errmsg(
"could not seek to end of file \"%s\": %m",
1359 need_to_close =
false;
1372 need_to_close =
true;
1403 return unlink(path);
void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
#define InvalidBlockNumber
#define MemSet(start, val, len)
int errmsg_internal(const char *fmt,...)
int errcode_for_file_access(void)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void FileWriteback(File file, off_t offset, off_t nbytes, uint32 wait_event_info)
int FilePrefetch(File file, off_t offset, int amount, uint32 wait_event_info)
int FileSync(File file, uint32 wait_event_info)
void FileClose(File file)
int data_sync_elevel(int elevel)
File PathNameOpenFile(const char *fileName, int fileFlags)
int FileWrite(File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
char * FilePathName(File file)
int FileRead(File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
off_t FileSize(File file)
int FileTruncate(File file, off_t offset, uint32 wait_event_info)
int pg_truncate(const char *path, off_t length)
#define FILE_POSSIBLY_DELETED(err)
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
MemoryContext TopMemoryContext
void * palloc0(Size size)
void * repalloc(void *pointer, Size size)
void * MemoryContextAlloc(MemoryContext context, Size size)
#define EXTENSION_CREATE_RECOVERY
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
bool mdfiletagmatches(const FileTag *ftag, const FileTag *candidate)
static MdfdVec * _mdfd_openseg(SMgrRelation reln, ForkNumber forkno, BlockNumber segno, int oflags)
#define EXTENSION_DONT_OPEN
bool mdexists(SMgrRelation reln, ForkNumber forkNum)
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
int mdunlinkfiletag(const FileTag *ftag, char *path)
static void register_unlink_segment(RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno)
static MemoryContext MdCxt
void mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
void DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo)
void mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
static int do_truncate(const char *path)
void mdclose(SMgrRelation reln, ForkNumber forknum)
void mdunlink(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
int mdsyncfiletag(const FileTag *ftag, char *path)
void mdwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
#define INIT_MD_FILETAG(a, xx_rnode, xx_forknum, xx_segno)
#define EXTENSION_RETURN_NULL
static char * _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
void mdopen(SMgrRelation reln)
void mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
bool mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
#define EXTENSION_DONT_CHECK_SIZE
static MdfdVec * mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
void mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
void ForgetDatabaseSyncRequests(Oid dbid)
void mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
void mdimmedsync(SMgrRelation reln, ForkNumber forknum)
static void mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
static void register_forget_request(RelFileNodeBackend rnode, ForkNumber forknum, BlockNumber segno)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define ERRCODE_DATA_CORRUPTED
size_t strlcpy(char *dst, const char *src, size_t siz)
static int fd(const char *x, int i)
char * psprintf(const char *fmt,...)
#define RelFileNodeBackendIsTemp(rnode)
#define relpathperm(rnode, forknum)
#define relpath(rnode, forknum)
void smgrclose(SMgrRelation reln)
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
int md_num_open_segs[MAX_FORKNUM+1]
RelFileNodeBackend smgr_rnode
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
bool RegisterSyncRequest(const FileTag *ftag, SyncRequestType type, bool retryOnError)
@ WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC
@ WAIT_EVENT_DATA_FILE_READ
@ WAIT_EVENT_DATA_FILE_WRITE
@ WAIT_EVENT_DATA_FILE_FLUSH
@ WAIT_EVENT_DATA_FILE_EXTEND
@ WAIT_EVENT_DATA_FILE_TRUNCATE
@ WAIT_EVENT_DATA_FILE_PREFETCH
@ WAIT_EVENT_DATA_FILE_SYNC
void XLogDropRelation(RelFileNode rnode, ForkNumber forknum)