PostgreSQL Source Code  git master
fd.c File Reference
#include "postgres.h"
#include <sys/file.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/pg_tablespace.h"
#include "common/file_perm.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "portability/mem.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "utils/guc.h"
#include "utils/resowner_private.h"
Include dependency graph for fd.c:

Go to the source code of this file.

Data Structures

struct  vfd
 
struct  AllocateDesc
 

Macros

#define NUM_RESERVED_FDS   10
 
#define FD_MINFREE   10
 
#define DO_DB(A)   ((void) 0)
 
#define VFD_CLOSED   (-1)
 
#define FileIsValid(file)   ((file) > 0 && (file) < (int) SizeVfdCache && VfdCache[file].fileName != NULL)
 
#define FileIsNotOpen(file)   (VfdCache[file].fd == VFD_CLOSED)
 
#define FD_DELETE_AT_CLOSE   (1 << 0) /* T = delete when closed */
 
#define FD_CLOSE_AT_EOXACT   (1 << 1) /* T = close at eoXact */
 
#define FD_TEMP_FILE_LIMIT   (1 << 2) /* T = respect temp_file_limit */
 

Typedefs

typedef struct vfd Vfd
 

Enumerations

enum  AllocateDescKind { AllocateDescFile, AllocateDescPipe, AllocateDescDir, AllocateDescRawFD }
 

Functions

static void Delete (File file)
 
static void LruDelete (File file)
 
static void Insert (File file)
 
static int LruInsert (File file)
 
static bool ReleaseLruFile (void)
 
static void ReleaseLruFiles (void)
 
static File AllocateVfd (void)
 
static void FreeVfd (File file)
 
static int FileAccess (File file)
 
static File OpenTemporaryFileInTablespace (Oid tblspcOid, bool rejectError)
 
static bool reserveAllocatedDesc (void)
 
static int FreeDesc (AllocateDesc *desc)
 
static void AtProcExit_Files (int code, Datum arg)
 
static void CleanupTempFiles (bool isCommit, bool isProcExit)
 
static void RemovePgTempRelationFiles (const char *tsdirname)
 
static void RemovePgTempRelationFilesInDbspace (const char *dbspacedirname)
 
static void walkdir (const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
 
static void datadir_fsync_fname (const char *fname, bool isdir, int elevel)
 
static void unlink_if_exists_fname (const char *fname, bool isdir, int elevel)
 
static int fsync_fname_ext (const char *fname, bool isdir, bool ignore_perm, int elevel)
 
static int fsync_parent_path (const char *fname, int elevel)
 
int pg_fsync (int fd)
 
int pg_fsync_no_writethrough (int fd)
 
int pg_fsync_writethrough (int fd)
 
int pg_fdatasync (int fd)
 
void pg_flush_data (int fd, off_t offset, off_t nbytes)
 
void fsync_fname (const char *fname, bool isdir)
 
int durable_rename (const char *oldfile, const char *newfile, int elevel)
 
int durable_unlink (const char *fname, int elevel)
 
int durable_link_or_rename (const char *oldfile, const char *newfile, int elevel)
 
void InitFileAccess (void)
 
static void count_usable_fds (int max_to_probe, int *usable_fds, int *already_open)
 
void set_max_safe_fds (void)
 
int BasicOpenFile (const char *fileName, int fileFlags)
 
int BasicOpenFilePerm (const char *fileName, int fileFlags, mode_t fileMode)
 
static void ReportTemporaryFileUsage (const char *path, off_t size)
 
static void RegisterTemporaryFile (File file)
 
File PathNameOpenFile (const char *fileName, int fileFlags)
 
File PathNameOpenFilePerm (const char *fileName, int fileFlags, mode_t fileMode)
 
void PathNameCreateTemporaryDir (const char *basedir, const char *directory)
 
void PathNameDeleteTemporaryDir (const char *dirname)
 
File OpenTemporaryFile (bool interXact)
 
void TempTablespacePath (char *path, Oid tablespace)
 
File PathNameCreateTemporaryFile (const char *path, bool error_on_failure)
 
File PathNameOpenTemporaryFile (const char *path)
 
bool PathNameDeleteTemporaryFile (const char *path, bool error_on_failure)
 
void FileClose (File file)
 
int FilePrefetch (File file, off_t offset, int amount, uint32 wait_event_info)
 
void FileWriteback (File file, off_t offset, off_t nbytes, uint32 wait_event_info)
 
int FileRead (File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
 
int FileWrite (File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
 
int FileSync (File file, uint32 wait_event_info)
 
off_t FileSize (File file)
 
int FileTruncate (File file, off_t offset, uint32 wait_event_info)
 
char * FilePathName (File file)
 
int FileGetRawDesc (File file)
 
int FileGetRawFlags (File file)
 
mode_t FileGetRawMode (File file)
 
FILE * AllocateFile (const char *name, const char *mode)
 
int OpenTransientFile (const char *fileName, int fileFlags)
 
int OpenTransientFilePerm (const char *fileName, int fileFlags, mode_t fileMode)
 
FILE * OpenPipeStream (const char *command, const char *mode)
 
int FreeFile (FILE *file)
 
int CloseTransientFile (int fd)
 
DIRAllocateDir (const char *dirname)
 
struct direntReadDir (DIR *dir, const char *dirname)
 
struct direntReadDirExtended (DIR *dir, const char *dirname, int elevel)
 
int FreeDir (DIR *dir)
 
int ClosePipeStream (FILE *file)
 
void closeAllVfds (void)
 
void SetTempTablespaces (Oid *tableSpaces, int numSpaces)
 
bool TempTablespacesAreSet (void)
 
int GetTempTablespaces (Oid *tableSpaces, int numSpaces)
 
Oid GetNextTempTableSpace (void)
 
void AtEOSubXact_Files (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
void AtEOXact_Files (bool isCommit)
 
void RemovePgTempFiles (void)
 
void RemovePgTempFilesInDir (const char *tmpdirname, bool missing_ok, bool unlink_all)
 
bool looks_like_temp_rel_name (const char *name)
 
void SyncDataDirectory (void)
 
int MakePGDirectory (const char *directoryName)
 
int data_sync_elevel (int elevel)
 

Variables

int max_files_per_process = 1000
 
int max_safe_fds = 32
 
bool data_sync_retry = false
 
static VfdVfdCache
 
static Size SizeVfdCache = 0
 
static int nfile = 0
 
static bool have_xact_temporary_files = false
 
static uint64 temporary_files_size = 0
 
static int numAllocatedDescs = 0
 
static int maxAllocatedDescs = 0
 
static AllocateDescallocatedDescs = NULL
 
static long tempFileCounter = 0
 
static OidtempTableSpaces = NULL
 
static int numTempTableSpaces = -1
 
static int nextTempTableSpace = 0
 

Macro Definition Documentation

◆ DO_DB

◆ FD_CLOSE_AT_EOXACT

#define FD_CLOSE_AT_EOXACT   (1 << 1) /* T = close at eoXact */

Definition at line 173 of file fd.c.

Referenced by CleanupTempFiles(), and RegisterTemporaryFile().

◆ FD_DELETE_AT_CLOSE

#define FD_DELETE_AT_CLOSE   (1 << 0) /* T = delete when closed */

Definition at line 172 of file fd.c.

Referenced by CleanupTempFiles(), FileClose(), and OpenTemporaryFile().

◆ FD_MINFREE

#define FD_MINFREE   10

Definition at line 124 of file fd.c.

Referenced by reserveAllocatedDesc(), and set_max_safe_fds().

◆ FD_TEMP_FILE_LIMIT

#define FD_TEMP_FILE_LIMIT   (1 << 2) /* T = respect temp_file_limit */

◆ FileIsNotOpen

#define FileIsNotOpen (   file)    (VfdCache[file].fd == VFD_CLOSED)

◆ FileIsValid

#define FileIsValid (   file)    ((file) > 0 && (file) < (int) SizeVfdCache && VfdCache[file].fileName != NULL)

◆ NUM_RESERVED_FDS

#define NUM_RESERVED_FDS   10

Definition at line 118 of file fd.c.

Referenced by set_max_safe_fds().

◆ VFD_CLOSED

#define VFD_CLOSED   (-1)

Definition at line 164 of file fd.c.

Referenced by AllocateVfd(), FileClose(), InitFileAccess(), and LruDelete().

Typedef Documentation

◆ Vfd

typedef struct vfd Vfd

Enumeration Type Documentation

◆ AllocateDescKind

Enumerator
AllocateDescFile 
AllocateDescPipe 
AllocateDescDir 
AllocateDescRawFD 

Definition at line 222 of file fd.c.

Function Documentation

◆ AllocateDir()

DIR* AllocateDir ( const char *  dirname)

Definition at line 2503 of file fd.c.

References AllocateDescDir, AllocateDesc::create_subid, AllocateDesc::desc, AllocateDesc::dir, DO_DB, elog, ereport, errcode(), errmsg(), ERROR, GetCurrentSubTransactionId(), AllocateDesc::kind, LOG, maxAllocatedDescs, numAllocatedDescs, opendir(), ReleaseLruFile(), ReleaseLruFiles(), and reserveAllocatedDesc().

Referenced by calculate_database_size(), calculate_tablespace_size(), CheckPointLogicalRewriteHeap(), CheckPointSnapBuild(), CleanupBackupHistory(), copydir(), db_dir_size(), DeleteAllExportedSnapshotFiles(), destroy_tablespace_directories(), directory_is_empty(), do_pg_start_backup(), dsm_cleanup_for_mmap(), get_ext_ver_list(), getInstallationPaths(), movedb(), ParseTzFile(), perform_base_backup(), pg_available_extension_versions(), pg_available_extensions(), pg_logdir_ls_internal(), pg_ls_dir(), pg_ls_dir_files(), pg_tablespace_databases(), pg_tzenumerate_next(), pg_tzenumerate_start(), pgarch_readyXlog(), pgstat_reset_remove_files(), RelationCacheInitFileRemove(), RelationCacheInitFileRemoveInDir(), RemoveNonParentXlogFiles(), RemoveOldXlogFiles(), RemovePgTempFiles(), RemovePgTempFilesInDir(), RemovePgTempRelationFiles(), RemovePgTempRelationFilesInDbspace(), RemoveTempXlogFiles(), ReorderBufferCleanupSerializedTXNs(), ResetUnloggedRelations(), ResetUnloggedRelationsInDbspaceDir(), ResetUnloggedRelationsInTablespaceDir(), restoreTwoPhaseData(), scan_directory_ci(), sendDir(), SlruScanDirectory(), StartupReorderBuffer(), StartupReplicationSlots(), UpdateLogicalMappings(), and walkdir().

2504 {
2505  DIR *dir;
2506 
2507  DO_DB(elog(LOG, "AllocateDir: Allocated %d (%s)",
2508  numAllocatedDescs, dirname));
2509 
2510  /* Can we allocate another non-virtual FD? */
2511  if (!reserveAllocatedDesc())
2512  ereport(ERROR,
2513  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2514  errmsg("exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"",
2515  maxAllocatedDescs, dirname)));
2516 
2517  /* Close excess kernel FDs. */
2518  ReleaseLruFiles();
2519 
2520 TryAgain:
2521  if ((dir = opendir(dirname)) != NULL)
2522  {
2524 
2525  desc->kind = AllocateDescDir;
2526  desc->desc.dir = dir;
2529  return desc->desc.dir;
2530  }
2531 
2532  if (errno == EMFILE || errno == ENFILE)
2533  {
2534  int save_errno = errno;
2535 
2536  ereport(LOG,
2537  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2538  errmsg("out of file descriptors: %m; release and retry")));
2539  errno = 0;
2540  if (ReleaseLruFile())
2541  goto TryAgain;
2542  errno = save_errno;
2543  }
2544 
2545  return NULL;
2546 }
static AllocateDesc * allocatedDescs
Definition: fd.c:244
union AllocateDesc::@26 desc
DIR * dir
Definition: fd.c:237
#define DO_DB(A)
Definition: fd.c:160
int errcode(int sqlerrcode)
Definition: elog.c:608
static bool reserveAllocatedDesc(void)
Definition: fd.c:2169
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:232
static bool ReleaseLruFile(void)
Definition: fd.c:1165
Definition: dirent.c:25
#define ERROR
Definition: elog.h:43
DIR * opendir(const char *)
Definition: dirent.c:33
#define ereport(elevel, rest)
Definition: elog.h:141
static void ReleaseLruFiles(void)
Definition: fd.c:1187
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:707
SubTransactionId create_subid
Definition: fd.c:233
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
static int maxAllocatedDescs
Definition: fd.c:243
static int numAllocatedDescs
Definition: fd.c:242

◆ AllocateFile()

FILE* AllocateFile ( const char *  name,
const char *  mode 
)

Definition at line 2242 of file fd.c.

References AllocateDescFile, AllocateDesc::create_subid, AllocateDesc::desc, DO_DB, elog, ereport, errcode(), errmsg(), ERROR, AllocateDesc::file, GetCurrentSubTransactionId(), AllocateDesc::kind, LOG, maxAllocatedDescs, numAllocatedDescs, ReleaseLruFile(), ReleaseLruFiles(), and reserveAllocatedDesc().

Referenced by _ShowOption(), AlterSystemSetConfigFile(), apw_dump_now(), apw_load_buffers(), BackendRun(), BeginCopyFrom(), BeginCopyTo(), checkControlFile(), do_pg_start_backup(), do_pg_stop_backup(), entry_reset(), existsTimeLineHistory(), ExportSnapshot(), fill_hba_view(), gc_qtexts(), ImportSnapshot(), load_dh_file(), load_hba(), load_ident(), load_relcache_init_file(), parse_extension_control_file(), ParseTzFile(), perform_base_backup(), pg_backup_start_time(), pg_current_logfile(), pg_file_write_internal(), pg_promote(), PGSharedMemoryAttach(), pgss_shmem_shutdown(), pgss_shmem_startup(), pgstat_read_db_statsfile(), pgstat_read_db_statsfile_timestamp(), pgstat_read_statsfiles(), pgstat_write_db_statsfile(), pgstat_write_statsfiles(), PostmasterMarkPIDForWorkerNotify(), read_backup_label(), read_binary_file(), read_tablespace_map(), read_whole_file(), readTimeLineHistory(), sendFile(), tokenize_inc_file(), tsearch_readline_begin(), ValidatePgVersion(), write_relcache_init_file(), XLogArchiveForceDone(), and XLogArchiveNotify().

2243 {
2244  FILE *file;
2245 
2246  DO_DB(elog(LOG, "AllocateFile: Allocated %d (%s)",
2248 
2249  /* Can we allocate another non-virtual FD? */
2250  if (!reserveAllocatedDesc())
2251  ereport(ERROR,
2252  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2253  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2254  maxAllocatedDescs, name)));
2255 
2256  /* Close excess kernel FDs. */
2257  ReleaseLruFiles();
2258 
2259 TryAgain:
2260  if ((file = fopen(name, mode)) != NULL)
2261  {
2263 
2264  desc->kind = AllocateDescFile;
2265  desc->desc.file = file;
2268  return desc->desc.file;
2269  }
2270 
2271  if (errno == EMFILE || errno == ENFILE)
2272  {
2273  int save_errno = errno;
2274 
2275  ereport(LOG,
2276  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2277  errmsg("out of file descriptors: %m; release and retry")));
2278  errno = 0;
2279  if (ReleaseLruFile())
2280  goto TryAgain;
2281  errno = save_errno;
2282  }
2283 
2284  return NULL;
2285 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
static AllocateDesc * allocatedDescs
Definition: fd.c:244
union AllocateDesc::@26 desc
#define DO_DB(A)
Definition: fd.c:160
int errcode(int sqlerrcode)
Definition: elog.c:608
static bool reserveAllocatedDesc(void)
Definition: fd.c:2169
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:232
static bool ReleaseLruFile(void)
Definition: fd.c:1165
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
static void ReleaseLruFiles(void)
Definition: fd.c:1187
FILE * file
Definition: fd.c:236
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:707
SubTransactionId create_subid
Definition: fd.c:233
const char * name
Definition: encode.c:521
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
static int maxAllocatedDescs
Definition: fd.c:243
static int numAllocatedDescs
Definition: fd.c:242

◆ AllocateVfd()

static File AllocateVfd ( void  )
static

Definition at line 1197 of file fd.c.

References Assert, DO_DB, elog, ereport, errcode(), errmsg(), ERROR, vfd::fd, i, LOG, MemSet, vfd::nextFree, realloc, SizeVfdCache, and VFD_CLOSED.

Referenced by PathNameOpenFilePerm().

1198 {
1199  Index i;
1200  File file;
1201 
1202  DO_DB(elog(LOG, "AllocateVfd. Size %zu", SizeVfdCache));
1203 
1204  Assert(SizeVfdCache > 0); /* InitFileAccess not called? */
1205 
1206  if (VfdCache[0].nextFree == 0)
1207  {
1208  /*
1209  * The free list is empty so it is time to increase the size of the
1210  * array. We choose to double it each time this happens. However,
1211  * there's not much point in starting *real* small.
1212  */
1213  Size newCacheSize = SizeVfdCache * 2;
1214  Vfd *newVfdCache;
1215 
1216  if (newCacheSize < 32)
1217  newCacheSize = 32;
1218 
1219  /*
1220  * Be careful not to clobber VfdCache ptr if realloc fails.
1221  */
1222  newVfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
1223  if (newVfdCache == NULL)
1224  ereport(ERROR,
1225  (errcode(ERRCODE_OUT_OF_MEMORY),
1226  errmsg("out of memory")));
1227  VfdCache = newVfdCache;
1228 
1229  /*
1230  * Initialize the new entries and link them into the free list.
1231  */
1232  for (i = SizeVfdCache; i < newCacheSize; i++)
1233  {
1234  MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
1235  VfdCache[i].nextFree = i + 1;
1236  VfdCache[i].fd = VFD_CLOSED;
1237  }
1238  VfdCache[newCacheSize - 1].nextFree = 0;
1240 
1241  /*
1242  * Record the new size
1243  */
1244  SizeVfdCache = newCacheSize;
1245  }
1246 
1247  file = VfdCache[0].nextFree;
1248 
1249  VfdCache[0].nextFree = VfdCache[file].nextFree;
1250 
1251  return file;
1252 }
File nextFree
Definition: fd.c:181
static Size SizeVfdCache
Definition: fd.c:197
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
int errcode(int sqlerrcode)
Definition: elog.c:608
#define MemSet(start, val, len)
Definition: c.h:962
#define LOG
Definition: elog.h:26
#define ERROR
Definition: elog.h:43
Definition: fd.c:176
int fd
Definition: fd.c:178
#define ereport(elevel, rest)
Definition: elog.h:141
unsigned int Index
Definition: c.h:476
#define VFD_CLOSED
Definition: fd.c:164
#define Assert(condition)
Definition: c.h:739
size_t Size
Definition: c.h:467
#define realloc(a, b)
Definition: header.h:60
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
int i
int File
Definition: fd.h:45

◆ AtEOSubXact_Files()

void AtEOSubXact_Files ( bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)

Definition at line 2785 of file fd.c.

References AllocateDesc::create_subid, FreeDesc(), i, and numAllocatedDescs.

Referenced by AbortSubTransaction(), and CommitSubTransaction().

2787 {
2788  Index i;
2789 
2790  for (i = 0; i < numAllocatedDescs; i++)
2791  {
2792  if (allocatedDescs[i].create_subid == mySubid)
2793  {
2794  if (isCommit)
2795  allocatedDescs[i].create_subid = parentSubid;
2796  else
2797  {
2798  /* have to recheck the item after FreeDesc (ugly) */
2799  FreeDesc(&allocatedDescs[i--]);
2800  }
2801  }
2802  }
2803 }
static AllocateDesc * allocatedDescs
Definition: fd.c:244
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2402
unsigned int Index
Definition: c.h:476
SubTransactionId create_subid
Definition: fd.c:233
int i
static int numAllocatedDescs
Definition: fd.c:242

◆ AtEOXact_Files()

void AtEOXact_Files ( bool  isCommit)

Definition at line 2818 of file fd.c.

References CleanupTempFiles(), numTempTableSpaces, and tempTableSpaces.

Referenced by AbortTransaction(), AutoVacLauncherMain(), BackgroundWriterMain(), CheckpointerMain(), CommitTransaction(), PrepareTransaction(), and WalWriterMain().

2819 {
2820  CleanupTempFiles(isCommit, false);
2821  tempTableSpaces = NULL;
2822  numTempTableSpaces = -1;
2823 }
static int numTempTableSpaces
Definition: fd.c:257
static Oid * tempTableSpaces
Definition: fd.c:256
static void CleanupTempFiles(bool isCommit, bool isProcExit)
Definition: fd.c:2850

◆ AtProcExit_Files()

static void AtProcExit_Files ( int  code,
Datum  arg 
)
static

Definition at line 2832 of file fd.c.

References CleanupTempFiles().

Referenced by InitFileAccess().

2833 {
2834  CleanupTempFiles(false, true);
2835 }
static void CleanupTempFiles(bool isCommit, bool isProcExit)
Definition: fd.c:2850

◆ BasicOpenFile()

int BasicOpenFile ( const char *  fileName,
int  fileFlags 
)

Definition at line 981 of file fd.c.

References BasicOpenFilePerm(), and pg_file_create_mode.

Referenced by AlterSystemSetConfigFile(), ReadControlFile(), update_controlfile(), wal_segment_open(), WalSndSegmentOpen(), WriteControlFile(), XLogFileInit(), XLogFileOpen(), and XLogFileRead().

982 {
983  return BasicOpenFilePerm(fileName, fileFlags, pg_file_create_mode);
984 }
int pg_file_create_mode
Definition: file_perm.c:19
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1003

◆ BasicOpenFilePerm()

int BasicOpenFilePerm ( const char *  fileName,
int  fileFlags,
mode_t  fileMode 
)

Definition at line 1003 of file fd.c.

References buf, elog, ereport, errcode(), errmsg(), vfd::fd, LOG, vfd::lruLessRecently, ReleaseLruFile(), and snprintf.

Referenced by BasicOpenFile(), LruInsert(), OpenTransientFilePerm(), PathNameOpenFilePerm(), and readRecoverySignalFile().

1004 {
1005  int fd;
1006 
1007 tryAgain:
1008  fd = open(fileName, fileFlags, fileMode);
1009 
1010  if (fd >= 0)
1011  return fd; /* success! */
1012 
1013  if (errno == EMFILE || errno == ENFILE)
1014  {
1015  int save_errno = errno;
1016 
1017  ereport(LOG,
1018  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
1019  errmsg("out of file descriptors: %m; release and retry")));
1020  errno = 0;
1021  if (ReleaseLruFile())
1022  goto tryAgain;
1023  errno = save_errno;
1024  }
1025 
1026  return -1; /* failure */
1027 }
int errcode(int sqlerrcode)
Definition: elog.c:608
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static bool ReleaseLruFile(void)
Definition: fd.c:1165
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ CleanupTempFiles()

static void CleanupTempFiles ( bool  isCommit,
bool  isProcExit 
)
static

Definition at line 2850 of file fd.c.

References Assert, elog, FD_CLOSE_AT_EOXACT, FD_DELETE_AT_CLOSE, vfd::fdstate, FileClose(), FileIsNotOpen, vfd::fileName, FreeDesc(), have_xact_temporary_files, i, numAllocatedDescs, SizeVfdCache, and WARNING.

Referenced by AtEOXact_Files(), and AtProcExit_Files().

2851 {
2852  Index i;
2853 
2854  /*
2855  * Careful here: at proc_exit we need extra cleanup, not just
2856  * xact_temporary files.
2857  */
2858  if (isProcExit || have_xact_temporary_files)
2859  {
2860  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
2861  for (i = 1; i < SizeVfdCache; i++)
2862  {
2863  unsigned short fdstate = VfdCache[i].fdstate;
2864 
2865  if (((fdstate & FD_DELETE_AT_CLOSE) || (fdstate & FD_CLOSE_AT_EOXACT)) &&
2866  VfdCache[i].fileName != NULL)
2867  {
2868  /*
2869  * If we're in the process of exiting a backend process, close
2870  * all temporary files. Otherwise, only close temporary files
2871  * local to the current transaction. They should be closed by
2872  * the ResourceOwner mechanism already, so this is just a
2873  * debugging cross-check.
2874  */
2875  if (isProcExit)
2876  FileClose(i);
2877  else if (fdstate & FD_CLOSE_AT_EOXACT)
2878  {
2879  elog(WARNING,
2880  "temporary file %s not closed at end-of-transaction",
2881  VfdCache[i].fileName);
2882  FileClose(i);
2883  }
2884  }
2885  }
2886 
2887  have_xact_temporary_files = false;
2888  }
2889 
2890  /* Complain if any allocated files remain open at commit. */
2891  if (isCommit && numAllocatedDescs > 0)
2892  elog(WARNING, "%d temporary files and directories not closed at end-of-transaction",
2894 
2895  /* Clean up "allocated" stdio files, dirs and fds. */
2896  while (numAllocatedDescs > 0)
2897  FreeDesc(&allocatedDescs[0]);
2898 }
static AllocateDesc * allocatedDescs
Definition: fd.c:244
static Size SizeVfdCache
Definition: fd.c:197
#define FD_DELETE_AT_CLOSE
Definition: fd.c:172
static Vfd * VfdCache
Definition: fd.c:196
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2402
static bool have_xact_temporary_files
Definition: fd.c:208
unsigned short fdstate
Definition: fd.c:179
#define WARNING
Definition: elog.h:40
#define FileIsNotOpen(file)
Definition: fd.c:169
unsigned int Index
Definition: c.h:476
void FileClose(File file)
Definition: fd.c:1748
#define Assert(condition)
Definition: c.h:739
#define elog(elevel,...)
Definition: elog.h:228
int i
#define FD_CLOSE_AT_EOXACT
Definition: fd.c:173
static int numAllocatedDescs
Definition: fd.c:242

◆ closeAllVfds()

void closeAllVfds ( void  )

Definition at line 2680 of file fd.c.

References Assert, FileIsNotOpen, i, LruDelete(), and SizeVfdCache.

Referenced by standard_ProcessUtility().

2681 {
2682  Index i;
2683 
2684  if (SizeVfdCache > 0)
2685  {
2686  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
2687  for (i = 1; i < SizeVfdCache; i++)
2688  {
2689  if (!FileIsNotOpen(i))
2690  LruDelete(i);
2691  }
2692  }
2693 }
static Size SizeVfdCache
Definition: fd.c:197
static void LruDelete(File file)
Definition: fd.c:1070
#define FileIsNotOpen(file)
Definition: fd.c:169
unsigned int Index
Definition: c.h:476
#define Assert(condition)
Definition: c.h:739
int i

◆ ClosePipeStream()

int ClosePipeStream ( FILE *  file)

Definition at line 2651 of file fd.c.

References AllocateDescPipe, AllocateDesc::desc, DO_DB, elog, AllocateDesc::file, FreeDesc(), i, AllocateDesc::kind, LOG, numAllocatedDescs, and WARNING.

Referenced by ClosePipeToProgram(), pg_import_system_collations(), and run_ssl_passphrase_command().

2652 {
2653  int i;
2654 
2655  DO_DB(elog(LOG, "ClosePipeStream: Allocated %d", numAllocatedDescs));
2656 
2657  /* Remove file from list of allocated files, if it's present */
2658  for (i = numAllocatedDescs; --i >= 0;)
2659  {
2660  AllocateDesc *desc = &allocatedDescs[i];
2661 
2662  if (desc->kind == AllocateDescPipe && desc->desc.file == file)
2663  return FreeDesc(desc);
2664  }
2665 
2666  /* Only get here if someone passes us a file not in allocatedDescs */
2667  elog(WARNING, "file passed to ClosePipeStream was not obtained from OpenPipeStream");
2668 
2669  return pclose(file);
2670 }
static AllocateDesc * allocatedDescs
Definition: fd.c:244
union AllocateDesc::@26 desc
#define DO_DB(A)
Definition: fd.c:160
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:232
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2402
#define WARNING
Definition: elog.h:40
FILE * file
Definition: fd.c:236
#define elog(elevel,...)
Definition: elog.h:228
int i
static int numAllocatedDescs
Definition: fd.c:242

◆ CloseTransientFile()

int CloseTransientFile ( int  fd)

Definition at line 2469 of file fd.c.

References AllocateDescRawFD, close, AllocateDesc::desc, DO_DB, elog, AllocateDesc::fd, FreeDesc(), i, AllocateDesc::kind, LOG, numAllocatedDescs, and WARNING.

Referenced by ApplyLogicalMappingFile(), be_lo_export(), CheckPointLogicalRewriteHeap(), CheckPointReplicationOrigin(), copy_file(), dsm_impl_mmap(), durable_rename(), fsync_fname_ext(), get_controlfile(), heap_xlog_logical_rewrite(), lo_import_internal(), load_relmap_file(), mdunlinkfork(), qtext_load_file(), qtext_store(), ReadTwoPhaseFile(), RecreateTwoPhaseFile(), ReorderBufferIterTXNFinish(), ReorderBufferRestoreChanges(), ReorderBufferSerializeChange(), ReorderBufferSerializeTXN(), RestoreSlotFromDisk(), SaveSlotToPath(), SendTimeLineHistory(), SimpleLruDoesPhysicalPageExist(), SimpleLruFlush(), SlruInternalWritePage(), SlruPhysicalReadPage(), SlruPhysicalWritePage(), SnapBuildRestore(), SnapBuildSerialize(), StartupReplicationOrigin(), walkdir(), write_relmap_file(), writeTimeLineHistory(), writeTimeLineHistoryFile(), and XLogFileCopy().

2470 {
2471  int i;
2472 
2473  DO_DB(elog(LOG, "CloseTransientFile: Allocated %d", numAllocatedDescs));
2474 
2475  /* Remove fd from list of allocated files, if it's present */
2476  for (i = numAllocatedDescs; --i >= 0;)
2477  {
2478  AllocateDesc *desc = &allocatedDescs[i];
2479 
2480  if (desc->kind == AllocateDescRawFD && desc->desc.fd == fd)
2481  return FreeDesc(desc);
2482  }
2483 
2484  /* Only get here if someone passes us a file not in allocatedDescs */
2485  elog(WARNING, "fd passed to CloseTransientFile was not obtained from OpenTransientFile");
2486 
2487  return close(fd);
2488 }
static AllocateDesc * allocatedDescs
Definition: fd.c:244
union AllocateDesc::@26 desc
#define DO_DB(A)
Definition: fd.c:160
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:232
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2402
#define WARNING
Definition: elog.h:40
int fd
Definition: fd.c:238
#define elog(elevel,...)
Definition: elog.h:228
int i
#define close(a)
Definition: win32.h:12
static int numAllocatedDescs
Definition: fd.c:242

◆ count_usable_fds()

static void count_usable_fds ( int  max_to_probe,
int *  usable_fds,
int *  already_open 
)
static

Definition at line 854 of file fd.c.

References close, elog, ereport, errmsg(), vfd::fd, palloc(), pfree(), repalloc(), and WARNING.

Referenced by set_max_safe_fds().

855 {
856  int *fd;
857  int size;
858  int used = 0;
859  int highestfd = 0;
860  int j;
861 
862 #ifdef HAVE_GETRLIMIT
863  struct rlimit rlim;
864  int getrlimit_status;
865 #endif
866 
867  size = 1024;
868  fd = (int *) palloc(size * sizeof(int));
869 
870 #ifdef HAVE_GETRLIMIT
871 #ifdef RLIMIT_NOFILE /* most platforms use RLIMIT_NOFILE */
872  getrlimit_status = getrlimit(RLIMIT_NOFILE, &rlim);
873 #else /* but BSD doesn't ... */
874  getrlimit_status = getrlimit(RLIMIT_OFILE, &rlim);
875 #endif /* RLIMIT_NOFILE */
876  if (getrlimit_status != 0)
877  ereport(WARNING, (errmsg("getrlimit failed: %m")));
878 #endif /* HAVE_GETRLIMIT */
879 
880  /* dup until failure or probe limit reached */
881  for (;;)
882  {
883  int thisfd;
884 
885 #ifdef HAVE_GETRLIMIT
886 
887  /*
888  * don't go beyond RLIMIT_NOFILE; causes irritating kernel logs on
889  * some platforms
890  */
891  if (getrlimit_status == 0 && highestfd >= rlim.rlim_cur - 1)
892  break;
893 #endif
894 
895  thisfd = dup(0);
896  if (thisfd < 0)
897  {
898  /* Expect EMFILE or ENFILE, else it's fishy */
899  if (errno != EMFILE && errno != ENFILE)
900  elog(WARNING, "dup(0) failed after %d successes: %m", used);
901  break;
902  }
903 
904  if (used >= size)
905  {
906  size *= 2;
907  fd = (int *) repalloc(fd, size * sizeof(int));
908  }
909  fd[used++] = thisfd;
910 
911  if (highestfd < thisfd)
912  highestfd = thisfd;
913 
914  if (used >= max_to_probe)
915  break;
916  }
917 
918  /* release the files we opened */
919  for (j = 0; j < used; j++)
920  close(fd[j]);
921 
922  pfree(fd);
923 
924  /*
925  * Return results. usable_fds is just the number of successful dups. We
926  * assume that the system limit is highestfd+1 (remember 0 is a legal FD
927  * number) and so already_open is highestfd+1 - usable_fds.
928  */
929  *usable_fds = used;
930  *already_open = highestfd + 1 - used;
931 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ereport(elevel, rest)
Definition: elog.h:141
#define WARNING
Definition: elog.h:40
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
#define close(a)
Definition: win32.h:12

◆ data_sync_elevel()

◆ datadir_fsync_fname()

static void datadir_fsync_fname ( const char *  fname,
bool  isdir,
int  elevel 
)
static

Definition at line 3345 of file fd.c.

References fsync_fname_ext().

Referenced by SyncDataDirectory().

3346 {
3347  /*
3348  * We want to silently ignoring errors about unreadable files. Pass that
3349  * desire on to fsync_fname_ext().
3350  */
3351  fsync_fname_ext(fname, isdir, true, elevel);
3352 }
static int elevel
Definition: vacuumlazy.c:143
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3380

◆ Delete()

static void Delete ( File  file)
static

Definition at line 1051 of file fd.c.

References Assert, DO_DB, elog, vfd::fileName, LOG, vfd::lruLessRecently, and vfd::lruMoreRecently.

Referenced by FileAccess(), FileClose(), and LruDelete().

1052 {
1053  Vfd *vfdP;
1054 
1055  Assert(file != 0);
1056 
1057  DO_DB(elog(LOG, "Delete %d (%s)",
1058  file, VfdCache[file].fileName));
1059  DO_DB(_dump_lru());
1060 
1061  vfdP = &VfdCache[file];
1062 
1065 
1066  DO_DB(_dump_lru());
1067 }
File lruLessRecently
Definition: fd.c:183
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
Definition: fd.c:176
#define Assert(condition)
Definition: c.h:739
File lruMoreRecently
Definition: fd.c:182
#define elog(elevel,...)
Definition: elog.h:228

◆ durable_link_or_rename()

int durable_link_or_rename ( const char *  oldfile,
const char *  newfile,
int  elevel 
)

Definition at line 769 of file fd.c.

References ereport, errcode_for_file_access(), errmsg(), fsync_fname_ext(), fsync_parent_path(), and link().

Referenced by InstallXLogFileSegment(), writeTimeLineHistory(), and writeTimeLineHistoryFile().

770 {
771  /*
772  * Ensure that, if we crash directly after the rename/link, a file with
773  * valid contents is moved into place.
774  */
775  if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
776  return -1;
777 
778 #ifdef HAVE_WORKING_LINK
779  if (link(oldfile, newfile) < 0)
780  {
781  ereport(elevel,
783  errmsg("could not link file \"%s\" to \"%s\": %m",
784  oldfile, newfile)));
785  return -1;
786  }
787  unlink(oldfile);
788 #else
789  /* XXX: Add racy file existence check? */
790  if (rename(oldfile, newfile) < 0)
791  {
792  ereport(elevel,
794  errmsg("could not rename file \"%s\" to \"%s\": %m",
795  oldfile, newfile)));
796  return -1;
797  }
798 #endif
799 
800  /*
801  * Make change persistent in case of an OS crash, both the new entry and
802  * its parent directory need to be flushed.
803  */
804  if (fsync_fname_ext(newfile, false, false, elevel) != 0)
805  return -1;
806 
807  /* Same for parent directory */
808  if (fsync_parent_path(newfile, elevel) != 0)
809  return -1;
810 
811  return 0;
812 }
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
int link(const char *fromname, const char *toname)
static int elevel
Definition: vacuumlazy.c:143
int errmsg(const char *fmt,...)
Definition: elog.c:822
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3380
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3456

◆ durable_rename()

int durable_rename ( const char *  oldfile,
const char *  newfile,
int  elevel 
)

Definition at line 643 of file fd.c.

References CloseTransientFile(), ereport, errcode_for_file_access(), errmsg(), vfd::fd, fsync_fname_ext(), fsync_parent_path(), OpenTransientFile(), PG_BINARY, and pg_fsync().

Referenced by AlterSystemSetConfigFile(), apw_dump_now(), CancelBackup(), CheckPointReplicationOrigin(), dir_close(), KeepFileRestoredFromArchive(), pgarch_archiveDone(), pgss_shmem_shutdown(), StartupXLOG(), and XLogArchiveForceDone().

644 {
645  int fd;
646 
647  /*
648  * First fsync the old and target path (if it exists), to ensure that they
649  * are properly persistent on disk. Syncing the target file is not
650  * strictly necessary, but it makes it easier to reason about crashes;
651  * because it's then guaranteed that either source or target file exists
652  * after a crash.
653  */
654  if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
655  return -1;
656 
657  fd = OpenTransientFile(newfile, PG_BINARY | O_RDWR);
658  if (fd < 0)
659  {
660  if (errno != ENOENT)
661  {
662  ereport(elevel,
664  errmsg("could not open file \"%s\": %m", newfile)));
665  return -1;
666  }
667  }
668  else
669  {
670  if (pg_fsync(fd) != 0)
671  {
672  int save_errno;
673 
674  /* close file upon error, might not be in transaction context */
675  save_errno = errno;
676  CloseTransientFile(fd);
677  errno = save_errno;
678 
679  ereport(elevel,
681  errmsg("could not fsync file \"%s\": %m", newfile)));
682  return -1;
683  }
684 
685  if (CloseTransientFile(fd) != 0)
686  {
687  ereport(elevel,
689  errmsg("could not close file \"%s\": %m", newfile)));
690  return -1;
691  }
692  }
693 
694  /* Time to do the real deal... */
695  if (rename(oldfile, newfile) < 0)
696  {
697  ereport(elevel,
699  errmsg("could not rename file \"%s\" to \"%s\": %m",
700  oldfile, newfile)));
701  return -1;
702  }
703 
704  /*
705  * To guarantee renaming the file is persistent, fsync the file with its
706  * new name, and its containing directory.
707  */
708  if (fsync_fname_ext(newfile, false, false, elevel) != 0)
709  return -1;
710 
711  if (fsync_parent_path(newfile, elevel) != 0)
712  return -1;
713 
714  return 0;
715 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1222
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2292
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
int CloseTransientFile(int fd)
Definition: fd.c:2469
static int elevel
Definition: vacuumlazy.c:143
int errmsg(const char *fmt,...)
Definition: elog.c:822
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3380
int pg_fsync(int fd)
Definition: fd.c:330
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3456

◆ durable_unlink()

int durable_unlink ( const char *  fname,
int  elevel 
)

Definition at line 733 of file fd.c.

References ereport, errcode_for_file_access(), errmsg(), and fsync_parent_path().

Referenced by do_pg_stop_backup(), exitArchiveRecovery(), InstallXLogFileSegment(), and RemoveXlogFile().

734 {
735  if (unlink(fname) < 0)
736  {
737  ereport(elevel,
739  errmsg("could not remove file \"%s\": %m",
740  fname)));
741  return -1;
742  }
743 
744  /*
745  * To guarantee that the removal of the file is persistent, fsync its
746  * parent directory.
747  */
748  if (fsync_parent_path(fname, elevel) != 0)
749  return -1;
750 
751  return 0;
752 }
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
static int elevel
Definition: vacuumlazy.c:143
int errmsg(const char *fmt,...)
Definition: elog.c:822
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3456

◆ FileAccess()

static int FileAccess ( File  file)
static

Definition at line 1275 of file fd.c.

References Delete(), DO_DB, elog, FileIsNotOpen, vfd::fileName, Insert(), LOG, LruInsert(), and vfd::lruLessRecently.

Referenced by FilePrefetch(), FileRead(), FileSize(), FileSync(), FileTruncate(), FileWrite(), and FileWriteback().

1276 {
1277  int returnValue;
1278 
1279  DO_DB(elog(LOG, "FileAccess %d (%s)",
1280  file, VfdCache[file].fileName));
1281 
1282  /*
1283  * Is the file open? If not, open it and put it at the head of the LRU
1284  * ring (possibly closing the least recently used file to get an FD).
1285  */
1286 
1287  if (FileIsNotOpen(file))
1288  {
1289  returnValue = LruInsert(file);
1290  if (returnValue != 0)
1291  return returnValue;
1292  }
1293  else if (VfdCache[0].lruLessRecently != file)
1294  {
1295  /*
1296  * We now know that the file is open and that it is not the last one
1297  * accessed, so we need to move it to the head of the Lru ring.
1298  */
1299 
1300  Delete(file);
1301  Insert(file);
1302  }
1303 
1304  return 0;
1305 }
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
static void Delete(File file)
Definition: fd.c:1051
#define LOG
Definition: elog.h:26
static int LruInsert(File file)
Definition: fd.c:1118
static void Insert(File file)
Definition: fd.c:1096
#define FileIsNotOpen(file)
Definition: fd.c:169
#define elog(elevel,...)
Definition: elog.h:228

◆ FileClose()

void FileClose ( File  file)

Definition at line 1748 of file fd.c.

References Assert, close, data_sync_elevel(), Delete(), DO_DB, elog, vfd::fd, FD_DELETE_AT_CLOSE, FD_TEMP_FILE_LIMIT, vfd::fdstate, FileIsNotOpen, FileIsValid, vfd::fileName, vfd::fileSize, FreeVfd(), LOG, nfile, ReportTemporaryFileUsage(), ResourceOwnerForgetFile(), vfd::resowner, stat, temporary_files_size, and VFD_CLOSED.

Referenced by BufFileClose(), CleanupTempFiles(), logical_end_heap_rewrite(), mdclose(), mdsyncfiletag(), mdtruncate(), and ResourceOwnerReleaseInternal().

1749 {
1750  Vfd *vfdP;
1751 
1752  Assert(FileIsValid(file));
1753 
1754  DO_DB(elog(LOG, "FileClose: %d (%s)",
1755  file, VfdCache[file].fileName));
1756 
1757  vfdP = &VfdCache[file];
1758 
1759  if (!FileIsNotOpen(file))
1760  {
1761  /* close the file */
1762  if (close(vfdP->fd) != 0)
1763  {
1764  /*
1765  * We may need to panic on failure to close non-temporary files;
1766  * see LruDelete.
1767  */
1769  "could not close file \"%s\": %m", vfdP->fileName);
1770  }
1771 
1772  --nfile;
1773  vfdP->fd = VFD_CLOSED;
1774 
1775  /* remove the file from the lru ring */
1776  Delete(file);
1777  }
1778 
1779  if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
1780  {
1781  /* Subtract its size from current usage (do first in case of error) */
1782  temporary_files_size -= vfdP->fileSize;
1783  vfdP->fileSize = 0;
1784  }
1785 
1786  /*
1787  * Delete the file if it was temporary, and make a log entry if wanted
1788  */
1789  if (vfdP->fdstate & FD_DELETE_AT_CLOSE)
1790  {
1791  struct stat filestats;
1792  int stat_errno;
1793 
1794  /*
1795  * If we get an error, as could happen within the ereport/elog calls,
1796  * we'll come right back here during transaction abort. Reset the
1797  * flag to ensure that we can't get into an infinite loop. This code
1798  * is arranged to ensure that the worst-case consequence is failing to
1799  * emit log message(s), not failing to attempt the unlink.
1800  */
1801  vfdP->fdstate &= ~FD_DELETE_AT_CLOSE;
1802 
1803 
1804  /* first try the stat() */
1805  if (stat(vfdP->fileName, &filestats))
1806  stat_errno = errno;
1807  else
1808  stat_errno = 0;
1809 
1810  /* in any case do the unlink */
1811  if (unlink(vfdP->fileName))
1812  elog(LOG, "could not unlink file \"%s\": %m", vfdP->fileName);
1813 
1814  /* and last report the stat results */
1815  if (stat_errno == 0)
1816  ReportTemporaryFileUsage(vfdP->fileName, filestats.st_size);
1817  else
1818  {
1819  errno = stat_errno;
1820  elog(LOG, "could not stat file \"%s\": %m", vfdP->fileName);
1821  }
1822  }
1823 
1824  /* Unregister it from the resource owner */
1825  if (vfdP->resowner)
1826  ResourceOwnerForgetFile(vfdP->resowner, file);
1827 
1828  /*
1829  * Return the Vfd slot to the free list
1830  */
1831  FreeVfd(file);
1832 }
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:174
#define DO_DB(A)
Definition: fd.c:160
#define FD_DELETE_AT_CLOSE
Definition: fd.c:172
static Vfd * VfdCache
Definition: fd.c:196
static void Delete(File file)
Definition: fd.c:1051
#define LOG
Definition: elog.h:26
char * fileName
Definition: fd.c:185
static int nfile
Definition: fd.c:202
unsigned short fdstate
Definition: fd.c:179
Definition: fd.c:176
off_t fileSize
Definition: fd.c:184
int fd
Definition: fd.c:178
ResourceOwner resowner
Definition: fd.c:180
static void ReportTemporaryFileUsage(const char *path, off_t size)
Definition: fd.c:1311
#define stat(a, b)
Definition: win32_port.h:255
#define FileIsNotOpen(file)
Definition: fd.c:169
int data_sync_elevel(int elevel)
Definition: fd.c:3519
#define FileIsValid(file)
Definition: fd.c:166
#define VFD_CLOSED
Definition: fd.c:164
static uint64 temporary_files_size
Definition: fd.c:216
#define Assert(condition)
Definition: c.h:739
#define elog(elevel,...)
Definition: elog.h:228
static void FreeVfd(File file)
Definition: fd.c:1255
#define close(a)
Definition: win32.h:12
void ResourceOwnerForgetFile(ResourceOwner owner, File file)
Definition: resowner.c:1253

◆ FileGetRawDesc()

int FileGetRawDesc ( File  file)

Definition at line 2138 of file fd.c.

References Assert, vfd::fd, and FileIsValid.

2139 {
2140  Assert(FileIsValid(file));
2141  return VfdCache[file].fd;
2142 }
static Vfd * VfdCache
Definition: fd.c:196
int fd
Definition: fd.c:178
#define FileIsValid(file)
Definition: fd.c:166
#define Assert(condition)
Definition: c.h:739

◆ FileGetRawFlags()

int FileGetRawFlags ( File  file)

Definition at line 2148 of file fd.c.

References Assert, vfd::fileFlags, and FileIsValid.

2149 {
2150  Assert(FileIsValid(file));
2151  return VfdCache[file].fileFlags;
2152 }
static Vfd * VfdCache
Definition: fd.c:196
#define FileIsValid(file)
Definition: fd.c:166
#define Assert(condition)
Definition: c.h:739
int fileFlags
Definition: fd.c:187

◆ FileGetRawMode()

mode_t FileGetRawMode ( File  file)

Definition at line 2158 of file fd.c.

References Assert, FileIsValid, and vfd::fileMode.

2159 {
2160  Assert(FileIsValid(file));
2161  return VfdCache[file].fileMode;
2162 }
static Vfd * VfdCache
Definition: fd.c:196
mode_t fileMode
Definition: fd.c:188
#define FileIsValid(file)
Definition: fd.c:166
#define Assert(condition)
Definition: c.h:739

◆ FilePathName()

char* FilePathName ( File  file)

Definition at line 2122 of file fd.c.

References Assert, FileIsValid, and vfd::fileName.

Referenced by _mdnblocks(), BufFileSize(), mdextend(), mdimmedsync(), mdread(), mdsyncfiletag(), mdtruncate(), mdwrite(), and register_dirty_segment().

2123 {
2124  Assert(FileIsValid(file));
2125 
2126  return VfdCache[file].fileName;
2127 }
static Vfd * VfdCache
Definition: fd.c:196
char * fileName
Definition: fd.c:185
#define FileIsValid(file)
Definition: fd.c:166
#define Assert(condition)
Definition: c.h:739

◆ FilePrefetch()

int FilePrefetch ( File  file,
off_t  offset,
int  amount,
uint32  wait_event_info 
)

Definition at line 1844 of file fd.c.

References Assert, DO_DB, elog, vfd::fd, FileAccess(), FileIsValid, vfd::fileName, INT64_FORMAT, LOG, pgstat_report_wait_end(), and pgstat_report_wait_start().

Referenced by mdprefetch().

1845 {
1846 #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
1847  int returnCode;
1848 
1849  Assert(FileIsValid(file));
1850 
1851  DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " %d",
1852  file, VfdCache[file].fileName,
1853  (int64) offset, amount));
1854 
1855  returnCode = FileAccess(file);
1856  if (returnCode < 0)
1857  return returnCode;
1858 
1859  pgstat_report_wait_start(wait_event_info);
1860  returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
1861  POSIX_FADV_WILLNEED);
1863 
1864  return returnCode;
1865 #else
1866  Assert(FileIsValid(file));
1867  return 0;
1868 #endif
1869 }
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1342
#define FileIsValid(file)
Definition: fd.c:166
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:739
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1318
#define INT64_FORMAT
Definition: c.h:401
#define elog(elevel,...)
Definition: elog.h:228

◆ FileRead()

int FileRead ( File  file,
char *  buffer,
int  amount,
off_t  offset,
uint32  wait_event_info 
)

Definition at line 1895 of file fd.c.

References _dosmaperr(), Assert, DO_DB, EINTR, elog, error(), vfd::fd, FileAccess(), FileIsValid, vfd::fileName, INT64_FORMAT, LOG, pg_pread(), pg_usleep(), pgstat_report_wait_end(), and pgstat_report_wait_start().

Referenced by BufFileLoadBuffer(), and mdread().

1897 {
1898  int returnCode;
1899  Vfd *vfdP;
1900 
1901  Assert(FileIsValid(file));
1902 
1903  DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p",
1904  file, VfdCache[file].fileName,
1905  (int64) offset,
1906  amount, buffer));
1907 
1908  returnCode = FileAccess(file);
1909  if (returnCode < 0)
1910  return returnCode;
1911 
1912  vfdP = &VfdCache[file];
1913 
1914 retry:
1915  pgstat_report_wait_start(wait_event_info);
1916  returnCode = pg_pread(vfdP->fd, buffer, amount, offset);
1918 
1919  if (returnCode < 0)
1920  {
1921  /*
1922  * Windows may run out of kernel buffers and return "Insufficient
1923  * system resources" error. Wait a bit and retry to solve it.
1924  *
1925  * It is rumored that EINTR is also possible on some Unix filesystems,
1926  * in which case immediate retry is indicated.
1927  */
1928 #ifdef WIN32
1929  DWORD error = GetLastError();
1930 
1931  switch (error)
1932  {
1933  case ERROR_NO_SYSTEM_RESOURCES:
1934  pg_usleep(1000L);
1935  errno = EINTR;
1936  break;
1937  default:
1938  _dosmaperr(error);
1939  break;
1940  }
1941 #endif
1942  /* OK to retry if interrupted */
1943  if (errno == EINTR)
1944  goto retry;
1945  }
1946 
1947  return returnCode;
1948 }
static void error(void)
Definition: sql-dyntest.c:147
#define DO_DB(A)
Definition: fd.c:160
void _dosmaperr(unsigned long)
Definition: win32error.c:171
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
ssize_t pg_pread(int fd, void *buf, size_t nbyte, off_t offset)
Definition: pread.c:27
void pg_usleep(long microsec)
Definition: signal.c:53
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1342
Definition: fd.c:176
int fd
Definition: fd.c:178
#define FileIsValid(file)
Definition: fd.c:166
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:739
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1318
#define INT64_FORMAT
Definition: c.h:401
#define elog(elevel,...)
Definition: elog.h:228
#define EINTR
Definition: win32_port.h:323

◆ FileSize()

off_t FileSize ( File  file)

Definition at line 2070 of file fd.c.

References Assert, DO_DB, elog, vfd::fd, FileAccess(), FileIsNotOpen, FileIsValid, vfd::fileName, and LOG.

Referenced by _mdnblocks(), and BufFileSize().

2071 {
2072  Assert(FileIsValid(file));
2073 
2074  DO_DB(elog(LOG, "FileSize %d (%s)",
2075  file, VfdCache[file].fileName));
2076 
2077  if (FileIsNotOpen(file))
2078  {
2079  if (FileAccess(file) < 0)
2080  return (off_t) -1;
2081  }
2082 
2083  return lseek(VfdCache[file].fd, 0, SEEK_END);
2084 }
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define FileIsNotOpen(file)
Definition: fd.c:169
#define FileIsValid(file)
Definition: fd.c:166
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:739
#define elog(elevel,...)
Definition: elog.h:228

◆ FileSync()

int FileSync ( File  file,
uint32  wait_event_info 
)

Definition at line 2049 of file fd.c.

References Assert, DO_DB, elog, vfd::fd, FileAccess(), FileIsValid, vfd::fileName, LOG, pg_fsync(), pgstat_report_wait_end(), and pgstat_report_wait_start().

Referenced by logical_end_heap_rewrite(), mdimmedsync(), mdsyncfiletag(), and register_dirty_segment().

2050 {
2051  int returnCode;
2052 
2053  Assert(FileIsValid(file));
2054 
2055  DO_DB(elog(LOG, "FileSync: %d (%s)",
2056  file, VfdCache[file].fileName));
2057 
2058  returnCode = FileAccess(file);
2059  if (returnCode < 0)
2060  return returnCode;
2061 
2062  pgstat_report_wait_start(wait_event_info);
2063  returnCode = pg_fsync(VfdCache[file].fd);
2065 
2066  return returnCode;
2067 }
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1342
#define FileIsValid(file)
Definition: fd.c:166
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:739
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1318
#define elog(elevel,...)
Definition: elog.h:228
int pg_fsync(int fd)
Definition: fd.c:330

◆ FileTruncate()

int FileTruncate ( File  file,
off_t  offset,
uint32  wait_event_info 
)

Definition at line 2087 of file fd.c.

References Assert, DO_DB, elog, vfd::fd, FD_TEMP_FILE_LIMIT, vfd::fdstate, FileAccess(), FileIsValid, vfd::fileName, vfd::fileSize, ftruncate, LOG, pgstat_report_wait_end(), pgstat_report_wait_start(), and temporary_files_size.

Referenced by mdtruncate().

2088 {
2089  int returnCode;
2090 
2091  Assert(FileIsValid(file));
2092 
2093  DO_DB(elog(LOG, "FileTruncate %d (%s)",
2094  file, VfdCache[file].fileName));
2095 
2096  returnCode = FileAccess(file);
2097  if (returnCode < 0)
2098  return returnCode;
2099 
2100  pgstat_report_wait_start(wait_event_info);
2101  returnCode = ftruncate(VfdCache[file].fd, offset);
2103 
2104  if (returnCode == 0 && VfdCache[file].fileSize > offset)
2105  {
2106  /* adjust our state for truncation of a temp file */
2107  Assert(VfdCache[file].fdstate & FD_TEMP_FILE_LIMIT);
2108  temporary_files_size -= VfdCache[file].fileSize - offset;
2109  VfdCache[file].fileSize = offset;
2110  }
2111 
2112  return returnCode;
2113 }
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:174
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1342
off_t fileSize
Definition: fd.c:184
#define FileIsValid(file)
Definition: fd.c:166
static uint64 temporary_files_size
Definition: fd.c:216
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:739
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1318
#define elog(elevel,...)
Definition: elog.h:228
#define ftruncate(a, b)
Definition: win32_port.h:60

◆ FileWrite()

int FileWrite ( File  file,
char *  buffer,
int  amount,
off_t  offset,
uint32  wait_event_info 
)

Definition at line 1951 of file fd.c.

References _dosmaperr(), Assert, DO_DB, EINTR, elog, ereport, errcode(), errmsg(), ERROR, error(), vfd::fd, FD_TEMP_FILE_LIMIT, vfd::fdstate, FileAccess(), FileIsValid, vfd::fileName, vfd::fileSize, INT64_FORMAT, LOG, pg_pwrite(), pg_usleep(), pgstat_report_wait_end(), pgstat_report_wait_start(), temp_file_limit, and temporary_files_size.

Referenced by BufFileDumpBuffer(), logical_heap_rewrite_flush_mappings(), mdextend(), and mdwrite().

1953 {
1954  int returnCode;
1955  Vfd *vfdP;
1956 
1957  Assert(FileIsValid(file));
1958 
1959  DO_DB(elog(LOG, "FileWrite: %d (%s) " INT64_FORMAT " %d %p",
1960  file, VfdCache[file].fileName,
1961  (int64) offset,
1962  amount, buffer));
1963 
1964  returnCode = FileAccess(file);
1965  if (returnCode < 0)
1966  return returnCode;
1967 
1968  vfdP = &VfdCache[file];
1969 
1970  /*
1971  * If enforcing temp_file_limit and it's a temp file, check to see if the
1972  * write would overrun temp_file_limit, and throw error if so. Note: it's
1973  * really a modularity violation to throw error here; we should set errno
1974  * and return -1. However, there's no way to report a suitable error
1975  * message if we do that. All current callers would just throw error
1976  * immediately anyway, so this is safe at present.
1977  */
1978  if (temp_file_limit >= 0 && (vfdP->fdstate & FD_TEMP_FILE_LIMIT))
1979  {
1980  off_t past_write = offset + amount;
1981 
1982  if (past_write > vfdP->fileSize)
1983  {
1984  uint64 newTotal = temporary_files_size;
1985 
1986  newTotal += past_write - vfdP->fileSize;
1987  if (newTotal > (uint64) temp_file_limit * (uint64) 1024)
1988  ereport(ERROR,
1989  (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
1990  errmsg("temporary file size exceeds temp_file_limit (%dkB)",
1991  temp_file_limit)));
1992  }
1993  }
1994 
1995 retry:
1996  errno = 0;
1997  pgstat_report_wait_start(wait_event_info);
1998  returnCode = pg_pwrite(VfdCache[file].fd, buffer, amount, offset);
2000 
2001  /* if write didn't set errno, assume problem is no disk space */
2002  if (returnCode != amount && errno == 0)
2003  errno = ENOSPC;
2004 
2005  if (returnCode >= 0)
2006  {
2007  /*
2008  * Maintain fileSize and temporary_files_size if it's a temp file.
2009  */
2010  if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
2011  {
2012  off_t past_write = offset + amount;
2013 
2014  if (past_write > vfdP->fileSize)
2015  {
2016  temporary_files_size += past_write - vfdP->fileSize;
2017  vfdP->fileSize = past_write;
2018  }
2019  }
2020  }
2021  else
2022  {
2023  /*
2024  * See comments in FileRead()
2025  */
2026 #ifdef WIN32
2027  DWORD error = GetLastError();
2028 
2029  switch (error)
2030  {
2031  case ERROR_NO_SYSTEM_RESOURCES:
2032  pg_usleep(1000L);
2033  errno = EINTR;
2034  break;
2035  default:
2036  _dosmaperr(error);
2037  break;
2038  }
2039 #endif
2040  /* OK to retry if interrupted */
2041  if (errno == EINTR)
2042  goto retry;
2043  }
2044 
2045  return returnCode;
2046 }
static void error(void)
Definition: sql-dyntest.c:147
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:174
#define DO_DB(A)
Definition: fd.c:160
void _dosmaperr(unsigned long)
Definition: win32error.c:171
static Vfd * VfdCache
Definition: fd.c:196
int errcode(int sqlerrcode)
Definition: elog.c:608
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset)
Definition: pwrite.c:27
void pg_usleep(long microsec)
Definition: signal.c:53
#define ERROR
Definition: elog.h:43
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1342
unsigned short fdstate
Definition: fd.c:179
Definition: fd.c:176
off_t fileSize
Definition: fd.c:184
#define ereport(elevel, rest)
Definition: elog.h:141
#define FileIsValid(file)
Definition: fd.c:166
static uint64 temporary_files_size
Definition: fd.c:216
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:739
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1318
#define INT64_FORMAT
Definition: c.h:401
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
#define EINTR
Definition: win32_port.h:323
int temp_file_limit
Definition: guc.c:525

◆ FileWriteback()

void FileWriteback ( File  file,
off_t  offset,
off_t  nbytes,
uint32  wait_event_info 
)

Definition at line 1872 of file fd.c.

References Assert, DO_DB, elog, vfd::fd, FileAccess(), FileIsValid, vfd::fileName, INT64_FORMAT, LOG, pg_flush_data(), pgstat_report_wait_end(), and pgstat_report_wait_start().

Referenced by mdwriteback().

1873 {
1874  int returnCode;
1875 
1876  Assert(FileIsValid(file));
1877 
1878  DO_DB(elog(LOG, "FileWriteback: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
1879  file, VfdCache[file].fileName,
1880  (int64) offset, (int64) nbytes));
1881 
1882  if (nbytes <= 0)
1883  return;
1884 
1885  returnCode = FileAccess(file);
1886  if (returnCode < 0)
1887  return;
1888 
1889  pgstat_report_wait_start(wait_event_info);
1890  pg_flush_data(VfdCache[file].fd, offset, nbytes);
1892 }
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1342
void pg_flush_data(int fd, off_t offset, off_t nbytes)
Definition: fd.c:440
#define FileIsValid(file)
Definition: fd.c:166
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:739
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1318
#define INT64_FORMAT
Definition: c.h:401
#define elog(elevel,...)
Definition: elog.h:228

◆ FreeDesc()

static int FreeDesc ( AllocateDesc desc)
static

Definition at line 2402 of file fd.c.

References AllocateDescDir, AllocateDescFile, AllocateDescPipe, AllocateDescRawFD, close, closedir(), AllocateDesc::desc, AllocateDesc::dir, elog, ERROR, AllocateDesc::fd, AllocateDesc::file, AllocateDesc::kind, and numAllocatedDescs.

Referenced by AtEOSubXact_Files(), CleanupTempFiles(), ClosePipeStream(), CloseTransientFile(), FreeDir(), and FreeFile().

2403 {
2404  int result;
2405 
2406  /* Close the underlying object */
2407  switch (desc->kind)
2408  {
2409  case AllocateDescFile:
2410  result = fclose(desc->desc.file);
2411  break;
2412  case AllocateDescPipe:
2413  result = pclose(desc->desc.file);
2414  break;
2415  case AllocateDescDir:
2416  result = closedir(desc->desc.dir);
2417  break;
2418  case AllocateDescRawFD:
2419  result = close(desc->desc.fd);
2420  break;
2421  default:
2422  elog(ERROR, "AllocateDesc kind not recognized");
2423  result = 0; /* keep compiler quiet */
2424  break;
2425  }
2426 
2427  /* Compact storage in the allocatedDescs array */
2430 
2431  return result;
2432 }
static AllocateDesc * allocatedDescs
Definition: fd.c:244
union AllocateDesc::@26 desc
DIR * dir
Definition: fd.c:237
int closedir(DIR *)
Definition: dirent.c:113
AllocateDescKind kind
Definition: fd.c:232
#define ERROR
Definition: elog.h:43
FILE * file
Definition: fd.c:236
int fd
Definition: fd.c:238
#define elog(elevel,...)
Definition: elog.h:228
#define close(a)
Definition: win32.h:12
static int numAllocatedDescs
Definition: fd.c:242

◆ FreeDir()

int FreeDir ( DIR dir)

Definition at line 2621 of file fd.c.

References AllocateDescDir, closedir(), AllocateDesc::desc, AllocateDesc::dir, DO_DB, elog, FreeDesc(), i, AllocateDesc::kind, LOG, numAllocatedDescs, and WARNING.

Referenced by calculate_database_size(), calculate_tablespace_size(), CheckPointLogicalRewriteHeap(), CheckPointSnapBuild(), CleanupBackupHistory(), copydir(), db_dir_size(), DeleteAllExportedSnapshotFiles(), destroy_tablespace_directories(), directory_is_empty(), do_pg_start_backup(), dsm_cleanup_for_mmap(), get_ext_ver_list(), getInstallationPaths(), movedb(), ParseTzFile(), perform_base_backup(), pg_available_extension_versions(), pg_available_extensions(), pg_logdir_ls_internal(), pg_ls_dir(), pg_ls_dir_files(), pg_tablespace_databases(), pg_tzenumerate_end(), pg_tzenumerate_next(), pgarch_readyXlog(), pgstat_reset_remove_files(), RelationCacheInitFileRemove(), RelationCacheInitFileRemoveInDir(), RemoveNonParentXlogFiles(), RemoveOldXlogFiles(), RemovePgTempFiles(), RemovePgTempFilesInDir(), RemovePgTempRelationFiles(), RemovePgTempRelationFilesInDbspace(), RemoveTempXlogFiles(), ReorderBufferCleanupSerializedTXNs(), ResetUnloggedRelations(), ResetUnloggedRelationsInDbspaceDir(), ResetUnloggedRelationsInTablespaceDir(), restoreTwoPhaseData(), scan_directory_ci(), sendDir(), SlruScanDirectory(), StartupReorderBuffer(), StartupReplicationSlots(), UpdateLogicalMappings(), and walkdir().

2622 {
2623  int i;
2624 
2625  /* Nothing to do if AllocateDir failed */
2626  if (dir == NULL)
2627  return 0;
2628 
2629  DO_DB(elog(LOG, "FreeDir: Allocated %d", numAllocatedDescs));
2630 
2631  /* Remove dir from list of allocated dirs, if it's present */
2632  for (i = numAllocatedDescs; --i >= 0;)
2633  {
2634  AllocateDesc *desc = &allocatedDescs[i];
2635 
2636  if (desc->kind == AllocateDescDir && desc->desc.dir == dir)
2637  return FreeDesc(desc);
2638  }
2639 
2640  /* Only get here if someone passes us a dir not in allocatedDescs */
2641  elog(WARNING, "dir passed to FreeDir was not obtained from AllocateDir");
2642 
2643  return closedir(dir);
2644 }
static AllocateDesc * allocatedDescs
Definition: fd.c:244
union AllocateDesc::@26 desc
DIR * dir
Definition: fd.c:237
#define DO_DB(A)
Definition: fd.c:160
int closedir(DIR *)
Definition: dirent.c:113
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:232
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2402
#define WARNING
Definition: elog.h:40
#define elog(elevel,...)
Definition: elog.h:228
int i
static int numAllocatedDescs
Definition: fd.c:242

◆ FreeFile()

int FreeFile ( FILE *  file)

Definition at line 2441 of file fd.c.

References AllocateDescFile, AllocateDesc::desc, DO_DB, elog, AllocateDesc::file, FreeDesc(), i, AllocateDesc::kind, LOG, numAllocatedDescs, and WARNING.

Referenced by _ShowOption(), AlterSystemSetConfigFile(), apw_dump_now(), apw_load_buffers(), BackendRun(), checkControlFile(), do_pg_start_backup(), do_pg_stop_backup(), EndCopy(), entry_reset(), existsTimeLineHistory(), ExportSnapshot(), fill_hba_view(), gc_qtexts(), ImportSnapshot(), load_dh_file(), load_hba(), load_ident(), load_relcache_init_file(), parse_extension_control_file(), ParseTzFile(), perform_base_backup(), pg_backup_start_time(), pg_current_logfile(), pg_file_write_internal(), pg_promote(), PGSharedMemoryAttach(), pgss_shmem_shutdown(), pgss_shmem_startup(), pgstat_read_db_statsfile(), pgstat_read_db_statsfile_timestamp(), pgstat_read_statsfiles(), pgstat_write_db_statsfile(), pgstat_write_statsfiles(), PostmasterMarkPIDForWorkerNotify(), read_backup_label(), read_binary_file(), read_tablespace_map(), read_whole_file(), readTimeLineHistory(), sendFile(), tokenize_inc_file(), tsearch_readline_end(), ValidatePgVersion(), write_relcache_init_file(), XLogArchiveForceDone(), and XLogArchiveNotify().

2442 {
2443  int i;
2444 
2445  DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedDescs));
2446 
2447  /* Remove file from list of allocated files, if it's present */
2448  for (i = numAllocatedDescs; --i >= 0;)
2449  {
2450  AllocateDesc *desc = &allocatedDescs[i];
2451 
2452  if (desc->kind == AllocateDescFile && desc->desc.file == file)
2453  return FreeDesc(desc);
2454  }
2455 
2456  /* Only get here if someone passes us a file not in allocatedDescs */
2457  elog(WARNING, "file passed to FreeFile was not obtained from AllocateFile");
2458 
2459  return fclose(file);
2460 }
static AllocateDesc * allocatedDescs
Definition: fd.c:244
union AllocateDesc::@26 desc
#define DO_DB(A)
Definition: fd.c:160
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:232
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2402
#define WARNING
Definition: elog.h:40
FILE * file
Definition: fd.c:236
#define elog(elevel,...)
Definition: elog.h:228
int i
static int numAllocatedDescs
Definition: fd.c:242

◆ FreeVfd()

static void FreeVfd ( File  file)
static

Definition at line 1255 of file fd.c.

References DO_DB, elog, vfd::fdstate, vfd::fileName, free, LOG, and vfd::nextFree.

Referenced by FileClose(), and PathNameOpenFilePerm().

1256 {
1257  Vfd *vfdP = &VfdCache[file];
1258 
1259  DO_DB(elog(LOG, "FreeVfd: %d (%s)",
1260  file, vfdP->fileName ? vfdP->fileName : ""));
1261 
1262  if (vfdP->fileName != NULL)
1263  {
1264  free(vfdP->fileName);
1265  vfdP->fileName = NULL;
1266  }
1267  vfdP->fdstate = 0x0;
1268 
1269  vfdP->nextFree = VfdCache[0].nextFree;
1270  VfdCache[0].nextFree = file;
1271 }
File nextFree
Definition: fd.c:181
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
char * fileName
Definition: fd.c:185
unsigned short fdstate
Definition: fd.c:179
Definition: fd.c:176
#define free(a)
Definition: header.h:65
#define elog(elevel,...)
Definition: elog.h:228

◆ fsync_fname()

void fsync_fname ( const char *  fname,
bool  isdir 
)

Definition at line 617 of file fd.c.

Referenced by _CloseArchive(), CheckPointCLOG(), CheckPointCommitTs(), CheckPointTwoPhase(), copydir(), CreateSlotOnDisk(), dir_close(), dir_finish(), dir_open_for_write(), main(), ReplicationSlotDropPtr(), ResetUnloggedRelationsInDbspaceDir(), RestoreSlotFromDisk(), SaveSlotToPath(), ShutdownCLOG(), ShutdownCommitTs(), SnapBuildRestore(), SnapBuildSerialize(), StartupReplicationSlots(), and tar_finish().

618 {
619  fsync_fname_ext(fname, isdir, false, data_sync_elevel(ERROR));
620 }
#define ERROR
Definition: elog.h:43
int data_sync_elevel(int elevel)
Definition: fd.c:3519
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3380

◆ fsync_fname_ext()

static int fsync_fname_ext ( const char *  fname,
bool  isdir,
bool  ignore_perm,
int  elevel 
)
static

Definition at line 3380 of file fd.c.

References CloseTransientFile(), ereport, errcode_for_file_access(), errmsg(), vfd::fd, OpenTransientFile(), PG_BINARY, and pg_fsync().

Referenced by datadir_fsync_fname(), durable_link_or_rename(), durable_rename(), fsync_fname(), and fsync_parent_path().

3381 {
3382  int fd;
3383  int flags;
3384  int returncode;
3385 
3386  /*
3387  * Some OSs require directories to be opened read-only whereas other
3388  * systems don't allow us to fsync files opened read-only; so we need both
3389  * cases here. Using O_RDWR will cause us to fail to fsync files that are
3390  * not writable by our userid, but we assume that's OK.
3391  */
3392  flags = PG_BINARY;
3393  if (!isdir)
3394  flags |= O_RDWR;
3395  else
3396  flags |= O_RDONLY;
3397 
3398  fd = OpenTransientFile(fname, flags);
3399 
3400  /*
3401  * Some OSs don't allow us to open directories at all (Windows returns
3402  * EACCES), just ignore the error in that case. If desired also silently
3403  * ignoring errors about unreadable files. Log others.
3404  */
3405  if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
3406  return 0;
3407  else if (fd < 0 && ignore_perm && errno == EACCES)
3408  return 0;
3409  else if (fd < 0)
3410  {
3411  ereport(elevel,
3413  errmsg("could not open file \"%s\": %m", fname)));
3414  return -1;
3415  }
3416 
3417  returncode = pg_fsync(fd);
3418 
3419  /*
3420  * Some OSes don't allow us to fsync directories at all, so we can ignore
3421  * those errors. Anything else needs to be logged.
3422  */
3423  if (returncode != 0 && !(isdir && (errno == EBADF || errno == EINVAL)))
3424  {
3425  int save_errno;
3426 
3427  /* close file upon error, might not be in transaction context */
3428  save_errno = errno;
3429  (void) CloseTransientFile(fd);
3430  errno = save_errno;
3431 
3432  ereport(elevel,
3434  errmsg("could not fsync file \"%s\": %m", fname)));
3435  return -1;
3436  }
3437 
3438  if (CloseTransientFile(fd) != 0)
3439  {
3440  ereport(elevel,
3442  errmsg("could not close file \"%s\": %m", fname)));
3443  return -1;
3444  }
3445 
3446  return 0;
3447 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1222
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2292
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
int CloseTransientFile(int fd)
Definition: fd.c:2469
static int elevel
Definition: vacuumlazy.c:143
int errmsg(const char *fmt,...)
Definition: elog.c:822
int pg_fsync(int fd)
Definition: fd.c:330

◆ fsync_parent_path()

static int fsync_parent_path ( const char *  fname,
int  elevel 
)
static

Definition at line 3456 of file fd.c.

References fsync_fname_ext(), get_parent_directory(), MAXPGPATH, and strlcpy().

Referenced by dir_close(), dir_open_for_write(), durable_link_or_rename(), durable_rename(), durable_unlink(), and tar_finish().

3457 {
3458  char parentpath[MAXPGPATH];
3459 
3460  strlcpy(parentpath, fname, MAXPGPATH);
3461  get_parent_directory(parentpath);
3462 
3463  /*
3464  * get_parent_directory() returns an empty string if the input argument is
3465  * just a file name (see comments in path.c), so handle that as being the
3466  * current directory.
3467  */
3468  if (strlen(parentpath) == 0)
3469  strlcpy(parentpath, ".", MAXPGPATH);
3470 
3471  if (fsync_fname_ext(parentpath, true, false, elevel) != 0)
3472  return -1;
3473 
3474  return 0;
3475 }
#define MAXPGPATH
void get_parent_directory(char *path)
Definition: path.c:854
static int elevel
Definition: vacuumlazy.c:143
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3380

◆ GetNextTempTableSpace()

Oid GetNextTempTableSpace ( void  )

Definition at line 2764 of file fd.c.

References InvalidOid, nextTempTableSpace, numTempTableSpaces, and tempTableSpaces.

Referenced by GetDefaultTablespace(), and OpenTemporaryFile().

2765 {
2766  if (numTempTableSpaces > 0)
2767  {
2768  /* Advance nextTempTableSpace counter with wraparound */
2770  nextTempTableSpace = 0;
2772  }
2773  return InvalidOid;
2774 }
static int numTempTableSpaces
Definition: fd.c:257
static int nextTempTableSpace
Definition: fd.c:258
#define InvalidOid
Definition: postgres_ext.h:36
static Oid * tempTableSpaces
Definition: fd.c:256

◆ GetTempTablespaces()

int GetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2746 of file fd.c.

References Assert, i, numTempTableSpaces, tempTableSpaces, and TempTablespacesAreSet().

Referenced by SharedFileSetInit().

2747 {
2748  int i;
2749 
2751  for (i = 0; i < numTempTableSpaces && i < numSpaces; ++i)
2752  tableSpaces[i] = tempTableSpaces[i];
2753 
2754  return i;
2755 }
static int numTempTableSpaces
Definition: fd.c:257
bool TempTablespacesAreSet(void)
Definition: fd.c:2734
#define Assert(condition)
Definition: c.h:739
static Oid * tempTableSpaces
Definition: fd.c:256
int i

◆ InitFileAccess()

void InitFileAccess ( void  )

Definition at line 821 of file fd.c.

References Assert, AtProcExit_Files(), ereport, errcode(), errmsg(), FATAL, vfd::fd, malloc, MemSet, on_proc_exit(), SizeVfdCache, and VFD_CLOSED.

Referenced by BaseInit().

822 {
823  Assert(SizeVfdCache == 0); /* call me only once */
824 
825  /* initialize cache header entry */
826  VfdCache = (Vfd *) malloc(sizeof(Vfd));
827  if (VfdCache == NULL)
828  ereport(FATAL,
829  (errcode(ERRCODE_OUT_OF_MEMORY),
830  errmsg("out of memory")));
831 
832  MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
834 
835  SizeVfdCache = 1;
836 
837  /* register proc-exit hook to ensure temp files are dropped at exit */
839 }
static void AtProcExit_Files(int code, Datum arg)
Definition: fd.c:2832
static Size SizeVfdCache
Definition: fd.c:197
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:305
static Vfd * VfdCache
Definition: fd.c:196
int errcode(int sqlerrcode)
Definition: elog.c:608
#define MemSet(start, val, len)
Definition: c.h:962
#define malloc(a)
Definition: header.h:50
#define FATAL
Definition: elog.h:52
Definition: fd.c:176
int fd
Definition: fd.c:178
#define ereport(elevel, rest)
Definition: elog.h:141
#define VFD_CLOSED
Definition: fd.c:164
#define Assert(condition)
Definition: c.h:739
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ Insert()

static void Insert ( File  file)
static

Definition at line 1096 of file fd.c.

References Assert, DO_DB, elog, vfd::fileName, LOG, vfd::lruLessRecently, and vfd::lruMoreRecently.

Referenced by AdvanceXLInsertBuffer(), CreateCheckPoint(), FileAccess(), GetXLogInsertRecPtr(), InitXLOGAccess(), LruInsert(), PathNameOpenFilePerm(), ReserveXLogInsertLocation(), ReserveXLogSwitch(), StartupXLOG(), UpdateFullPageWrites(), WaitXLogInsertionsToFinish(), and XLogInsertRecord().

1097 {
1098  Vfd *vfdP;
1099 
1100  Assert(file != 0);
1101 
1102  DO_DB(elog(LOG, "Insert %d (%s)",
1103  file, VfdCache[file].fileName));
1104  DO_DB(_dump_lru());
1105 
1106  vfdP = &VfdCache[file];
1107 
1108  vfdP->lruMoreRecently = 0;
1110  VfdCache[0].lruLessRecently = file;
1112 
1113  DO_DB(_dump_lru());
1114 }
File lruLessRecently
Definition: fd.c:183
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
Definition: fd.c:176
#define Assert(condition)
Definition: c.h:739
File lruMoreRecently
Definition: fd.c:182
#define elog(elevel,...)
Definition: elog.h:228

◆ looks_like_temp_rel_name()

bool looks_like_temp_rel_name ( const char *  name)

Definition at line 3101 of file fd.c.

References forkname_chars().

Referenced by RemovePgTempRelationFilesInDbspace(), and sendDir().

3102 {
3103  int pos;
3104  int savepos;
3105 
3106  /* Must start with "t". */
3107  if (name[0] != 't')
3108  return false;
3109 
3110  /* Followed by a non-empty string of digits and then an underscore. */
3111  for (pos = 1; isdigit((unsigned char) name[pos]); ++pos)
3112  ;
3113  if (pos == 1 || name[pos] != '_')
3114  return false;
3115 
3116  /* Followed by another nonempty string of digits. */
3117  for (savepos = ++pos; isdigit((unsigned char) name[pos]); ++pos)
3118  ;
3119  if (savepos == pos)
3120  return false;
3121 
3122  /* We might have _forkname or .segment or both. */
3123  if (name[pos] == '_')
3124  {
3125  int forkchar = forkname_chars(&name[pos + 1], NULL);
3126 
3127  if (forkchar <= 0)
3128  return false;
3129  pos += forkchar + 1;
3130  }
3131  if (name[pos] == '.')
3132  {
3133  int segchar;
3134 
3135  for (segchar = 1; isdigit((unsigned char) name[pos + segchar]); ++segchar)
3136  ;
3137  if (segchar <= 1)
3138  return false;
3139  pos += segchar;
3140  }
3141 
3142  /* Now we should be at the end. */
3143  if (name[pos] != '\0')
3144  return false;
3145  return true;
3146 }
int forkname_chars(const char *str, ForkNumber *fork)
Definition: relpath.c:78
const char * name
Definition: encode.c:521

◆ LruDelete()

static void LruDelete ( File  file)
static

Definition at line 1070 of file fd.c.

References Assert, close, data_sync_elevel(), Delete(), DO_DB, elog, vfd::fd, FD_TEMP_FILE_LIMIT, vfd::fdstate, vfd::fileName, LOG, nfile, and VFD_CLOSED.

Referenced by closeAllVfds(), RegisterTemporaryFile(), and ReleaseLruFile().

1071 {
1072  Vfd *vfdP;
1073 
1074  Assert(file != 0);
1075 
1076  DO_DB(elog(LOG, "LruDelete %d (%s)",
1077  file, VfdCache[file].fileName));
1078 
1079  vfdP = &VfdCache[file];
1080 
1081  /*
1082  * Close the file. We aren't expecting this to fail; if it does, better
1083  * to leak the FD than to mess up our internal state.
1084  */
1085  if (close(vfdP->fd) != 0)
1087  "could not close file \"%s\": %m", vfdP->fileName);
1088  vfdP->fd = VFD_CLOSED;
1089  --nfile;
1090 
1091  /* delete the vfd record from the LRU ring */
1092  Delete(file);
1093 }
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:174
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
static void Delete(File file)
Definition: fd.c:1051
#define LOG
Definition: elog.h:26
char * fileName
Definition: fd.c:185
static int nfile
Definition: fd.c:202
unsigned short fdstate
Definition: fd.c:179
Definition: fd.c:176
int fd
Definition: fd.c:178
int data_sync_elevel(int elevel)
Definition: fd.c:3519
#define VFD_CLOSED
Definition: fd.c:164
#define Assert(condition)
Definition: c.h:739
#define elog(elevel,...)
Definition: elog.h:228
#define close(a)
Definition: win32.h:12

◆ LruInsert()

static int LruInsert ( File  file)
static

Definition at line 1118 of file fd.c.

References Assert, BasicOpenFilePerm(), DO_DB, elog, vfd::fd, vfd::fileFlags, FileIsNotOpen, vfd::fileMode, vfd::fileName, Insert(), LOG, nfile, and ReleaseLruFiles().

Referenced by FileAccess().

1119 {
1120  Vfd *vfdP;
1121 
1122  Assert(file != 0);
1123 
1124  DO_DB(elog(LOG, "LruInsert %d (%s)",
1125  file, VfdCache[file].fileName));
1126 
1127  vfdP = &VfdCache[file];
1128 
1129  if (FileIsNotOpen(file))
1130  {
1131  /* Close excess kernel FDs. */
1132  ReleaseLruFiles();
1133 
1134  /*
1135  * The open could still fail for lack of file descriptors, eg due to
1136  * overall system file table being full. So, be prepared to release
1137  * another FD if necessary...
1138  */
1139  vfdP->fd = BasicOpenFilePerm(vfdP->fileName, vfdP->fileFlags,
1140  vfdP->fileMode);
1141  if (vfdP->fd < 0)
1142  {
1143  DO_DB(elog(LOG, "re-open failed: %m"));
1144  return -1;
1145  }
1146  else
1147  {
1148  ++nfile;
1149  }
1150  }
1151 
1152  /*
1153  * put it at the head of the Lru ring
1154  */
1155 
1156  Insert(file);
1157 
1158  return 0;
1159 }
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
mode_t fileMode
Definition: fd.c:188
char * fileName
Definition: fd.c:185
static int nfile
Definition: fd.c:202
Definition: fd.c:176
int fd
Definition: fd.c:178
static void Insert(File file)
Definition: fd.c:1096
static void ReleaseLruFiles(void)
Definition: fd.c:1187
#define FileIsNotOpen(file)
Definition: fd.c:169
#define Assert(condition)
Definition: c.h:739
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1003
#define elog(elevel,...)
Definition: elog.h:228
int fileFlags
Definition: fd.c:187

◆ MakePGDirectory()

int MakePGDirectory ( const char *  directoryName)

◆ OpenPipeStream()

FILE* OpenPipeStream ( const char *  command,
const char *  mode 
)

Definition at line 2345 of file fd.c.

References AllocateDescPipe, AllocateDesc::create_subid, AllocateDesc::desc, DO_DB, elog, ereport, errcode(), errmsg(), ERROR, AllocateDesc::file, GetCurrentSubTransactionId(), AllocateDesc::kind, LOG, maxAllocatedDescs, numAllocatedDescs, pqsignal(), ReleaseLruFile(), ReleaseLruFiles(), reserveAllocatedDesc(), SIG_DFL, SIG_IGN, SIGPIPE, and generate_unaccent_rules::stdout.

Referenced by BeginCopyFrom(), BeginCopyTo(), pg_import_system_collations(), and run_ssl_passphrase_command().

2346 {
2347  FILE *file;
2348  int save_errno;
2349 
2350  DO_DB(elog(LOG, "OpenPipeStream: Allocated %d (%s)",
2351  numAllocatedDescs, command));
2352 
2353  /* Can we allocate another non-virtual FD? */
2354  if (!reserveAllocatedDesc())
2355  ereport(ERROR,
2356  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2357  errmsg("exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"",
2358  maxAllocatedDescs, command)));
2359 
2360  /* Close excess kernel FDs. */
2361  ReleaseLruFiles();
2362 
2363 TryAgain:
2364  fflush(stdout);
2365  fflush(stderr);
2367  errno = 0;
2368  file = popen(command, mode);
2369  save_errno = errno;
2371  errno = save_errno;
2372  if (file != NULL)
2373  {
2375 
2376  desc->kind = AllocateDescPipe;
2377  desc->desc.file = file;
2380  return desc->desc.file;
2381  }
2382 
2383  if (errno == EMFILE || errno == ENFILE)
2384  {
2385  ereport(LOG,
2386  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2387  errmsg("out of file descriptors: %m; release and retry")));
2388  if (ReleaseLruFile())
2389  goto TryAgain;
2390  errno = save_errno;
2391  }
2392 
2393  return NULL;
2394 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
static AllocateDesc * allocatedDescs
Definition: fd.c:244
union AllocateDesc::@26 desc
#define DO_DB(A)
Definition: fd.c:160
int errcode(int sqlerrcode)
Definition: elog.c:608
static bool reserveAllocatedDesc(void)
Definition: fd.c:2169
#define SIGPIPE
Definition: win32_port.h:159
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:232
static bool ReleaseLruFile(void)
Definition: fd.c:1165
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define SIG_IGN
Definition: win32_port.h:151
static void ReleaseLruFiles(void)
Definition: fd.c:1187
FILE * file
Definition: fd.c:236
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:170
#define SIG_DFL
Definition: win32_port.h:149
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:707
SubTransactionId create_subid
Definition: fd.c:233
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
static int maxAllocatedDescs
Definition: fd.c:243
static int numAllocatedDescs
Definition: fd.c:242

◆ OpenTemporaryFile()

File OpenTemporaryFile ( bool  interXact)

Definition at line 1499 of file fd.c.

References CurrentResourceOwner, FD_DELETE_AT_CLOSE, FD_TEMP_FILE_LIMIT, vfd::fdstate, GetNextTempTableSpace(), MyDatabaseTableSpace, numTempTableSpaces, OidIsValid, OpenTemporaryFileInTablespace(), RegisterTemporaryFile(), and ResourceOwnerEnlargeFiles().

Referenced by BufFileCreateTemp(), and extendBufFile().

1500 {
1501  File file = 0;
1502 
1503  /*
1504  * Make sure the current resource owner has space for this File before we
1505  * open it, if we'll be registering it below.
1506  */
1507  if (!interXact)
1509 
1510  /*
1511  * If some temp tablespace(s) have been given to us, try to use the next
1512  * one. If a given tablespace can't be found, we silently fall back to
1513  * the database's default tablespace.
1514  *
1515  * BUT: if the temp file is slated to outlive the current transaction,
1516  * force it into the database's default tablespace, so that it will not
1517  * pose a threat to possible tablespace drop attempts.
1518  */
1519  if (numTempTableSpaces > 0 && !interXact)
1520  {
1521  Oid tblspcOid = GetNextTempTableSpace();
1522 
1523  if (OidIsValid(tblspcOid))
1524  file = OpenTemporaryFileInTablespace(tblspcOid, false);
1525  }
1526 
1527  /*
1528  * If not, or if tablespace is bad, create in database's default
1529  * tablespace. MyDatabaseTableSpace should normally be set before we get
1530  * here, but just in case it isn't, fall back to pg_default tablespace.
1531  */
1532  if (file <= 0)
1535  DEFAULTTABLESPACE_OID,
1536  true);
1537 
1538  /* Mark it for deletion at close and temporary file size limit */
1540 
1541  /* Register it with the current resource owner */
1542  if (!interXact)
1543  RegisterTemporaryFile(file);
1544 
1545  return file;
1546 }
static File OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
Definition: fd.c:1577
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:174
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
#define FD_DELETE_AT_CLOSE
Definition: fd.c:172
static Vfd * VfdCache
Definition: fd.c:196
static int numTempTableSpaces
Definition: fd.c:257
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
Oid MyDatabaseTableSpace
Definition: globals.c:87
Oid GetNextTempTableSpace(void)
Definition: fd.c:2764
unsigned short fdstate
Definition: fd.c:179
static void RegisterTemporaryFile(File file)
Definition: fd.c:1330
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1233
int File
Definition: fd.h:45

◆ OpenTemporaryFileInTablespace()

static File OpenTemporaryFileInTablespace ( Oid  tblspcOid,
bool  rejectError 
)
static

Definition at line 1577 of file fd.c.

References elog, ERROR, MakePGDirectory(), MAXPGPATH, MyProcPid, PathNameOpenFile(), PG_BINARY, PG_TEMP_FILE_PREFIX, snprintf, tempFileCounter, and TempTablespacePath().

Referenced by OpenTemporaryFile().

1578 {
1579  char tempdirpath[MAXPGPATH];
1580  char tempfilepath[MAXPGPATH];
1581  File file;
1582 
1583  TempTablespacePath(tempdirpath, tblspcOid);
1584 
1585  /*
1586  * Generate a tempfile name that should be unique within the current
1587  * database instance.
1588  */
1589  snprintf(tempfilepath, sizeof(tempfilepath), "%s/%s%d.%ld",
1590  tempdirpath, PG_TEMP_FILE_PREFIX, MyProcPid, tempFileCounter++);
1591 
1592  /*
1593  * Open the file. Note: we don't use O_EXCL, in case there is an orphaned
1594  * temp file that can be reused.
1595  */
1596  file = PathNameOpenFile(tempfilepath,
1597  O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1598  if (file <= 0)
1599  {
1600  /*
1601  * We might need to create the tablespace's tempfile directory, if no
1602  * one has yet done so.
1603  *
1604  * Don't check for an error from MakePGDirectory; it could fail if
1605  * someone else just did the same thing. If it doesn't work then
1606  * we'll bomb out on the second create attempt, instead.
1607  */
1608  (void) MakePGDirectory(tempdirpath);
1609 
1610  file = PathNameOpenFile(tempfilepath,
1611  O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1612  if (file <= 0 && rejectError)
1613  elog(ERROR, "could not create temporary file \"%s\": %m",
1614  tempfilepath);
1615  }
1616 
1617  return file;
1618 }
int MyProcPid
Definition: globals.c:40
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1358
void TempTablespacePath(char *path, Oid tablespace)
Definition: fd.c:1552
#define PG_BINARY
Definition: c.h:1222
#define ERROR
Definition: elog.h:43
#define PG_TEMP_FILE_PREFIX
Definition: pg_checksums.c:59
#define MAXPGPATH
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3496
static long tempFileCounter
Definition: fd.c:250
#define elog(elevel,...)
Definition: elog.h:228
#define snprintf
Definition: port.h:192
int File
Definition: fd.h:45

◆ OpenTransientFile()

◆ OpenTransientFilePerm()

int OpenTransientFilePerm ( const char *  fileName,
int  fileFlags,
mode_t  fileMode 
)

Definition at line 2301 of file fd.c.

References AllocateDescRawFD, BasicOpenFilePerm(), AllocateDesc::create_subid, AllocateDesc::desc, DO_DB, elog, ereport, errcode(), errmsg(), ERROR, vfd::fd, AllocateDesc::fd, GetCurrentSubTransactionId(), AllocateDesc::kind, LOG, maxAllocatedDescs, numAllocatedDescs, ReleaseLruFiles(), and reserveAllocatedDesc().

Referenced by be_lo_export(), and OpenTransientFile().

2302 {
2303  int fd;
2304 
2305  DO_DB(elog(LOG, "OpenTransientFile: Allocated %d (%s)",
2306  numAllocatedDescs, fileName));
2307 
2308  /* Can we allocate another non-virtual FD? */
2309  if (!reserveAllocatedDesc())
2310  ereport(ERROR,
2311  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2312  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2313  maxAllocatedDescs, fileName)));
2314 
2315  /* Close excess kernel FDs. */
2316  ReleaseLruFiles();
2317 
2318  fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
2319 
2320  if (fd >= 0)
2321  {
2323 
2324  desc->kind = AllocateDescRawFD;
2325  desc->desc.fd = fd;
2328 
2329  return fd;
2330  }
2331 
2332  return -1; /* failure */
2333 }
static AllocateDesc * allocatedDescs
Definition: fd.c:244
union AllocateDesc::@26 desc
#define DO_DB(A)
Definition: fd.c:160
int errcode(int sqlerrcode)
Definition: elog.c:608
static bool reserveAllocatedDesc(void)
Definition: fd.c:2169
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:232
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
static void ReleaseLruFiles(void)
Definition: fd.c:1187
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:707
SubTransactionId create_subid
Definition: fd.c:233
int fd
Definition: fd.c:238
int errmsg(const char *fmt,...)
Definition: elog.c:822
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1003
#define elog(elevel,...)
Definition: elog.h:228
static int maxAllocatedDescs
Definition: fd.c:243
static int numAllocatedDescs
Definition: fd.c:242

◆ PathNameCreateTemporaryDir()

void PathNameCreateTemporaryDir ( const char *  basedir,
const char *  directory 
)

Definition at line 1435 of file fd.c.

References ereport, errcode_for_file_access(), errmsg(), ERROR, and MakePGDirectory().

Referenced by SharedFileSetCreate().

1436 {
1437  if (MakePGDirectory(directory) < 0)
1438  {
1439  if (errno == EEXIST)
1440  return;
1441 
1442  /*
1443  * Failed. Try to create basedir first in case it's missing. Tolerate
1444  * EEXIST to close a race against another process following the same
1445  * algorithm.
1446  */
1447  if (MakePGDirectory(basedir) < 0 && errno != EEXIST)
1448  ereport(ERROR,
1450  errmsg("cannot create temporary directory \"%s\": %m",
1451  basedir)));
1452 
1453  /* Try again. */
1454  if (MakePGDirectory(directory) < 0 && errno != EEXIST)
1455  ereport(ERROR,
1457  errmsg("cannot create temporary subdirectory \"%s\": %m",
1458  directory)));
1459  }
1460 }
static char * basedir
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3496
static const char * directory
Definition: zic.c:622
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ PathNameCreateTemporaryFile()

File PathNameCreateTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1634 of file fd.c.

References CurrentResourceOwner, ereport, errcode_for_file_access(), errmsg(), ERROR, FD_TEMP_FILE_LIMIT, vfd::fdstate, PathNameOpenFile(), PG_BINARY, RegisterTemporaryFile(), and ResourceOwnerEnlargeFiles().

Referenced by SharedFileSetCreate().

1635 {
1636  File file;
1637 
1639 
1640  /*
1641  * Open the file. Note: we don't use O_EXCL, in case there is an orphaned
1642  * temp file that can be reused.
1643  */
1644  file = PathNameOpenFile(path, O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1645  if (file <= 0)
1646  {
1647  if (error_on_failure)
1648  ereport(ERROR,
1650  errmsg("could not create temporary file \"%s\": %m",
1651  path)));
1652  else
1653  return file;
1654  }
1655 
1656  /* Mark it for temp_file_limit accounting. */
1658 
1659  /* Register it for automatic close. */
1660  RegisterTemporaryFile(file);
1661 
1662  return file;
1663 }
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1358
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:174
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
static Vfd * VfdCache
Definition: fd.c:196
#define PG_BINARY
Definition: c.h:1222
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:631
unsigned short fdstate
Definition: fd.c:179
#define ereport(elevel, rest)
Definition: elog.h:141
static void RegisterTemporaryFile(File file)
Definition: fd.c:1330
int errmsg(const char *fmt,...)
Definition: elog.c:822
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1233
int File
Definition: fd.h:45

◆ PathNameDeleteTemporaryDir()

void PathNameDeleteTemporaryDir ( const char *  dirname)

Definition at line 1466 of file fd.c.

References LOG, stat, unlink_if_exists_fname(), and walkdir().

Referenced by SharedFileSetDeleteAll().

1467 {
1468  struct stat statbuf;
1469 
1470  /* Silently ignore missing directory. */
1471  if (stat(dirname, &statbuf) != 0 && errno == ENOENT)
1472  return;
1473 
1474  /*
1475  * Currently, walkdir doesn't offer a way for our passed in function to
1476  * maintain state. Perhaps it should, so that we could tell the caller
1477  * whether this operation succeeded or failed. Since this operation is
1478  * used in a cleanup path, we wouldn't actually behave differently: we'll
1479  * just log failures.
1480  */
1481  walkdir(dirname, unlink_if_exists_fname, false, LOG);
1482 }
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
Definition: fd.c:3245
#define LOG
Definition: elog.h:26
static void unlink_if_exists_fname(const char *fname, bool isdir, int elevel)
Definition: fd.c:3355
#define stat(a, b)
Definition: win32_port.h:255

◆ PathNameDeleteTemporaryFile()

bool PathNameDeleteTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1702 of file fd.c.

References ereport, errcode_for_file_access(), errmsg(), ERROR, LOG, ReportTemporaryFileUsage(), and stat.

Referenced by SharedFileSetDelete(), and unlink_if_exists_fname().

1703 {
1704  struct stat filestats;
1705  int stat_errno;
1706 
1707  /* Get the final size for pgstat reporting. */
1708  if (stat(path, &filestats) != 0)
1709  stat_errno = errno;
1710  else
1711  stat_errno = 0;
1712 
1713  /*
1714  * Unlike FileClose's automatic file deletion code, we tolerate
1715  * non-existence to support BufFileDeleteShared which doesn't know how
1716  * many segments it has to delete until it runs out.
1717  */
1718  if (stat_errno == ENOENT)
1719  return false;
1720 
1721  if (unlink(path) < 0)
1722  {
1723  if (errno != ENOENT)
1724  ereport(error_on_failure ? ERROR : LOG,
1726  errmsg("could not unlink temporary file \"%s\": %m",
1727  path)));
1728  return false;
1729  }
1730 
1731  if (stat_errno == 0)
1732  ReportTemporaryFileUsage(path, filestats.st_size);
1733  else
1734  {
1735  errno = stat_errno;
1736  ereport(LOG,
1738  errmsg("could not stat file \"%s\": %m", path)));
1739  }
1740 
1741  return true;
1742 }
#define LOG
Definition: elog.h:26
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
static void ReportTemporaryFileUsage(const char *path, off_t size)
Definition: fd.c:1311
#define stat(a, b)
Definition: win32_port.h:255
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ PathNameOpenFile()

File PathNameOpenFile ( const char *  fileName,
int  fileFlags 
)

Definition at line 1358 of file fd.c.

References PathNameOpenFilePerm(), and pg_file_create_mode.

Referenced by _mdfd_openseg(), logical_rewrite_log_mapping(), mdcreate(), mdopenfork(), mdsyncfiletag(), OpenTemporaryFileInTablespace(), PathNameCreateTemporaryFile(), and PathNameOpenTemporaryFile().

1359 {
1360  return PathNameOpenFilePerm(fileName, fileFlags, pg_file_create_mode);
1361 }
File PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1371
int pg_file_create_mode
Definition: file_perm.c:19

◆ PathNameOpenFilePerm()

File PathNameOpenFilePerm ( const char *  fileName,
int  fileFlags,
mode_t  fileMode 
)

Definition at line 1371 of file fd.c.

References AllocateVfd(), BasicOpenFilePerm(), DO_DB, elog, ereport, errcode(), errmsg(), ERROR, vfd::fd, vfd::fdstate, vfd::fileFlags, vfd::fileMode, vfd::fileName, vfd::fileSize, free, FreeVfd(), Insert(), LOG, nfile, ReleaseLruFiles(), and vfd::resowner.

Referenced by PathNameOpenFile().

1372 {
1373  char *fnamecopy;
1374  File file;
1375  Vfd *vfdP;
1376 
1377  DO_DB(elog(LOG, "PathNameOpenFilePerm: %s %x %o",
1378  fileName, fileFlags, fileMode));
1379 
1380  /*
1381  * We need a malloc'd copy of the file name; fail cleanly if no room.
1382  */
1383  fnamecopy = strdup(fileName);
1384  if (fnamecopy == NULL)
1385  ereport(ERROR,
1386  (errcode(ERRCODE_OUT_OF_MEMORY),
1387  errmsg("out of memory")));
1388 
1389  file = AllocateVfd();
1390  vfdP = &VfdCache[file];
1391 
1392  /* Close excess kernel FDs. */
1393  ReleaseLruFiles();
1394 
1395  vfdP->fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
1396 
1397  if (vfdP->fd < 0)
1398  {
1399  int save_errno = errno;
1400 
1401  FreeVfd(file);
1402  free(fnamecopy);
1403  errno = save_errno;
1404  return -1;
1405  }
1406  ++nfile;
1407  DO_DB(elog(LOG, "PathNameOpenFile: success %d",
1408  vfdP->fd));
1409 
1410  Insert(file);
1411 
1412  vfdP->fileName = fnamecopy;
1413  /* Saved flags are adjusted to be OK for re-opening file */
1414  vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
1415  vfdP->fileMode = fileMode;
1416  vfdP->fileSize = 0;
1417  vfdP->fdstate = 0x0;
1418  vfdP->resowner = NULL;
1419 
1420  return file;
1421 }
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
int errcode(int sqlerrcode)
Definition: elog.c:608
#define LOG
Definition: elog.h:26
mode_t fileMode
Definition: fd.c:188
#define ERROR
Definition: elog.h:43
char * fileName
Definition: fd.c:185
static int nfile
Definition: fd.c:202
static File AllocateVfd(void)
Definition: fd.c:1197
unsigned short fdstate
Definition: fd.c:179
Definition: fd.c:176
off_t fileSize
Definition: fd.c:184
int fd
Definition: fd.c:178
#define ereport(elevel, rest)
Definition: elog.h:141
static void Insert(File file)
Definition: fd.c:1096
ResourceOwner resowner
Definition: fd.c:180
static void ReleaseLruFiles(void)
Definition: fd.c:1187
#define free(a)
Definition: header.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:822
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1003
#define elog(elevel,...)
Definition: elog.h:228
static void FreeVfd(File file)
Definition: fd.c:1255
int fileFlags
Definition: fd.c:187
int File
Definition: fd.h:45

◆ PathNameOpenTemporaryFile()

File PathNameOpenTemporaryFile ( const char *  path)

Definition at line 1672 of file fd.c.

References CurrentResourceOwner, ereport, errcode_for_file_access(), errmsg(), ERROR, PathNameOpenFile(), PG_BINARY, RegisterTemporaryFile(), and ResourceOwnerEnlargeFiles().

Referenced by SharedFileSetOpen().

1673 {
1674  File file;
1675 
1677 
1678  /* We open the file read-only. */
1679  file = PathNameOpenFile(path, O_RDONLY | PG_BINARY);
1680 
1681  /* If no such file, then we don't raise an error. */
1682  if (file <= 0 && errno != ENOENT)
1683  ereport(ERROR,
1685  errmsg("could not open temporary file \"%s\": %m",
1686  path)));
1687 
1688  if (file > 0)
1689  {
1690  /* Register it for automatic close. */
1691  RegisterTemporaryFile(file);
1692  }
1693 
1694  return file;
1695 }
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1358
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
#define PG_BINARY
Definition: c.h:1222
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
static void RegisterTemporaryFile(File file)
Definition: fd.c:1330
int errmsg(const char *fmt,...)
Definition: elog.c:822
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1233
int File
Definition: fd.h:45

◆ pg_fdatasync()

int pg_fdatasync ( int  fd)

Definition at line 420 of file fd.c.

References enableFsync, and fsync.

Referenced by issue_xlog_fsync().

421 {
422  if (enableFsync)
423  {
424 #ifdef HAVE_FDATASYNC
425  return fdatasync(fd);
426 #else
427  return fsync(fd);
428 #endif
429  }
430  else
431  return 0;
432 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define fsync(fd)
Definition: win32_port.h:63
bool enableFsync
Definition: globals.c:119

◆ pg_flush_data()

void pg_flush_data ( int  fd,
off_t  offset,
off_t  nbytes 
)

Definition at line 440 of file fd.c.

References data_sync_elevel(), elevel, enableFsync, ereport, errcode_for_file_access(), errmsg(), FATAL, MAP_FAILED, and WARNING.

Referenced by copy_file(), FileWriteback(), and walkdir().

441 {
442  /*
443  * Right now file flushing is primarily used to avoid making later
444  * fsync()/fdatasync() calls have less impact. Thus don't trigger flushes
445  * if fsyncs are disabled - that's a decision we might want to make
446  * configurable at some point.
447  */
448  if (!enableFsync)
449  return;
450 
451  /*
452  * We compile all alternatives that are supported on the current platform,
453  * to find portability problems more easily.
454  */
455 #if defined(HAVE_SYNC_FILE_RANGE)
456  {
457  int rc;
458  static bool not_implemented_by_kernel = false;
459 
460  if (not_implemented_by_kernel)
461  return;
462 
463  /*
464  * sync_file_range(SYNC_FILE_RANGE_WRITE), currently linux specific,
465  * tells the OS that writeback for the specified blocks should be
466  * started, but that we don't want to wait for completion. Note that
467  * this call might block if too much dirty data exists in the range.
468  * This is the preferable method on OSs supporting it, as it works
469  * reliably when available (contrast to msync()) and doesn't flush out
470  * clean data (like FADV_DONTNEED).
471  */
472  rc = sync_file_range(fd, offset, nbytes,
473  SYNC_FILE_RANGE_WRITE);
474  if (rc != 0)
475  {
476  int elevel;
477 
478  /*
479  * For systems that don't have an implementation of
480  * sync_file_range() such as Windows WSL, generate only one
481  * warning and then suppress all further attempts by this process.
482  */
483  if (errno == ENOSYS)
484  {
485  elevel = WARNING;
486  not_implemented_by_kernel = true;
487  }
488  else
489  elevel = data_sync_elevel(WARNING);
490 
491  ereport(elevel,
493  errmsg("could not flush dirty data: %m")));
494  }
495 
496  return;
497  }
498 #endif
499 #if !defined(WIN32) && defined(MS_ASYNC)
500  {
501  void *p;
502  static int pagesize = 0;
503 
504  /*
505  * On several OSs msync(MS_ASYNC) on a mmap'ed file triggers
506  * writeback. On linux it only does so if MS_SYNC is specified, but
507  * then it does the writeback synchronously. Luckily all common linux
508  * systems have sync_file_range(). This is preferable over
509  * FADV_DONTNEED because it doesn't flush out clean data.
510  *
511  * We map the file (mmap()), tell the kernel to sync back the contents
512  * (msync()), and then remove the mapping again (munmap()).
513  */
514 
515  /* mmap() needs actual length if we want to map whole file */
516  if (offset == 0 && nbytes == 0)
517  {
518  nbytes = lseek(fd, 0, SEEK_END);
519  if (nbytes < 0)
520  {
523  errmsg("could not determine dirty data size: %m")));
524  return;
525  }
526  }
527 
528  /*
529  * Some platforms reject partial-page mmap() attempts. To deal with
530  * that, just truncate the request to a page boundary. If any extra
531  * bytes don't get flushed, well, it's only a hint anyway.
532  */
533 
534  /* fetch pagesize only once */
535  if (pagesize == 0)
536  pagesize = sysconf(_SC_PAGESIZE);
537 
538  /* align length to pagesize, dropping any fractional page */
539  if (pagesize > 0)
540  nbytes = (nbytes / pagesize) * pagesize;
541 
542  /* fractional-page request is a no-op */
543  if (nbytes <= 0)
544  return;
545 
546  /*
547  * mmap could well fail, particularly on 32-bit platforms where there
548  * may simply not be enough address space. If so, silently fall
549  * through to the next implementation.
550  */
551  if (nbytes <= (off_t) SSIZE_MAX)
552  p = mmap(NULL, nbytes, PROT_READ, MAP_SHARED, fd, offset);
553  else
554  p = MAP_FAILED;
555 
556  if (p != MAP_FAILED)
557  {
558  int rc;
559 
560  rc = msync(p, (size_t) nbytes, MS_ASYNC);
561  if (rc != 0)
562  {
565  errmsg("could not flush dirty data: %m")));
566  /* NB: need to fall through to munmap()! */
567  }
568 
569  rc = munmap(p, (size_t) nbytes);
570  if (rc != 0)
571  {
572  /* FATAL error because mapping would remain */
573  ereport(FATAL,
575  errmsg("could not munmap() while flushing data: %m")));
576  }
577 
578  return;
579  }
580  }
581 #endif
582 #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
583  {
584  int rc;
585 
586  /*
587  * Signal the kernel that the passed in range should not be cached
588  * anymore. This has the, desired, side effect of writing out dirty
589  * data, and the, undesired, side effect of likely discarding useful
590  * clean cached blocks. For the latter reason this is the least
591  * preferable method.
592  */
593 
594  rc = posix_fadvise(fd, offset, nbytes, POSIX_FADV_DONTNEED);
595 
596  if (rc != 0)
597  {
598  /* don't error out, this is just a performance optimization */
601  errmsg("could not flush dirty data: %m")));
602  }
603 
604  return;
605  }
606 #endif
607 }
#define MAP_FAILED
Definition: mem.h:45
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define FATAL
Definition: elog.h:52
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
#define WARNING
Definition: elog.h:40
static int elevel
Definition: vacuumlazy.c:143
int data_sync_elevel(int elevel)
Definition: fd.c:3519
bool enableFsync
Definition: globals.c:119
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ pg_fsync()

int pg_fsync ( int  fd)

Definition at line 330 of file fd.c.

References Assert, pg_fsync_no_writethrough(), pg_fsync_writethrough(), S_ISDIR, stat, sync_method, and SYNC_METHOD_FSYNC_WRITETHROUGH.

Referenced by AddToDataDirLockFile(), assign_xlog_sync_method(), BootStrapXLOG(), CheckPointLogicalRewriteHeap(), CreateLockFile(), do_pg_start_backup(), durable_rename(), FileSync(), fsync_fname_ext(), heap_xlog_logical_rewrite(), readRecoverySignalFile(), RecreateTwoPhaseFile(), RestoreSlotFromDisk(), SaveSlotToPath(), SimpleLruFlush(), SlruPhysicalWritePage(), SnapBuildSerialize(), update_controlfile(), write_auto_conf_file(), write_relmap_file(), WriteControlFile(), writeTimeLineHistory(), writeTimeLineHistoryFile(), XLogFileCopy(), and XLogFileInit().

331 {
332 #if !defined(WIN32) && defined(USE_ASSERT_CHECKING)
333  struct stat st;
334 
335  /*
336  * Some operating system implementations of fsync() have requirements
337  * about the file access modes that were used when their file descriptor
338  * argument was opened, and these requirements differ depending on whether
339  * the file descriptor is for a directory.
340  *
341  * For any file descriptor that may eventually be handed to fsync(), we
342  * should have opened it with access modes that are compatible with
343  * fsync() on all supported systems, otherwise the code may not be
344  * portable, even if it runs ok on the current system.
345  *
346  * We assert here that a descriptor for a file was opened with write
347  * permissions (either O_RDWR or O_WRONLY) and for a directory without
348  * write permissions (O_RDONLY).
349  *
350  * Ignore any fstat errors and let the follow-up fsync() do its work.
351  * Doing this sanity check here counts for the case where fsync() is
352  * disabled.
353  */
354  if (fstat(fd, &st) == 0)
355  {
356  int desc_flags = fcntl(fd, F_GETFL);
357 
358  /*
359  * O_RDONLY is historically 0, so just make sure that for directories
360  * no write flags are used.
361  */
362  if (S_ISDIR(st.st_mode))
363  Assert((desc_flags & (O_RDWR | O_WRONLY)) == 0);
364  else
365  Assert((desc_flags & (O_RDWR | O_WRONLY)) != 0);
366  }
367  errno = 0;
368 #endif
369 
370  /* #if is to skip the sync_method test if there's no need for it */
371 #if defined(HAVE_FSYNC_WRITETHROUGH) && !defined(FSYNC_WRITETHROUGH_IS_FSYNC)
373  return pg_fsync_writethrough(fd);
374  else
375 #endif
377 }
#define SYNC_METHOD_FSYNC_WRITETHROUGH
Definition: xlog.h:28
int pg_fsync_writethrough(int fd)
Definition: fd.c:397
int pg_fsync_no_writethrough(int fd)
Definition: fd.c:385
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define stat(a, b)
Definition: win32_port.h:255
#define Assert(condition)
Definition: c.h:739
int sync_method
Definition: xlog.c:102
#define S_ISDIR(m)
Definition: win32_port.h:296

◆ pg_fsync_no_writethrough()

int pg_fsync_no_writethrough ( int  fd)

Definition at line 385 of file fd.c.

References enableFsync, and fsync.

Referenced by issue_xlog_fsync(), and pg_fsync().

386 {
387  if (enableFsync)
388  return fsync(fd);
389  else
390  return 0;
391 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define fsync(fd)
Definition: win32_port.h:63
bool enableFsync
Definition: globals.c:119

◆ pg_fsync_writethrough()

int pg_fsync_writethrough ( int  fd)

Definition at line 397 of file fd.c.

References enableFsync.

Referenced by issue_xlog_fsync(), pg_fsync(), signal_cleanup(), and test_sync().

398 {
399  if (enableFsync)
400  {
401 #ifdef WIN32
402  return _commit(fd);
403 #elif defined(F_FULLFSYNC)
404  return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
405 #else
406  errno = ENOSYS;
407  return -1;
408 #endif
409  }
410  else
411  return 0;
412 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
bool enableFsync
Definition: globals.c:119

◆ ReadDir()

◆ ReadDirExtended()

struct dirent* ReadDirExtended ( DIR dir,
const char *  dirname,
int  elevel 
)

Definition at line 2584 of file fd.c.

References ereport, errcode_for_file_access(), errmsg(), and readdir().

Referenced by DeleteAllExportedSnapshotFiles(), ReadDir(), RelationCacheInitFileRemove(), RelationCacheInitFileRemoveInDir(), RemovePgTempFiles(), RemovePgTempFilesInDir(), RemovePgTempRelationFiles(), RemovePgTempRelationFilesInDbspace(), ReorderBufferCleanupSerializedTXNs(), scan_directory_ci(), and walkdir().

2585 {
2586  struct dirent *dent;
2587 
2588  /* Give a generic message for AllocateDir failure, if caller didn't */
2589  if (dir == NULL)
2590  {
2591  ereport(elevel,
2593  errmsg("could not open directory \"%s\": %m",
2594  dirname)));
2595  return NULL;
2596  }
2597 
2598  errno = 0;
2599  if ((dent = readdir(dir)) != NULL)
2600  return dent;
2601 
2602  if (errno)
2603  ereport(elevel,
2605  errmsg("could not read directory \"%s\": %m",
2606  dirname)));
2607  return NULL;
2608 }
Definition: dirent.h:9
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
static int elevel
Definition: vacuumlazy.c:143
struct dirent * readdir(DIR *)
Definition: dirent.c:77
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ RegisterTemporaryFile()

static void RegisterTemporaryFile ( File  file)
static

Definition at line 1330 of file fd.c.

References Assert, CurrentResourceOwner, FD_CLOSE_AT_EOXACT, vfd::fdstate, FileIsNotOpen, FileIsValid, have_xact_temporary_files, LruDelete(), ResourceOwnerRememberFile(), and vfd::resowner.

Referenced by OpenTemporaryFile(), PathNameCreateTemporaryFile(), and PathNameOpenTemporaryFile().

1331 {
1334 
1335  /* Backup mechanism for closing at end of xact. */
1338 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
static Vfd * VfdCache
Definition: fd.c:196
static bool have_xact_temporary_files
Definition: fd.c:208
void ResourceOwnerRememberFile(ResourceOwner owner, File file)
Definition: resowner.c:1244
unsigned short fdstate
Definition: fd.c:179
ResourceOwner resowner
Definition: fd.c:180
#define FD_CLOSE_AT_EOXACT
Definition: fd.c:173

◆ ReleaseLruFile()

static bool ReleaseLruFile ( void  )
static

Definition at line 1165 of file fd.c.

References Assert, DO_DB, elog, LOG, LruDelete(), vfd::lruMoreRecently, and nfile.

Referenced by AllocateDir(), AllocateFile(), BasicOpenFilePerm(), OpenPipeStream(), and ReleaseLruFiles().

1166 {
1167  DO_DB(elog(LOG, "ReleaseLruFile. Opened %d", nfile));
1168 
1169  if (nfile > 0)
1170  {
1171  /*
1172  * There are opened files and so there should be at least one used vfd
1173  * in the ring.
1174  */
1175  Assert(VfdCache[0].lruMoreRecently != 0);
1176  LruDelete(VfdCache[0].lruMoreRecently);
1177  return true; /* freed a file */
1178  }
1179  return false; /* no files available to free */
1180 }
#define DO_DB(A)
Definition: fd.c:160
static Vfd * VfdCache
Definition: fd.c:196
#define LOG
Definition: elog.h:26
static void LruDelete(File file)
Definition: fd.c:1070
static int nfile
Definition: fd.c:202
#define Assert(condition)
Definition: c.h:739
#define elog(elevel,...)
Definition: elog.h:228

◆ ReleaseLruFiles()

static void ReleaseLruFiles ( void  )
static

Definition at line 1187 of file fd.c.

References max_safe_fds, nfile, numAllocatedDescs, and ReleaseLruFile().

Referenced by AllocateDir(), AllocateFile(), LruInsert(), OpenPipeStream(), OpenTransientFilePerm(), and PathNameOpenFilePerm().

1188 {
1189  while (nfile + numAllocatedDescs >= max_safe_fds)
1190  {
1191  if (!ReleaseLruFile())
1192  break;
1193  }
1194 }
int max_safe_fds
Definition: fd.c:145
static bool ReleaseLruFile(void)
Definition: fd.c:1165
static int nfile
Definition: fd.c:202
static int numAllocatedDescs
Definition: fd.c:242

◆ RemovePgTempFiles()

void RemovePgTempFiles ( void  )

Definition at line 2920 of file fd.c.

References AllocateDir(), dirent::d_name, FreeDir(), LOG, MAXPGPATH, PG_TEMP_FILES_DIR, ReadDirExtended(), RemovePgTempFilesInDir(), RemovePgTempRelationFiles(), snprintf, and TABLESPACE_VERSION_DIRECTORY.

Referenced by PostmasterMain().

2921 {
2922  char temp_path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY) + sizeof(PG_TEMP_FILES_DIR)];
2923  DIR *spc_dir;
2924  struct dirent *spc_de;
2925 
2926  /*
2927  * First process temp files in pg_default ($PGDATA/base)
2928  */
2929  snprintf(temp_path, sizeof(temp_path), "base/%s", PG_TEMP_FILES_DIR);
2930  RemovePgTempFilesInDir(temp_path, true, false);
2931  RemovePgTempRelationFiles("base");
2932 
2933  /*
2934  * Cycle through temp directories for all non-default tablespaces.
2935  */
2936  spc_dir = AllocateDir("pg_tblspc");
2937 
2938  while ((spc_de = ReadDirExtended(spc_dir, "pg_tblspc", LOG)) != NULL)
2939  {
2940  if (strcmp(spc_de->d_name, ".") == 0 ||
2941  strcmp(spc_de->d_name, "..") == 0)
2942  continue;
2943 
2944  snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s/%s",
2946  RemovePgTempFilesInDir(temp_path, true, false);
2947 
2948  snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s",
2950  RemovePgTempRelationFiles(temp_path);
2951  }
2952 
2953  FreeDir(spc_dir);
2954 
2955  /*
2956  * In EXEC_BACKEND case there is a pgsql_tmp directory at the top level of
2957  * DataDir as well. However, that is *not* cleaned here because doing so
2958  * would create a race condition. It's done separately, earlier in
2959  * postmaster startup.
2960  */
2961 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2584
#define PG_TEMP_FILES_DIR
Definition: pg_checksums.c:58
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
static void RemovePgTempRelationFiles(const char *tsdirname)
Definition: fd.c:3045
Definition: dirent.c:25
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, bool unlink_all)
Definition: fd.c:2979
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2503
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int FreeDir(DIR *dir)
Definition: fd.c:2621

◆ RemovePgTempFilesInDir()

void RemovePgTempFilesInDir ( const char *  tmpdirname,
bool  missing_ok,
bool  unlink_all 
)

Definition at line 2979 of file fd.c.

References AllocateDir(), dirent::d_name, ereport, errcode_for_file_access(), errmsg(), FreeDir(), LOG, lstat, MAXPGPATH, PG_TEMP_FILE_PREFIX, ReadDirExtended(), RemovePgTempFilesInDir(), S_ISDIR, snprintf, and stat.

Referenced by PostmasterMain(), RemovePgTempFiles(), and RemovePgTempFilesInDir().

2980 {
2981  DIR *temp_dir;
2982  struct dirent *temp_de;
2983  char rm_path[MAXPGPATH * 2];
2984 
2985  temp_dir = AllocateDir(tmpdirname);
2986 
2987  if (temp_dir == NULL && errno == ENOENT && missing_ok)
2988  return;
2989 
2990  while ((temp_de = ReadDirExtended(temp_dir, tmpdirname, LOG)) != NULL)
2991  {
2992  if (strcmp(temp_de->d_name, ".") == 0 ||
2993  strcmp(temp_de->d_name, "..") == 0)
2994  continue;
2995 
2996  snprintf(rm_path, sizeof(rm_path), "%s/%s",
2997  tmpdirname, temp_de->d_name);
2998 
2999  if (unlink_all ||
3000  strncmp(temp_de->d_name,
3002  strlen(PG_TEMP_FILE_PREFIX)) == 0)
3003  {
3004  struct stat statbuf;
3005 
3006  if (lstat(rm_path, &statbuf) < 0)
3007  {
3008  ereport(LOG,
3010  errmsg("could not stat file \"%s\": %m", rm_path)));
3011  continue;
3012  }
3013 
3014  if (S_ISDIR(statbuf.st_mode))
3015  {
3016  /* recursively remove contents, then directory itself */
3017  RemovePgTempFilesInDir(rm_path, false, true);
3018 
3019  if (rmdir(rm_path) < 0)
3020  ereport(LOG,
3022  errmsg("could not remove directory \"%s\": %m",
3023  rm_path)));
3024  }
3025  else
3026  {
3027  if (unlink(rm_path) < 0)
3028  ereport(LOG,
3030  errmsg("could not remove file \"%s\": %m",
3031  rm_path)));
3032  }
3033  }
3034  else
3035  ereport(LOG,
3036  (errmsg("unexpected file found in temporary-files directory: \"%s\"",
3037  rm_path)));
3038  }
3039 
3040  FreeDir(temp_dir);
3041 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2584
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define PG_TEMP_FILE_PREFIX
Definition: pg_checksums.c:59
#define MAXPGPATH
void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, bool unlink_all)
Definition: fd.c:2979
int errcode_for_file_access(void)
Definition: elog.c:631
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2503
#define ereport(elevel, rest)
Definition: elog.h:141
#define stat(a, b)
Definition: win32_port.h:255
#define S_ISDIR(m)
Definition: win32_port.h:296
#define lstat(path, sb)
Definition: win32_port.h:244
int errmsg(const char *fmt,...)
Definition: elog.c:822
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int FreeDir(DIR *dir)
Definition: fd.c:2621

◆ RemovePgTempRelationFiles()

static void RemovePgTempRelationFiles ( const char *  tsdirname)
static

Definition at line 3045 of file fd.c.

References AllocateDir(), dirent::d_name, FreeDir(), LOG, MAXPGPATH, ReadDirExtended(), RemovePgTempRelationFilesInDbspace(), and snprintf.

Referenced by RemovePgTempFiles().

3046 {
3047  DIR *ts_dir;
3048  struct dirent *de;
3049  char dbspace_path[MAXPGPATH * 2];
3050 
3051  ts_dir = AllocateDir(tsdirname);
3052 
3053  while ((de = ReadDirExtended(ts_dir, tsdirname, LOG)) != NULL)
3054  {
3055  /*
3056  * We're only interested in the per-database directories, which have
3057  * numeric names. Note that this code will also (properly) ignore "."
3058  * and "..".
3059  */
3060  if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
3061  continue;
3062 
3063  snprintf(dbspace_path, sizeof(dbspace_path), "%s/%s",
3064  tsdirname, de->d_name);
3065  RemovePgTempRelationFilesInDbspace(dbspace_path);
3066  }
3067 
3068  FreeDir(ts_dir);
3069 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2584
static void RemovePgTempRelationFilesInDbspace(const char *dbspacedirname)
Definition: fd.c:3073
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2503
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int FreeDir(DIR *dir)
Definition: fd.c:2621

◆ RemovePgTempRelationFilesInDbspace()

static void RemovePgTempRelationFilesInDbspace ( const char *  dbspacedirname)
static

Definition at line 3073 of file fd.c.

References AllocateDir(), dirent::d_name, ereport, errcode_for_file_access(), errmsg(), FreeDir(), LOG, looks_like_temp_rel_name(), MAXPGPATH, ReadDirExtended(), and snprintf.

Referenced by RemovePgTempRelationFiles().

3074 {
3075  DIR *dbspace_dir;
3076  struct dirent *de;
3077  char rm_path[MAXPGPATH * 2];
3078 
3079  dbspace_dir = AllocateDir(dbspacedirname);
3080 
3081  while ((de = ReadDirExtended(dbspace_dir, dbspacedirname, LOG)) != NULL)
3082  {
3083  if (!looks_like_temp_rel_name(de->d_name))
3084  continue;
3085 
3086  snprintf(rm_path, sizeof(rm_path), "%s/%s",
3087  dbspacedirname, de->d_name);
3088 
3089  if (unlink(rm_path) < 0)
3090  ereport(LOG,
3092  errmsg("could not remove file \"%s\": %m",
3093  rm_path)));
3094  }
3095 
3096  FreeDir(dbspace_dir);
3097 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2584
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:631
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2503
#define ereport(elevel, rest)
Definition: elog.h:141
bool looks_like_temp_rel_name(const char *name)
Definition: fd.c:3101
int errmsg(const char *fmt,...)
Definition: elog.c:822
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int FreeDir(DIR *dir)
Definition: fd.c:2621

◆ ReportTemporaryFileUsage()

static void ReportTemporaryFileUsage ( const char *  path,
off_t  size 
)
static

Definition at line 1311 of file fd.c.

References ereport, errmsg(), LOG, log_temp_files, and pgstat_report_tempfile().

Referenced by FileClose(), and PathNameDeleteTemporaryFile().

1312 {
1313  pgstat_report_tempfile(size);
1314 
1315  if (log_temp_files >= 0)
1316  {
1317  if ((size / 1024) >= log_temp_files)
1318  ereport(LOG,
1319  (errmsg("temporary file: path \"%s\", size %lu",
1320  path, (unsigned long) size)));
1321  }
1322 }
int log_temp_files
Definition: guc.c:518
void pgstat_report_tempfile(size_t filesize)
Definition: pgstat.c:1564
#define LOG
Definition: elog.h:26
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ reserveAllocatedDesc()

static bool reserveAllocatedDesc ( void  )
static

Definition at line 2169 of file fd.c.

References ereport, errcode(), errmsg(), ERROR, FD_MINFREE, malloc, max_safe_fds, maxAllocatedDescs, numAllocatedDescs, and realloc.

Referenced by AllocateDir(), AllocateFile(), OpenPipeStream(), and OpenTransientFilePerm().

2170 {
2171  AllocateDesc *newDescs;
2172  int newMax;
2173 
2174  /* Quick out if array already has a free slot. */
2176  return true;
2177 
2178  /*
2179  * If the array hasn't yet been created in the current process, initialize
2180  * it with FD_MINFREE / 2 elements. In many scenarios this is as many as
2181  * we will ever need, anyway. We don't want to look at max_safe_fds
2182  * immediately because set_max_safe_fds() may not have run yet.
2183  */
2184  if (allocatedDescs == NULL)
2185  {
2186  newMax = FD_MINFREE / 2;
2187  newDescs = (AllocateDesc *) malloc(newMax * sizeof(AllocateDesc));
2188  /* Out of memory already? Treat as fatal error. */
2189  if (newDescs == NULL)
2190  ereport(ERROR,
2191  (errcode(ERRCODE_OUT_OF_MEMORY),
2192  errmsg("out of memory")));
2193  allocatedDescs = newDescs;
2194  maxAllocatedDescs = newMax;
2195  return true;
2196  }
2197 
2198  /*
2199  * Consider enlarging the array beyond the initial allocation used above.
2200  * By the time this happens, max_safe_fds should be known accurately.
2201  *
2202  * We mustn't let allocated descriptors hog all the available FDs, and in
2203  * practice we'd better leave a reasonable number of FDs for VFD use. So
2204  * set the maximum to max_safe_fds / 2. (This should certainly be at
2205  * least as large as the initial size, FD_MINFREE / 2.)
2206  */
2207  newMax = max_safe_fds / 2;
2208  if (newMax > maxAllocatedDescs)
2209  {
2210  newDescs = (AllocateDesc *) realloc(allocatedDescs,
2211  newMax * sizeof(AllocateDesc));
2212  /* Treat out-of-memory as a non-fatal error. */
2213  if (newDescs == NULL)
2214  return false;
2215  allocatedDescs = newDescs;
2216  maxAllocatedDescs = newMax;
2217  return true;
2218  }
2219 
2220  /* Can't enlarge allocatedDescs[] any more. */
2221  return false;
2222 }
static AllocateDesc * allocatedDescs
Definition: fd.c:244
int max_safe_fds
Definition: fd.c:145
int errcode(int sqlerrcode)
Definition: elog.c:608
#define malloc(a)
Definition: header.h:50
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define FD_MINFREE
Definition: fd.c:124
#define realloc(a, b)
Definition: header.h:60
int errmsg(const char *fmt,...)
Definition: elog.c:822
static int maxAllocatedDescs
Definition: fd.c:243
static int numAllocatedDescs
Definition: fd.c:242

◆ set_max_safe_fds()

void set_max_safe_fds ( void  )

Definition at line 938 of file fd.c.

References count_usable_fds(), DEBUG2, elog, ereport, errcode(), errdetail(), errmsg(), FATAL, FD_MINFREE, max_files_per_process, max_safe_fds, Min, and NUM_RESERVED_FDS.

Referenced by PostmasterMain().

939 {
940  int usable_fds;
941  int already_open;
942 
943  /*----------
944  * We want to set max_safe_fds to
945  * MIN(usable_fds, max_files_per_process - already_open)
946  * less the slop factor for files that are opened without consulting
947  * fd.c. This ensures that we won't exceed either max_files_per_process
948  * or the experimentally-determined EMFILE limit.
949  *----------
950  */
952  &usable_fds, &already_open);
953 
954  max_safe_fds = Min(usable_fds, max_files_per_process - already_open);
955 
956  /*
957  * Take off the FDs reserved for system() etc.
958  */
960 
961  /*
962  * Make sure we still have enough to get by.
963  */
964  if (max_safe_fds < FD_MINFREE)
965  ereport(FATAL,
966  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
967  errmsg("insufficient file descriptors available to start server process"),
968  errdetail("System allows %d, we need at least %d.",
971 
972  elog(DEBUG2, "max_safe_fds = %d, usable_fds = %d, already_open = %d",
973  max_safe_fds, usable_fds, already_open);
974 }
static void count_usable_fds(int max_to_probe, int *usable_fds, int *already_open)
Definition: fd.c:854
#define NUM_RESERVED_FDS
Definition: fd.c:118
int max_safe_fds
Definition: fd.c:145
#define Min(x, y)
Definition: c.h:911
int errcode(int sqlerrcode)
Definition: elog.c:608
#define FATAL
Definition: elog.h:52
#define DEBUG2
Definition: elog.h:24
int errdetail(const char *fmt,...)
Definition: elog.c:955
int max_files_per_process
Definition: fd.c:132
#define ereport(elevel, rest)
Definition: elog.h:141
#define FD_MINFREE
Definition: fd.c:124
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228

◆ SetTempTablespaces()

void SetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2706 of file fd.c.

References Assert, nextTempTableSpace, numTempTableSpaces, random(), and tempTableSpaces.

Referenced by assign_temp_tablespaces(), and PrepareTempTablespaces().

2707 {
2708  Assert(numSpaces >= 0);
2709  tempTableSpaces = tableSpaces;
2710  numTempTableSpaces = numSpaces;
2711 
2712  /*
2713  * Select a random starting point in the list. This is to minimize
2714  * conflicts between backends that are most likely sharing the same list
2715  * of temp tablespaces. Note that if we create multiple temp files in the
2716  * same transaction, we'll advance circularly through the list --- this
2717  * ensures that large temporary sort files are nicely spread across all
2718  * available tablespaces.
2719  */
2720  if (numSpaces > 1)
2721  nextTempTableSpace = random() % numSpaces;
2722  else
2723  nextTempTableSpace = 0;
2724 }
long random(void)
Definition: random.c:22
static int numTempTableSpaces
Definition: fd.c:257
static int nextTempTableSpace
Definition: fd.c:258
#define Assert(condition)
Definition: c.h:739
static Oid * tempTableSpaces
Definition: fd.c:256

◆ SyncDataDirectory()

void SyncDataDirectory ( void  )

Definition at line 3171 of file fd.c.

References datadir_fsync_fname(), DEBUG1, enableFsync, ereport, errcode_for_file_access(), errmsg(), LOG, lstat, pgwin32_is_junction(), stat, and walkdir().

Referenced by StartupXLOG().

3172 {
3173  bool xlog_is_symlink;
3174 
3175  /* We can skip this whole thing if fsync is disabled. */
3176  if (!enableFsync)
3177  return;
3178 
3179  /*
3180  * If pg_wal is a symlink, we'll need to recurse into it separately,
3181  * because the first walkdir below will ignore it.
3182  */
3183  xlog_is_symlink = false;
3184 
3185 #ifndef WIN32
3186  {
3187  struct stat st;
3188 
3189  if (lstat("pg_wal", &st) < 0)
3190  ereport(LOG,
3192  errmsg("could not stat file \"%s\": %m",
3193  "pg_wal")));
3194  else if (S_ISLNK(st.st_mode))
3195  xlog_is_symlink = true;
3196  }
3197 #else
3198  if (pgwin32_is_junction("pg_wal"))
3199  xlog_is_symlink = true;
3200 #endif
3201 
3202  /*
3203  * If possible, hint to the kernel that we're soon going to fsync the data
3204  * directory and its contents. Errors in this step are even less
3205  * interesting than normal, so log them only at DEBUG1.
3206  */
3207 #ifdef PG_FLUSH_DATA_WORKS
3208  walkdir(".", pre_sync_fname, false, DEBUG1);
3209  if (xlog_is_symlink)
3210  walkdir("pg_wal", pre_sync_fname, false, DEBUG1);
3211  walkdir("pg_tblspc", pre_sync_fname, true, DEBUG1);
3212 #endif
3213 
3214  /*
3215  * Now we do the fsync()s in the same order.
3216  *
3217  * The main call ignores symlinks, so in addition to specially processing
3218  * pg_wal if it's a symlink, pg_tblspc has to be visited separately with
3219  * process_symlinks = true. Note that if there are any plain directories
3220  * in pg_tblspc, they'll get fsync'd twice. That's not an expected case
3221  * so we don't worry about optimizing it.
3222  */
3223  walkdir(".", datadir_fsync_fname, false, LOG);
3224  if (xlog_is_symlink)
3225  walkdir("pg_wal", datadir_fsync_fname, false, LOG);
3226  walkdir("pg_tblspc", datadir_fsync_fname, true, LOG);
3227 }
#define DEBUG1
Definition: elog.h:25
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
Definition: fd.c:3245
#define LOG
Definition: elog.h:26
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
static void datadir_fsync_fname(const char *fname, bool isdir, int elevel)
Definition: fd.c:3345
#define stat(a, b)
Definition: win32_port.h:255
#define lstat(path, sb)
Definition: win32_port.h:244
bool enableFsync
Definition: globals.c:119
int errmsg(const char *fmt,...)
Definition: elog.c:822
bool pgwin32_is_junction(const char *path)

◆ TempTablespacePath()

void TempTablespacePath ( char *  path,
Oid  tablespace 
)

Definition at line 1552 of file fd.c.

References InvalidOid, MAXPGPATH, PG_TEMP_FILES_DIR, snprintf, and TABLESPACE_VERSION_DIRECTORY.

Referenced by OpenTemporaryFileInTablespace(), pg_ls_tmpdir(), SharedFileSetCreate(), and SharedFileSetPath().

1553 {
1554  /*
1555  * Identify the tempfile directory for this tablespace.
1556  *
1557  * If someone tries to specify pg_global, use pg_default instead.
1558  */
1559  if (tablespace == InvalidOid ||
1560  tablespace == DEFAULTTABLESPACE_OID ||
1561  tablespace == GLOBALTABLESPACE_OID)
1562  snprintf(path, MAXPGPATH, "base/%s", PG_TEMP_FILES_DIR);
1563  else
1564  {
1565  /* All other tablespaces are accessed via symlinks */
1566  snprintf(path, MAXPGPATH, "pg_tblspc/%u/%s/%s",
1569  }
1570 }
#define PG_TEMP_FILES_DIR
Definition: pg_checksums.c:58
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
char * tablespace
Definition: pgbench.c:189
#define InvalidOid
Definition: postgres_ext.h:36
#define snprintf
Definition: port.h:192

◆ TempTablespacesAreSet()

bool TempTablespacesAreSet ( void  )

Definition at line 2734 of file fd.c.

References numTempTableSpaces.

Referenced by GetTempTablespaces(), and PrepareTempTablespaces().

2735 {
2736  return (numTempTableSpaces >= 0);
2737 }
static int numTempTableSpaces
Definition: fd.c:257

◆ unlink_if_exists_fname()

static void unlink_if_exists_fname ( const char *  fname,
bool  isdir,
int  elevel 
)
static

Definition at line 3355 of file fd.c.

References ereport, errcode_for_file_access(), errmsg(), and PathNameDeleteTemporaryFile().

Referenced by PathNameDeleteTemporaryDir().

3356 {
3357  if (isdir)
3358  {
3359  if (rmdir(fname) != 0 && errno != ENOENT)
3360  ereport(elevel,
3362  errmsg("could not remove directory \"%s\": %m", fname)));
3363  }
3364  else
3365  {
3366  /* Use PathNameDeleteTemporaryFile to report filesize */
3367  PathNameDeleteTemporaryFile(fname, false);
3368  }
3369 }
bool PathNameDeleteTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1702
int errcode_for_file_access(void)
Definition: elog.c:631
#define ereport(elevel, rest)
Definition: elog.h:141
static int elevel
Definition: vacuumlazy.c:143
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ walkdir()

static void walkdir ( const char *  path,
void(*)(const char *fname, bool isdir, int elevel action,
bool  process_symlinks,
int  elevel 
)
static

Definition at line 3245 of file fd.c.

References generate_unaccent_rules::action, AllocateDir(), CHECK_FOR_INTERRUPTS, CloseTransientFile(), dirent::d_name, elevel, ereport, errcode_for_file_access(), errmsg(), vfd::fd, FreeDir(), lstat, MAXPGPATH, OpenTransientFile(), PG_BINARY, pg_flush_data(), ReadDirExtended(), S_ISDIR, S_ISREG, snprintf, stat, and subpath().

Referenced by PathNameDeleteTemporaryDir(), and SyncDataDirectory().

3249 {
3250  DIR *dir;
3251  struct dirent *de;
3252 
3253  dir = AllocateDir(path);
3254 
3255  while ((de = ReadDirExtended(dir, path, elevel)) != NULL)
3256  {
3257  char subpath[MAXPGPATH * 2];
3258  struct stat fst;
3259  int sret;
3260 
3262 
3263  if (strcmp(de->d_name, ".") == 0 ||
3264  strcmp(de->d_name, "..") == 0)
3265  continue;
3266 
3267  snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name);
3268 
3269  if (process_symlinks)
3270  sret = stat(subpath, &fst);
3271  else
3272  sret = lstat(subpath, &fst);
3273 
3274  if (sret < 0)
3275  {
3276  ereport(elevel,
3278  errmsg("could not stat file \"%s\": %m", subpath)));
3279  continue;
3280  }
3281 
3282  if (S_ISREG(fst.st_mode))
3283  (*action) (subpath, false, elevel);
3284  else if (S_ISDIR(fst.st_mode))
3285  walkdir(subpath, action, false, elevel);
3286  }
3287 
3288  FreeDir(dir); /* we ignore any error here */
3289 
3290  /*
3291  * It's important to fsync the destination directory itself as individual
3292  * file fsyncs don't guarantee that the directory entry for the file is
3293  * synced. However, skip this if AllocateDir failed; the action function
3294  * might not be robust against that.
3295  */
3296  if (dir)
3297  (*action) (path, true, elevel);
3298 }
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
Definition: fd.c:3245
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2584
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:631
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2503
#define ereport(elevel, rest)
Definition: elog.h:141
#define S_ISREG(m)
Definition: win32_port.h:299
#define stat(a, b)
Definition: win32_port.h:255
static int elevel
Definition: vacuumlazy.c:143
#define S_ISDIR(m)
Definition: win32_port.h:296
#define lstat(path, sb)
Definition: win32_port.h:244
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int FreeDir(DIR *dir)
Definition: fd.c:2621
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:241

Variable Documentation

◆ allocatedDescs

AllocateDesc* allocatedDescs = NULL
static

Definition at line 244 of file fd.c.

◆ data_sync_retry

bool data_sync_retry = false

Definition at line 148 of file fd.c.

Referenced by data_sync_elevel().

◆ have_xact_temporary_files

bool have_xact_temporary_files = false
static

Definition at line 208 of file fd.c.

Referenced by CleanupTempFiles(), and RegisterTemporaryFile().

◆ max_files_per_process

int max_files_per_process = 1000

Definition at line 132 of file fd.c.

Referenced by set_max_safe_fds().

◆ max_safe_fds

int max_safe_fds = 32

◆ maxAllocatedDescs

int maxAllocatedDescs = 0
static

◆ nextTempTableSpace

int nextTempTableSpace = 0
static

Definition at line 258 of file fd.c.

Referenced by GetNextTempTableSpace(), and SetTempTablespaces().

◆ nfile

int nfile = 0
static

◆ numAllocatedDescs

◆ numTempTableSpaces

int numTempTableSpaces = -1
static

◆ SizeVfdCache

Size SizeVfdCache = 0
static

Definition at line 197 of file fd.c.

Referenced by AllocateVfd(), CleanupTempFiles(), closeAllVfds(), and InitFileAccess().

◆ tempFileCounter

long tempFileCounter = 0
static

Definition at line 250 of file fd.c.

Referenced by OpenTemporaryFileInTablespace().

◆ temporary_files_size

uint64 temporary_files_size = 0
static

Definition at line 216 of file fd.c.

Referenced by FileClose(), FileTruncate(), and FileWrite().

◆ tempTableSpaces

Oid* tempTableSpaces = NULL
static

◆ VfdCache

Vfd* VfdCache
static

Definition at line 196 of file fd.c.