92 #define INIT_MD_FILETAG(a,xx_rlocator,xx_forknum,xx_segno) \
94 memset(&(a), 0, sizeof(FileTag)), \
95 (a).handler = SYNC_HANDLER_MD, \
96 (a).rlocator = (xx_rlocator), \
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)));
301 for (forknum = 0; forknum <=
MAX_FORKNUM; forknum++)
320 if (ret < 0 && errno != ENOENT)
325 errmsg(
"could not truncate file \"%s\": %m", path)));
339 path =
relpath(rlocator, forknum);
362 if (ret >= 0 || errno != ENOENT)
365 if (ret < 0 && errno != ENOENT)
370 errmsg(
"could not remove file \"%s\": %m", path)));
398 if (ret >= 0 || errno != ENOENT)
400 char *segpath = (
char *)
palloc(strlen(path) + 12);
403 for (segno = 1;; segno++)
405 sprintf(segpath,
"%s.%u", path, segno);
423 if (unlink(segpath) < 0)
429 errmsg(
"could not remove file \"%s\": %m", segpath)));
450 const void *buffer,
bool skipFsync)
457 #ifdef CHECK_WRITE_VS_EXTEND
469 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
470 errmsg(
"cannot extend file \"%s\" beyond %u blocks",
476 seekpos = (off_t) BLCKSZ * (blocknum % ((
BlockNumber) RELSEG_SIZE));
478 Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
485 errmsg(
"could not extend file \"%s\": %m",
487 errhint(
"Check free disk space.")));
491 errmsg(
"could not extend file \"%s\": wrote only %d of %d bytes at block %u",
493 nbytes, BLCKSZ, blocknum),
494 errhint(
"Check free disk space.")));
538 errmsg(
"could not open file \"%s\": %m", path)));
560 for (
int forknum = 0; forknum <=
MAX_FORKNUM; forknum++)
577 while (nopensegs > 0)
602 seekpos = (off_t) BLCKSZ * (blocknum % ((
BlockNumber) RELSEG_SIZE));
604 Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
648 segnum_start = blocknum / RELSEG_SIZE;
651 segnum_end = (blocknum + nblocks - 1) / RELSEG_SIZE;
652 if (segnum_start != segnum_end)
653 nflush = RELSEG_SIZE - (blocknum % ((
BlockNumber) RELSEG_SIZE));
656 Assert(nflush <= nblocks);
658 seekpos = (off_t) BLCKSZ * (blocknum % ((
BlockNumber) RELSEG_SIZE));
678 TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum,
687 seekpos = (off_t) BLCKSZ * (blocknum % ((
BlockNumber) RELSEG_SIZE));
689 Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
693 TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum,
701 if (nbytes != BLCKSZ)
706 errmsg(
"could not read block %u in file \"%s\": %m",
718 MemSet(buffer, 0, BLCKSZ);
722 errmsg(
"could not read block %u in file \"%s\": read only %d of %d bytes",
737 const void *buffer,
bool skipFsync)
744 #ifdef CHECK_WRITE_VS_EXTEND
748 TRACE_POSTGRESQL_SMGR_MD_WRITE_START(forknum, blocknum,
757 seekpos = (off_t) BLCKSZ * (blocknum % ((
BlockNumber) RELSEG_SIZE));
759 Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
763 TRACE_POSTGRESQL_SMGR_MD_WRITE_DONE(forknum, blocknum,
771 if (nbytes != BLCKSZ)
776 errmsg(
"could not write block %u in file \"%s\": %m",
781 errmsg(
"could not write block %u in file \"%s\": wrote only %d of %d bytes",
785 errhint(
"Check free disk space.")));
834 return (segno * ((
BlockNumber) RELSEG_SIZE)) + nblocks;
869 if (nblocks > curnblk)
875 (
errmsg(
"could not truncate file \"%s\" to %u blocks: it's only %u blocks now",
879 if (nblocks == curnblk)
887 while (curopensegs > 0)
891 priorblocks = (curopensegs - 1) * RELSEG_SIZE;
893 v = &reln->
md_seg_fds[forknum][curopensegs - 1];
895 if (priorblocks > nblocks)
904 errmsg(
"could not truncate file \"%s\": %m",
916 else if (priorblocks + ((
BlockNumber) RELSEG_SIZE) > nblocks)
930 errmsg(
"could not truncate file \"%s\" to %u blocks: %m",
963 int min_inactive_seg;
998 errmsg(
"could not fsync file \"%s\": %m",
1002 if (segno > min_inactive_seg)
1047 (
errmsg_internal(
"could not forward fsync request because request queue is full")));
1052 errmsg(
"could not fsync file \"%s\": %m",
1097 rlocator.
dbOid = dbid;
1116 for (
i = 0;
i < ndelrels;
i++)
1132 for (
i = 0;
i < ndelrels;
i++)
1189 fullpath =
psprintf(
"%s.%u", path, segno);
1249 bool skipFsync,
int behavior)
1263 if (targetseg < reln->md_num_open_segs[forknum])
1290 nextsegno <= targetseg; nextsegno++)
1319 char *zerobuf =
palloc0(BLCKSZ);
1323 zerobuf, skipFsync);
1351 errmsg(
"could not open file \"%s\" (target block %u): previous segment is only %u blocks",
1365 errmsg(
"could not open file \"%s\" (target block %u): %m",
1386 errmsg(
"could not seek to end of file \"%s\": %m",
1412 need_to_close =
false;
1425 need_to_close =
true;
1458 return unlink(path);
void TablespaceCreateDbspace(Oid spcOid, Oid dbOid, bool isRedo)
#define InvalidBlockNumber
#define MemSet(start, val, len)
elog(ERROR, "%s: %s", p2, msg)
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 FileSync(File file, uint32 wait_event_info)
void FileClose(File file)
int FilePrefetch(File file, off_t offset, off_t amount, uint32 wait_event_info)
int data_sync_elevel(int elevel)
File PathNameOpenFile(const char *fileName, int fileFlags)
int FileWrite(File file, const void *buffer, size_t amount, off_t offset, uint32 wait_event_info)
int FileRead(File file, void *buffer, size_t amount, off_t offset, uint32 wait_event_info)
char * FilePathName(File file)
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)
void mdunlink(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
static void register_forget_request(RelFileLocatorBackend rlocator, ForkNumber forknum, BlockNumber segno)
#define EXTENSION_CREATE_RECOVERY
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
static void mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
void mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
bool mdfiletagmatches(const FileTag *ftag, const FileTag *candidate)
bool mdexists(SMgrRelation reln, ForkNumber forknum)
static void register_unlink_segment(RelFileLocatorBackend rlocator, ForkNumber forknum, BlockNumber segno)
#define EXTENSION_DONT_OPEN
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
int mdunlinkfiletag(const FileTag *ftag, char *path)
static MemoryContext MdCxt
void mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
void mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
static int do_truncate(const char *path)
void mdclose(SMgrRelation reln, ForkNumber forknum)
static MdfdVec * _mdfd_openseg(SMgrRelation reln, ForkNumber forknum, BlockNumber segno, int oflags)
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)
void mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void *buffer)
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno, bool skipFsync, int behavior)
#define EXTENSION_RETURN_NULL
static char * _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
void mdopen(SMgrRelation reln)
bool mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
#define INIT_MD_FILETAG(a, xx_rlocator, xx_forknum, xx_segno)
#define EXTENSION_DONT_CHECK_SIZE
static MdfdVec * mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
void DropRelationFiles(RelFileLocator *delrels, int ndelrels, bool isRedo)
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)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define ERRCODE_DATA_CORRUPTED
void pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op)
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 RelFileLocatorBackendIsTemp(rlocator)
#define relpath(rlocator, forknum)
#define relpathperm(rlocator, forknum)
void smgrclose(SMgrRelation reln)
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
int md_num_open_segs[MAX_FORKNUM+1]
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
RelFileLocatorBackend smgr_rlocator
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(RelFileLocator rlocator, ForkNumber forknum)