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 "miscadmin.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/pg_tablespace.h"
#include "common/file_perm.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 FileUnknownPos   ((off_t) -1)
 
#define FilePosIsUnknown(pos)   ((pos) < 0)
 
#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 isProcExit)
 
static void RemovePgTempFilesInDir (const char *tmpdirname, bool missing_ok, bool unlink_all)
 
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, uint32 wait_event_info)
 
int FileWrite (File file, char *buffer, int amount, uint32 wait_event_info)
 
int FileSync (File file, uint32 wait_event_info)
 
off_t FileSeek (File file, off_t offset, int whence)
 
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)
 
off_t FileGetSize (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 (void)
 
void RemovePgTempFiles (void)
 
bool looks_like_temp_rel_name (const char *name)
 
void SyncDataDirectory (void)
 
int MakePGDirectory (const char *directoryName)
 

Variables

int max_files_per_process = 1000
 
int max_safe_fds = 32
 
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 181 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 180 of file fd.c.

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

◆ FD_MINFREE

#define FD_MINFREE   10

Definition at line 125 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)

◆ FilePosIsUnknown

#define FilePosIsUnknown (   pos)    ((pos) < 0)

Definition at line 177 of file fd.c.

Referenced by FileRead(), FileSeek(), FileWrite(), and LruDelete().

◆ FileUnknownPos

#define FileUnknownPos   ((off_t) -1)

Definition at line 176 of file fd.c.

Referenced by FileRead(), and FileWrite().

◆ NUM_RESERVED_FDS

#define NUM_RESERVED_FDS   10

Definition at line 119 of file fd.c.

Referenced by set_max_safe_fds().

◆ VFD_CLOSED

#define VFD_CLOSED   (-1)

Definition at line 163 of file fd.c.

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

Typedef Documentation

◆ Vfd

typedef struct vfd Vfd

Enumeration Type Documentation

◆ AllocateDescKind

Enumerator
AllocateDescFile 
AllocateDescPipe 
AllocateDescDir 
AllocateDescRawFD 

Definition at line 231 of file fd.c.

Function Documentation

◆ AllocateDir()

DIR* AllocateDir ( const char *  dirname)

Definition at line 2600 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(), ReorderBufferCleanupSerializedTXNs(), ResetUnloggedRelations(), ResetUnloggedRelationsInDbspaceDir(), ResetUnloggedRelationsInTablespaceDir(), restoreTwoPhaseData(), scan_directory_ci(), sendDir(), SlruScanDirectory(), StartupReorderBuffer(), StartupReplicationSlots(), UpdateLogicalMappings(), and walkdir().

2601 {
2602  DIR *dir;
2603 
2604  DO_DB(elog(LOG, "AllocateDir: Allocated %d (%s)",
2605  numAllocatedDescs, dirname));
2606 
2607  /* Can we allocate another non-virtual FD? */
2608  if (!reserveAllocatedDesc())
2609  ereport(ERROR,
2610  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2611  errmsg("exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"",
2612  maxAllocatedDescs, dirname)));
2613 
2614  /* Close excess kernel FDs. */
2615  ReleaseLruFiles();
2616 
2617 TryAgain:
2618  if ((dir = opendir(dirname)) != NULL)
2619  {
2621 
2622  desc->kind = AllocateDescDir;
2623  desc->desc.dir = dir;
2626  return desc->desc.dir;
2627  }
2628 
2629  if (errno == EMFILE || errno == ENFILE)
2630  {
2631  int save_errno = errno;
2632 
2633  ereport(LOG,
2634  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2635  errmsg("out of file descriptors: %m; release and retry")));
2636  errno = 0;
2637  if (ReleaseLruFile())
2638  goto TryAgain;
2639  errno = save_errno;
2640  }
2641 
2642  return NULL;
2643 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
DIR * dir
Definition: fd.c:246
#define DO_DB(A)
Definition: fd.c:159
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool reserveAllocatedDesc(void)
Definition: fd.c:2273
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:241
static bool ReleaseLruFile(void)
Definition: fd.c:1158
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:122
static void ReleaseLruFiles(void)
Definition: fd.c:1180
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:641
SubTransactionId create_subid
Definition: fd.c:242
int errmsg(const char *fmt,...)
Definition: elog.c:797
union AllocateDesc::@27 desc
#define elog
Definition: elog.h:219
static int maxAllocatedDescs
Definition: fd.c:252
static int numAllocatedDescs
Definition: fd.c:251

◆ AllocateFile()

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

Definition at line 2346 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(), PGSharedMemoryIsInUse(), 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(), readRecoveryCommandFile(), readTimeLineHistory(), sendFile(), tokenize_inc_file(), tsearch_readline_begin(), ValidatePgVersion(), write_relcache_init_file(), XLogArchiveForceDone(), and XLogArchiveNotify().

2347 {
2348  FILE *file;
2349 
2350  DO_DB(elog(LOG, "AllocateFile: Allocated %d (%s)",
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 open file \"%s\"",
2358  maxAllocatedDescs, name)));
2359 
2360  /* Close excess kernel FDs. */
2361  ReleaseLruFiles();
2362 
2363 TryAgain:
2364  if ((file = fopen(name, mode)) != NULL)
2365  {
2367 
2368  desc->kind = AllocateDescFile;
2369  desc->desc.file = file;
2372  return desc->desc.file;
2373  }
2374 
2375  if (errno == EMFILE || errno == ENFILE)
2376  {
2377  int save_errno = errno;
2378 
2379  ereport(LOG,
2380  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2381  errmsg("out of file descriptors: %m; release and retry")));
2382  errno = 0;
2383  if (ReleaseLruFile())
2384  goto TryAgain;
2385  errno = save_errno;
2386  }
2387 
2388  return NULL;
2389 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
#define DO_DB(A)
Definition: fd.c:159
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool reserveAllocatedDesc(void)
Definition: fd.c:2273
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:241
static bool ReleaseLruFile(void)
Definition: fd.c:1158
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
static void ReleaseLruFiles(void)
Definition: fd.c:1180
FILE * file
Definition: fd.c:245
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:641
SubTransactionId create_subid
Definition: fd.c:242
const char * name
Definition: encode.c:521
int errmsg(const char *fmt,...)
Definition: elog.c:797
union AllocateDesc::@27 desc
#define elog
Definition: elog.h:219
static int maxAllocatedDescs
Definition: fd.c:252
static int numAllocatedDescs
Definition: fd.c:251

◆ AllocateVfd()

static File AllocateVfd ( void  )
static

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

1191 {
1192  Index i;
1193  File file;
1194 
1195  DO_DB(elog(LOG, "AllocateVfd. Size %zu", SizeVfdCache));
1196 
1197  Assert(SizeVfdCache > 0); /* InitFileAccess not called? */
1198 
1199  if (VfdCache[0].nextFree == 0)
1200  {
1201  /*
1202  * The free list is empty so it is time to increase the size of the
1203  * array. We choose to double it each time this happens. However,
1204  * there's not much point in starting *real* small.
1205  */
1206  Size newCacheSize = SizeVfdCache * 2;
1207  Vfd *newVfdCache;
1208 
1209  if (newCacheSize < 32)
1210  newCacheSize = 32;
1211 
1212  /*
1213  * Be careful not to clobber VfdCache ptr if realloc fails.
1214  */
1215  newVfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
1216  if (newVfdCache == NULL)
1217  ereport(ERROR,
1218  (errcode(ERRCODE_OUT_OF_MEMORY),
1219  errmsg("out of memory")));
1220  VfdCache = newVfdCache;
1221 
1222  /*
1223  * Initialize the new entries and link them into the free list.
1224  */
1225  for (i = SizeVfdCache; i < newCacheSize; i++)
1226  {
1227  MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
1228  VfdCache[i].nextFree = i + 1;
1229  VfdCache[i].fd = VFD_CLOSED;
1230  }
1231  VfdCache[newCacheSize - 1].nextFree = 0;
1233 
1234  /*
1235  * Record the new size
1236  */
1237  SizeVfdCache = newCacheSize;
1238  }
1239 
1240  file = VfdCache[0].nextFree;
1241 
1242  VfdCache[0].nextFree = VfdCache[file].nextFree;
1243 
1244  return file;
1245 }
File nextFree
Definition: fd.c:189
static Size SizeVfdCache
Definition: fd.c:206
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:908
#define LOG
Definition: elog.h:26
#define ERROR
Definition: elog.h:43
Definition: fd.c:184
int fd
Definition: fd.c:186
#define ereport(elevel, rest)
Definition: elog.h:122
unsigned int Index
Definition: c.h:442
#define VFD_CLOSED
Definition: fd.c:163
#define Assert(condition)
Definition: c.h:699
size_t Size
Definition: c.h:433
#define realloc(a, b)
Definition: header.h:60
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define elog
Definition: elog.h:219
int File
Definition: fd.h:49

◆ AtEOSubXact_Files()

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

Definition at line 2882 of file fd.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

2884 {
2885  Index i;
2886 
2887  for (i = 0; i < numAllocatedDescs; i++)
2888  {
2889  if (allocatedDescs[i].create_subid == mySubid)
2890  {
2891  if (isCommit)
2892  allocatedDescs[i].create_subid = parentSubid;
2893  else
2894  {
2895  /* have to recheck the item after FreeDesc (ugly) */
2896  FreeDesc(&allocatedDescs[i--]);
2897  }
2898  }
2899  }
2900 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2499
unsigned int Index
Definition: c.h:442
SubTransactionId create_subid
Definition: fd.c:242
int i
static int numAllocatedDescs
Definition: fd.c:251

◆ AtEOXact_Files()

void AtEOXact_Files ( void  )

Definition at line 2913 of file fd.c.

References CleanupTempFiles(), numTempTableSpaces, and tempTableSpaces.

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

2914 {
2915  CleanupTempFiles(false);
2916  tempTableSpaces = NULL;
2917  numTempTableSpaces = -1;
2918 }
static int numTempTableSpaces
Definition: fd.c:266
static void CleanupTempFiles(bool isProcExit)
Definition: fd.c:2942
static Oid * tempTableSpaces
Definition: fd.c:265

◆ AtProcExit_Files()

static void AtProcExit_Files ( int  code,
Datum  arg 
)
static

Definition at line 2927 of file fd.c.

References CleanupTempFiles().

Referenced by InitFileAccess().

2928 {
2929  CleanupTempFiles(true);
2930 }
static void CleanupTempFiles(bool isProcExit)
Definition: fd.c:2942

◆ BasicOpenFile()

int BasicOpenFile ( const char *  fileName,
int  fileFlags 
)

Definition at line 932 of file fd.c.

References BasicOpenFilePerm(), and pg_file_create_mode.

Referenced by AlterSystemSetConfigFile(), GetNewRelFileNode(), ReadControlFile(), UpdateControlFile(), WriteControlFile(), XLogFileInit(), XLogFileOpen(), XLogFileRead(), and XLogRead().

933 {
934  return BasicOpenFilePerm(fileName, fileFlags, pg_file_create_mode);
935 }
int pg_file_create_mode
Definition: file_perm.c:20
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:954

◆ BasicOpenFilePerm()

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

Definition at line 954 of file fd.c.

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

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

955 {
956  int fd;
957 
958 tryAgain:
959  fd = open(fileName, fileFlags, fileMode);
960 
961  if (fd >= 0)
962  return fd; /* success! */
963 
964  if (errno == EMFILE || errno == ENFILE)
965  {
966  int save_errno = errno;
967 
968  ereport(LOG,
969  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
970  errmsg("out of file descriptors: %m; release and retry")));
971  errno = 0;
972  if (ReleaseLruFile())
973  goto tryAgain;
974  errno = save_errno;
975  }
976 
977  return -1; /* failure */
978 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#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:1158
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ CleanupTempFiles()

static void CleanupTempFiles ( bool  isProcExit)
static

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

2943 {
2944  Index i;
2945 
2946  /*
2947  * Careful here: at proc_exit we need extra cleanup, not just
2948  * xact_temporary files.
2949  */
2950  if (isProcExit || have_xact_temporary_files)
2951  {
2952  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
2953  for (i = 1; i < SizeVfdCache; i++)
2954  {
2955  unsigned short fdstate = VfdCache[i].fdstate;
2956 
2957  if (((fdstate & FD_DELETE_AT_CLOSE) || (fdstate & FD_CLOSE_AT_EOXACT)) &&
2958  VfdCache[i].fileName != NULL)
2959  {
2960  /*
2961  * If we're in the process of exiting a backend process, close
2962  * all temporary files. Otherwise, only close temporary files
2963  * local to the current transaction. They should be closed by
2964  * the ResourceOwner mechanism already, so this is just a
2965  * debugging cross-check.
2966  */
2967  if (isProcExit)
2968  FileClose(i);
2969  else if (fdstate & FD_CLOSE_AT_EOXACT)
2970  {
2971  elog(WARNING,
2972  "temporary file %s not closed at end-of-transaction",
2973  VfdCache[i].fileName);
2974  FileClose(i);
2975  }
2976  }
2977  }
2978 
2979  have_xact_temporary_files = false;
2980  }
2981 
2982  /* Clean up "allocated" stdio files, dirs and fds. */
2983  while (numAllocatedDescs > 0)
2984  FreeDesc(&allocatedDescs[0]);
2985 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
static Size SizeVfdCache
Definition: fd.c:206
#define FD_DELETE_AT_CLOSE
Definition: fd.c:180
static Vfd * VfdCache
Definition: fd.c:205
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2499
static bool have_xact_temporary_files
Definition: fd.c:217
unsigned short fdstate
Definition: fd.c:187
#define WARNING
Definition: elog.h:40
#define FileIsNotOpen(file)
Definition: fd.c:168
unsigned int Index
Definition: c.h:442
void FileClose(File file)
Definition: fd.c:1742
#define Assert(condition)
Definition: c.h:699
int i
#define FD_CLOSE_AT_EOXACT
Definition: fd.c:181
#define elog
Definition: elog.h:219
static int numAllocatedDescs
Definition: fd.c:251

◆ closeAllVfds()

void closeAllVfds ( void  )

Definition at line 2777 of file fd.c.

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

Referenced by standard_ProcessUtility().

2778 {
2779  Index i;
2780 
2781  if (SizeVfdCache > 0)
2782  {
2783  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
2784  for (i = 1; i < SizeVfdCache; i++)
2785  {
2786  if (!FileIsNotOpen(i))
2787  LruDelete(i);
2788  }
2789  }
2790 }
static Size SizeVfdCache
Definition: fd.c:206
static void LruDelete(File file)
Definition: fd.c:1021
#define FileIsNotOpen(file)
Definition: fd.c:168
unsigned int Index
Definition: c.h:442
#define Assert(condition)
Definition: c.h:699
int i

◆ ClosePipeStream()

int ClosePipeStream ( FILE *  file)

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

2749 {
2750  int i;
2751 
2752  DO_DB(elog(LOG, "ClosePipeStream: Allocated %d", numAllocatedDescs));
2753 
2754  /* Remove file from list of allocated files, if it's present */
2755  for (i = numAllocatedDescs; --i >= 0;)
2756  {
2757  AllocateDesc *desc = &allocatedDescs[i];
2758 
2759  if (desc->kind == AllocateDescPipe && desc->desc.file == file)
2760  return FreeDesc(desc);
2761  }
2762 
2763  /* Only get here if someone passes us a file not in allocatedDescs */
2764  elog(WARNING, "file passed to ClosePipeStream was not obtained from OpenPipeStream");
2765 
2766  return pclose(file);
2767 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
#define DO_DB(A)
Definition: fd.c:159
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:241
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2499
#define WARNING
Definition: elog.h:40
FILE * file
Definition: fd.c:245
union AllocateDesc::@27 desc
int i
#define elog
Definition: elog.h:219
static int numAllocatedDescs
Definition: fd.c:251

◆ CloseTransientFile()

int CloseTransientFile ( int  fd)

Definition at line 2566 of file fd.c.

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

Referenced by be_lo_export(), CheckPointLogicalRewriteHeap(), CheckPointReplicationOrigin(), copy_file(), dsm_impl_mmap(), durable_rename(), fsync_fname_ext(), 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().

2567 {
2568  int i;
2569 
2570  DO_DB(elog(LOG, "CloseTransientFile: Allocated %d", numAllocatedDescs));
2571 
2572  /* Remove fd from list of allocated files, if it's present */
2573  for (i = numAllocatedDescs; --i >= 0;)
2574  {
2575  AllocateDesc *desc = &allocatedDescs[i];
2576 
2577  if (desc->kind == AllocateDescRawFD && desc->desc.fd == fd)
2578  return FreeDesc(desc);
2579  }
2580 
2581  /* Only get here if someone passes us a file not in allocatedDescs */
2582  elog(WARNING, "fd passed to CloseTransientFile was not obtained from OpenTransientFile");
2583 
2584  return close(fd);
2585 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
#define DO_DB(A)
Definition: fd.c:159
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:241
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2499
#define WARNING
Definition: elog.h:40
int fd
Definition: fd.c:247
union AllocateDesc::@27 desc
int i
#define elog
Definition: elog.h:219
#define close(a)
Definition: win32.h:12
static int numAllocatedDescs
Definition: fd.c:251

◆ count_usable_fds()

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

Definition at line 805 of file fd.c.

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

Referenced by set_max_safe_fds().

806 {
807  int *fd;
808  int size;
809  int used = 0;
810  int highestfd = 0;
811  int j;
812 
813 #ifdef HAVE_GETRLIMIT
814  struct rlimit rlim;
815  int getrlimit_status;
816 #endif
817 
818  size = 1024;
819  fd = (int *) palloc(size * sizeof(int));
820 
821 #ifdef HAVE_GETRLIMIT
822 #ifdef RLIMIT_NOFILE /* most platforms use RLIMIT_NOFILE */
823  getrlimit_status = getrlimit(RLIMIT_NOFILE, &rlim);
824 #else /* but BSD doesn't ... */
825  getrlimit_status = getrlimit(RLIMIT_OFILE, &rlim);
826 #endif /* RLIMIT_NOFILE */
827  if (getrlimit_status != 0)
828  ereport(WARNING, (errmsg("getrlimit failed: %m")));
829 #endif /* HAVE_GETRLIMIT */
830 
831  /* dup until failure or probe limit reached */
832  for (;;)
833  {
834  int thisfd;
835 
836 #ifdef HAVE_GETRLIMIT
837 
838  /*
839  * don't go beyond RLIMIT_NOFILE; causes irritating kernel logs on
840  * some platforms
841  */
842  if (getrlimit_status == 0 && highestfd >= rlim.rlim_cur - 1)
843  break;
844 #endif
845 
846  thisfd = dup(0);
847  if (thisfd < 0)
848  {
849  /* Expect EMFILE or ENFILE, else it's fishy */
850  if (errno != EMFILE && errno != ENFILE)
851  elog(WARNING, "dup(0) failed after %d successes: %m", used);
852  break;
853  }
854 
855  if (used >= size)
856  {
857  size *= 2;
858  fd = (int *) repalloc(fd, size * sizeof(int));
859  }
860  fd[used++] = thisfd;
861 
862  if (highestfd < thisfd)
863  highestfd = thisfd;
864 
865  if (used >= max_to_probe)
866  break;
867  }
868 
869  /* release the files we opened */
870  for (j = 0; j < used; j++)
871  close(fd[j]);
872 
873  pfree(fd);
874 
875  /*
876  * Return results. usable_fds is just the number of successful dups. We
877  * assume that the system limit is highestfd+1 (remember 0 is a legal FD
878  * number) and so already_open is highestfd+1 - usable_fds.
879  */
880  *usable_fds = used;
881  *already_open = highestfd + 1 - used;
882 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define close(a)
Definition: win32.h:12

◆ datadir_fsync_fname()

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

Definition at line 3426 of file fd.c.

References fsync_fname_ext().

Referenced by SyncDataDirectory().

3427 {
3428  /*
3429  * We want to silently ignoring errors about unreadable files. Pass that
3430  * desire on to fsync_fname_ext().
3431  */
3432  fsync_fname_ext(fname, isdir, true, elevel);
3433 }
static int elevel
Definition: vacuumlazy.c:144
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3461

◆ Delete()

static void Delete ( File  file)
static

Definition at line 1002 of file fd.c.

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

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

1003 {
1004  Vfd *vfdP;
1005 
1006  Assert(file != 0);
1007 
1008  DO_DB(elog(LOG, "Delete %d (%s)",
1009  file, VfdCache[file].fileName));
1010  DO_DB(_dump_lru());
1011 
1012  vfdP = &VfdCache[file];
1013 
1016 
1017  DO_DB(_dump_lru());
1018 }
File lruLessRecently
Definition: fd.c:191
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
#define LOG
Definition: elog.h:26
Definition: fd.c:184
#define Assert(condition)
Definition: c.h:699
File lruMoreRecently
Definition: fd.c:190
#define elog
Definition: elog.h:219

◆ durable_link_or_rename()

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

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

721 {
722  /*
723  * Ensure that, if we crash directly after the rename/link, a file with
724  * valid contents is moved into place.
725  */
726  if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
727  return -1;
728 
729 #if HAVE_WORKING_LINK
730  if (link(oldfile, newfile) < 0)
731  {
732  ereport(elevel,
734  errmsg("could not link file \"%s\" to \"%s\": %m",
735  oldfile, newfile)));
736  return -1;
737  }
738  unlink(oldfile);
739 #else
740  /* XXX: Add racy file existence check? */
741  if (rename(oldfile, newfile) < 0)
742  {
743  ereport(elevel,
745  errmsg("could not rename file \"%s\" to \"%s\": %m",
746  oldfile, newfile)));
747  return -1;
748  }
749 #endif
750 
751  /*
752  * Make change persistent in case of an OS crash, both the new entry and
753  * its parent directory need to be flushed.
754  */
755  if (fsync_fname_ext(newfile, false, false, elevel) != 0)
756  return -1;
757 
758  /* Same for parent directory */
759  if (fsync_parent_path(newfile, elevel) != 0)
760  return -1;
761 
762  return 0;
763 }
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
int link(const char *fromname, const char *toname)
static int elevel
Definition: vacuumlazy.c:144
int errmsg(const char *fmt,...)
Definition: elog.c:797
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3461
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3531

◆ durable_rename()

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

Definition at line 601 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(), exitArchiveRecovery(), KeepFileRestoredFromArchive(), pgarch_archiveDone(), pgss_shmem_shutdown(), StartupXLOG(), and XLogArchiveForceDone().

602 {
603  int fd;
604 
605  /*
606  * First fsync the old and target path (if it exists), to ensure that they
607  * are properly persistent on disk. Syncing the target file is not
608  * strictly necessary, but it makes it easier to reason about crashes;
609  * because it's then guaranteed that either source or target file exists
610  * after a crash.
611  */
612  if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
613  return -1;
614 
615  fd = OpenTransientFile(newfile, PG_BINARY | O_RDWR);
616  if (fd < 0)
617  {
618  if (errno != ENOENT)
619  {
620  ereport(elevel,
622  errmsg("could not open file \"%s\": %m", newfile)));
623  return -1;
624  }
625  }
626  else
627  {
628  if (pg_fsync(fd) != 0)
629  {
630  int save_errno;
631 
632  /* close file upon error, might not be in transaction context */
633  save_errno = errno;
634  CloseTransientFile(fd);
635  errno = save_errno;
636 
637  ereport(elevel,
639  errmsg("could not fsync file \"%s\": %m", newfile)));
640  return -1;
641  }
642  CloseTransientFile(fd);
643  }
644 
645  /* Time to do the real deal... */
646  if (rename(oldfile, newfile) < 0)
647  {
648  ereport(elevel,
650  errmsg("could not rename file \"%s\" to \"%s\": %m",
651  oldfile, newfile)));
652  return -1;
653  }
654 
655  /*
656  * To guarantee renaming the file is persistent, fsync the file with its
657  * new name, and its containing directory.
658  */
659  if (fsync_fname_ext(newfile, false, false, elevel) != 0)
660  return -1;
661 
662  if (fsync_parent_path(newfile, elevel) != 0)
663  return -1;
664 
665  return 0;
666 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1080
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2396
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
int CloseTransientFile(int fd)
Definition: fd.c:2566
static int elevel
Definition: vacuumlazy.c:144
int errmsg(const char *fmt,...)
Definition: elog.c:797
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3461
int pg_fsync(int fd)
Definition: fd.c:341
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3531

◆ durable_unlink()

int durable_unlink ( const char *  fname,
int  elevel 
)

Definition at line 684 of file fd.c.

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

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

685 {
686  if (unlink(fname) < 0)
687  {
688  ereport(elevel,
690  errmsg("could not remove file \"%s\": %m",
691  fname)));
692  return -1;
693  }
694 
695  /*
696  * To guarantee that the removal of the file is persistent, fsync its
697  * parent directory.
698  */
699  if (fsync_parent_path(fname, elevel) != 0)
700  return -1;
701 
702  return 0;
703 }
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
static int elevel
Definition: vacuumlazy.c:144
int errmsg(const char *fmt,...)
Definition: elog.c:797
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3531

◆ FileAccess()

static int FileAccess ( File  file)
static

Definition at line 1268 of file fd.c.

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

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

1269 {
1270  int returnValue;
1271 
1272  DO_DB(elog(LOG, "FileAccess %d (%s)",
1273  file, VfdCache[file].fileName));
1274 
1275  /*
1276  * Is the file open? If not, open it and put it at the head of the LRU
1277  * ring (possibly closing the least recently used file to get an FD).
1278  */
1279 
1280  if (FileIsNotOpen(file))
1281  {
1282  returnValue = LruInsert(file);
1283  if (returnValue != 0)
1284  return returnValue;
1285  }
1286  else if (VfdCache[0].lruLessRecently != file)
1287  {
1288  /*
1289  * We now know that the file is open and that it is not the last one
1290  * accessed, so we need to move it to the head of the Lru ring.
1291  */
1292 
1293  Delete(file);
1294  Insert(file);
1295  }
1296 
1297  return 0;
1298 }
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
static void Delete(File file)
Definition: fd.c:1002
#define LOG
Definition: elog.h:26
static int LruInsert(File file)
Definition: fd.c:1084
static void Insert(File file)
Definition: fd.c:1062
#define FileIsNotOpen(file)
Definition: fd.c:168
#define elog
Definition: elog.h:219

◆ FileClose()

void FileClose ( File  file)

Definition at line 1742 of file fd.c.

References Assert, close, 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(), mdtruncate(), and ResourceOwnerReleaseInternal().

1743 {
1744  Vfd *vfdP;
1745 
1746  Assert(FileIsValid(file));
1747 
1748  DO_DB(elog(LOG, "FileClose: %d (%s)",
1749  file, VfdCache[file].fileName));
1750 
1751  vfdP = &VfdCache[file];
1752 
1753  if (!FileIsNotOpen(file))
1754  {
1755  /* close the file */
1756  if (close(vfdP->fd))
1757  elog(LOG, "could not close file \"%s\": %m", vfdP->fileName);
1758 
1759  --nfile;
1760  vfdP->fd = VFD_CLOSED;
1761 
1762  /* remove the file from the lru ring */
1763  Delete(file);
1764  }
1765 
1766  if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
1767  {
1768  /* Subtract its size from current usage (do first in case of error) */
1769  temporary_files_size -= vfdP->fileSize;
1770  vfdP->fileSize = 0;
1771  }
1772 
1773  /*
1774  * Delete the file if it was temporary, and make a log entry if wanted
1775  */
1776  if (vfdP->fdstate & FD_DELETE_AT_CLOSE)
1777  {
1778  struct stat filestats;
1779  int stat_errno;
1780 
1781  /*
1782  * If we get an error, as could happen within the ereport/elog calls,
1783  * we'll come right back here during transaction abort. Reset the
1784  * flag to ensure that we can't get into an infinite loop. This code
1785  * is arranged to ensure that the worst-case consequence is failing to
1786  * emit log message(s), not failing to attempt the unlink.
1787  */
1788  vfdP->fdstate &= ~FD_DELETE_AT_CLOSE;
1789 
1790 
1791  /* first try the stat() */
1792  if (stat(vfdP->fileName, &filestats))
1793  stat_errno = errno;
1794  else
1795  stat_errno = 0;
1796 
1797  /* in any case do the unlink */
1798  if (unlink(vfdP->fileName))
1799  elog(LOG, "could not unlink file \"%s\": %m", vfdP->fileName);
1800 
1801  /* and last report the stat results */
1802  if (stat_errno == 0)
1803  ReportTemporaryFileUsage(vfdP->fileName, filestats.st_size);
1804  else
1805  {
1806  errno = stat_errno;
1807  elog(LOG, "could not stat file \"%s\": %m", vfdP->fileName);
1808  }
1809  }
1810 
1811  /* Unregister it from the resource owner */
1812  if (vfdP->resowner)
1813  ResourceOwnerForgetFile(vfdP->resowner, file);
1814 
1815  /*
1816  * Return the Vfd slot to the free list
1817  */
1818  FreeVfd(file);
1819 }
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:182
#define DO_DB(A)
Definition: fd.c:159
#define FD_DELETE_AT_CLOSE
Definition: fd.c:180
static Vfd * VfdCache
Definition: fd.c:205
static void Delete(File file)
Definition: fd.c:1002
#define LOG
Definition: elog.h:26
char * fileName
Definition: fd.c:194
static int nfile
Definition: fd.c:211
unsigned short fdstate
Definition: fd.c:187
Definition: fd.c:184
off_t fileSize
Definition: fd.c:193
int fd
Definition: fd.c:186
ResourceOwner resowner
Definition: fd.c:188
static void ReportTemporaryFileUsage(const char *path, off_t size)
Definition: fd.c:1304
#define stat(a, b)
Definition: win32_port.h:266
#define FileIsNotOpen(file)
Definition: fd.c:168
#define FileIsValid(file)
Definition: fd.c:165
#define VFD_CLOSED
Definition: fd.c:163
static uint64 temporary_files_size
Definition: fd.c:225
#define Assert(condition)
Definition: c.h:699
static void FreeVfd(File file)
Definition: fd.c:1248
#define elog
Definition: elog.h:219
#define close(a)
Definition: win32.h:12
void ResourceOwnerForgetFile(ResourceOwner owner, File file)
Definition: resowner.c:1208

◆ FileGetRawDesc()

int FileGetRawDesc ( File  file)

Definition at line 2232 of file fd.c.

References Assert, vfd::fd, and FileIsValid.

2233 {
2234  Assert(FileIsValid(file));
2235  return VfdCache[file].fd;
2236 }
static Vfd * VfdCache
Definition: fd.c:205
int fd
Definition: fd.c:186
#define FileIsValid(file)
Definition: fd.c:165
#define Assert(condition)
Definition: c.h:699

◆ FileGetRawFlags()

int FileGetRawFlags ( File  file)

Definition at line 2242 of file fd.c.

References Assert, vfd::fileFlags, and FileIsValid.

2243 {
2244  Assert(FileIsValid(file));
2245  return VfdCache[file].fileFlags;
2246 }
static Vfd * VfdCache
Definition: fd.c:205
#define FileIsValid(file)
Definition: fd.c:165
#define Assert(condition)
Definition: c.h:699
int fileFlags
Definition: fd.c:196

◆ FileGetRawMode()

mode_t FileGetRawMode ( File  file)

Definition at line 2252 of file fd.c.

References Assert, FileIsValid, and vfd::fileMode.

2253 {
2254  Assert(FileIsValid(file));
2255  return VfdCache[file].fileMode;
2256 }
static Vfd * VfdCache
Definition: fd.c:205
mode_t fileMode
Definition: fd.c:197
#define FileIsValid(file)
Definition: fd.c:165
#define Assert(condition)
Definition: c.h:699

◆ FileGetSize()

off_t FileGetSize ( File  file)

Definition at line 2262 of file fd.c.

References Assert, FileIsValid, and vfd::fileSize.

Referenced by BufFileSize().

2263 {
2264  Assert(FileIsValid(file));
2265  return VfdCache[file].fileSize;
2266 }
static Vfd * VfdCache
Definition: fd.c:205
off_t fileSize
Definition: fd.c:193
#define FileIsValid(file)
Definition: fd.c:165
#define Assert(condition)
Definition: c.h:699

◆ FilePathName()

char* FilePathName ( File  file)

Definition at line 2216 of file fd.c.

References Assert, FileIsValid, and vfd::fileName.

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

2217 {
2218  Assert(FileIsValid(file));
2219 
2220  return VfdCache[file].fileName;
2221 }
static Vfd * VfdCache
Definition: fd.c:205
char * fileName
Definition: fd.c:194
#define FileIsValid(file)
Definition: fd.c:165
#define Assert(condition)
Definition: c.h:699

◆ FilePrefetch()

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

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

1833 {
1834 #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
1835  int returnCode;
1836 
1837  Assert(FileIsValid(file));
1838 
1839  DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " %d",
1840  file, VfdCache[file].fileName,
1841  (int64) offset, amount));
1842 
1843  returnCode = FileAccess(file);
1844  if (returnCode < 0)
1845  return returnCode;
1846 
1847  pgstat_report_wait_start(wait_event_info);
1848  returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
1849  POSIX_FADV_WILLNEED);
1851 
1852  return returnCode;
1853 #else
1854  Assert(FileIsValid(file));
1855  return 0;
1856 #endif
1857 }
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
#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:1260
#define FileIsValid(file)
Definition: fd.c:165
static int FileAccess(File file)
Definition: fd.c:1268
#define Assert(condition)
Definition: c.h:699
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
#define INT64_FORMAT
Definition: c.h:367
#define elog
Definition: elog.h:219

◆ FileRead()

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

Definition at line 1887 of file fd.c.

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

Referenced by BufFileLoadBuffer(), and mdread().

1888 {
1889  int returnCode;
1890  Vfd *vfdP;
1891 
1892  Assert(FileIsValid(file));
1893 
1894  DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p",
1895  file, VfdCache[file].fileName,
1896  (int64) VfdCache[file].seekPos,
1897  amount, buffer));
1898 
1899  returnCode = FileAccess(file);
1900  if (returnCode < 0)
1901  return returnCode;
1902 
1903  vfdP = &VfdCache[file];
1904 
1905 retry:
1906  pgstat_report_wait_start(wait_event_info);
1907  returnCode = read(vfdP->fd, buffer, amount);
1909 
1910  if (returnCode >= 0)
1911  {
1912  /* if seekPos is unknown, leave it that way */
1913  if (!FilePosIsUnknown(vfdP->seekPos))
1914  vfdP->seekPos += returnCode;
1915  }
1916  else
1917  {
1918  /*
1919  * Windows may run out of kernel buffers and return "Insufficient
1920  * system resources" error. Wait a bit and retry to solve it.
1921  *
1922  * It is rumored that EINTR is also possible on some Unix filesystems,
1923  * in which case immediate retry is indicated.
1924  */
1925 #ifdef WIN32
1926  DWORD error = GetLastError();
1927 
1928  switch (error)
1929  {
1930  case ERROR_NO_SYSTEM_RESOURCES:
1931  pg_usleep(1000L);
1932  errno = EINTR;
1933  break;
1934  default:
1935  _dosmaperr(error);
1936  break;
1937  }
1938 #endif
1939  /* OK to retry if interrupted */
1940  if (errno == EINTR)
1941  goto retry;
1942 
1943  /* Trouble, so assume we don't know the file position anymore */
1944  vfdP->seekPos = FileUnknownPos;
1945  }
1946 
1947  return returnCode;
1948 }
static void error(void)
Definition: sql-dyntest.c:147
#define DO_DB(A)
Definition: fd.c:159
void _dosmaperr(unsigned long)
Definition: win32error.c:171
static Vfd * VfdCache
Definition: fd.c:205
#define LOG
Definition: elog.h:26
#define FilePosIsUnknown(pos)
Definition: fd.c:177
void pg_usleep(long microsec)
Definition: signal.c:53
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1260
off_t seekPos
Definition: fd.c:192
Definition: fd.c:184
int fd
Definition: fd.c:186
#define FileIsValid(file)
Definition: fd.c:165
static int FileAccess(File file)
Definition: fd.c:1268
#define Assert(condition)
Definition: c.h:699
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
#define INT64_FORMAT
Definition: c.h:367
#define elog
Definition: elog.h:219
#define EINTR
Definition: win32_port.h:334
#define FileUnknownPos
Definition: fd.c:176
#define read(a, b, c)
Definition: win32.h:13

◆ FileSeek()

off_t FileSeek ( File  file,
off_t  offset,
int  whence 
)

Definition at line 2093 of file fd.c.

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

Referenced by _mdnblocks(), BufFileDumpBuffer(), BufFileLoadBuffer(), mdextend(), mdread(), and mdwrite().

2094 {
2095  Vfd *vfdP;
2096 
2097  Assert(FileIsValid(file));
2098 
2099  DO_DB(elog(LOG, "FileSeek: %d (%s) " INT64_FORMAT " " INT64_FORMAT " %d",
2100  file, VfdCache[file].fileName,
2101  (int64) VfdCache[file].seekPos,
2102  (int64) offset, whence));
2103 
2104  vfdP = &VfdCache[file];
2105 
2106  if (FileIsNotOpen(file))
2107  {
2108  switch (whence)
2109  {
2110  case SEEK_SET:
2111  if (offset < 0)
2112  {
2113  errno = EINVAL;
2114  return (off_t) -1;
2115  }
2116  vfdP->seekPos = offset;
2117  break;
2118  case SEEK_CUR:
2119  if (FilePosIsUnknown(vfdP->seekPos) ||
2120  vfdP->seekPos + offset < 0)
2121  {
2122  errno = EINVAL;
2123  return (off_t) -1;
2124  }
2125  vfdP->seekPos += offset;
2126  break;
2127  case SEEK_END:
2128  if (FileAccess(file) < 0)
2129  return (off_t) -1;
2130  vfdP->seekPos = lseek(vfdP->fd, offset, whence);
2131  break;
2132  default:
2133  elog(ERROR, "invalid whence: %d", whence);
2134  break;
2135  }
2136  }
2137  else
2138  {
2139  switch (whence)
2140  {
2141  case SEEK_SET:
2142  if (offset < 0)
2143  {
2144  errno = EINVAL;
2145  return (off_t) -1;
2146  }
2147  if (vfdP->seekPos != offset)
2148  vfdP->seekPos = lseek(vfdP->fd, offset, whence);
2149  break;
2150  case SEEK_CUR:
2151  if (offset != 0 || FilePosIsUnknown(vfdP->seekPos))
2152  vfdP->seekPos = lseek(vfdP->fd, offset, whence);
2153  break;
2154  case SEEK_END:
2155  vfdP->seekPos = lseek(vfdP->fd, offset, whence);
2156  break;
2157  default:
2158  elog(ERROR, "invalid whence: %d", whence);
2159  break;
2160  }
2161  }
2162 
2163  return vfdP->seekPos;
2164 }
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
#define LOG
Definition: elog.h:26
#define FilePosIsUnknown(pos)
Definition: fd.c:177
#define ERROR
Definition: elog.h:43
off_t seekPos
Definition: fd.c:192
Definition: fd.c:184
int fd
Definition: fd.c:186
#define FileIsNotOpen(file)
Definition: fd.c:168
#define FileIsValid(file)
Definition: fd.c:165
static int FileAccess(File file)
Definition: fd.c:1268
#define Assert(condition)
Definition: c.h:699
#define INT64_FORMAT
Definition: c.h:367
#define elog
Definition: elog.h:219

◆ FileSync()

int FileSync ( File  file,
uint32  wait_event_info 
)

Definition at line 2072 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(), mdsync(), and register_dirty_segment().

2073 {
2074  int returnCode;
2075 
2076  Assert(FileIsValid(file));
2077 
2078  DO_DB(elog(LOG, "FileSync: %d (%s)",
2079  file, VfdCache[file].fileName));
2080 
2081  returnCode = FileAccess(file);
2082  if (returnCode < 0)
2083  return returnCode;
2084 
2085  pgstat_report_wait_start(wait_event_info);
2086  returnCode = pg_fsync(VfdCache[file].fd);
2088 
2089  return returnCode;
2090 }
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
#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:1260
#define FileIsValid(file)
Definition: fd.c:165
static int FileAccess(File file)
Definition: fd.c:1268
#define Assert(condition)
Definition: c.h:699
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
int pg_fsync(int fd)
Definition: fd.c:341
#define elog
Definition: elog.h:219

◆ FileTruncate()

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

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

2182 {
2183  int returnCode;
2184 
2185  Assert(FileIsValid(file));
2186 
2187  DO_DB(elog(LOG, "FileTruncate %d (%s)",
2188  file, VfdCache[file].fileName));
2189 
2190  returnCode = FileAccess(file);
2191  if (returnCode < 0)
2192  return returnCode;
2193 
2194  pgstat_report_wait_start(wait_event_info);
2195  returnCode = ftruncate(VfdCache[file].fd, offset);
2197 
2198  if (returnCode == 0 && VfdCache[file].fileSize > offset)
2199  {
2200  /* adjust our state for truncation of a temp file */
2201  Assert(VfdCache[file].fdstate & FD_TEMP_FILE_LIMIT);
2202  temporary_files_size -= VfdCache[file].fileSize - offset;
2203  VfdCache[file].fileSize = offset;
2204  }
2205 
2206  return returnCode;
2207 }
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:182
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
#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:1260
off_t fileSize
Definition: fd.c:193
#define FileIsValid(file)
Definition: fd.c:165
static uint64 temporary_files_size
Definition: fd.c:225
static int FileAccess(File file)
Definition: fd.c:1268
#define Assert(condition)
Definition: c.h:699
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
#define elog
Definition: elog.h:219
#define ftruncate(a, b)
Definition: win32_port.h:60

◆ FileWrite()

int FileWrite ( File  file,
char *  buffer,
int  amount,
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, FilePosIsUnknown, vfd::fileSize, FileUnknownPos, INT64_FORMAT, LOG, pg_usleep(), pgstat_report_wait_end(), pgstat_report_wait_start(), vfd::seekPos, temp_file_limit, temporary_files_size, and write.

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

1952 {
1953  int returnCode;
1954  Vfd *vfdP;
1955 
1956  Assert(FileIsValid(file));
1957 
1958  DO_DB(elog(LOG, "FileWrite: %d (%s) " INT64_FORMAT " %d %p",
1959  file, VfdCache[file].fileName,
1960  (int64) VfdCache[file].seekPos,
1961  amount, buffer));
1962 
1963  returnCode = FileAccess(file);
1964  if (returnCode < 0)
1965  return returnCode;
1966 
1967  vfdP = &VfdCache[file];
1968 
1969  /*
1970  * If enforcing temp_file_limit and it's a temp file, check to see if the
1971  * write would overrun temp_file_limit, and throw error if so. Note: it's
1972  * really a modularity violation to throw error here; we should set errno
1973  * and return -1. However, there's no way to report a suitable error
1974  * message if we do that. All current callers would just throw error
1975  * immediately anyway, so this is safe at present.
1976  */
1977  if (temp_file_limit >= 0 && (vfdP->fdstate & FD_TEMP_FILE_LIMIT))
1978  {
1979  off_t newPos;
1980 
1981  /*
1982  * Normally we should know the seek position, but if for some reason
1983  * we have lost track of it, try again to get it. Here, it's fine to
1984  * throw an error if we still can't get it.
1985  */
1986  if (FilePosIsUnknown(vfdP->seekPos))
1987  {
1988  vfdP->seekPos = lseek(vfdP->fd, (off_t) 0, SEEK_CUR);
1989  if (FilePosIsUnknown(vfdP->seekPos))
1990  elog(ERROR, "could not seek file \"%s\": %m", vfdP->fileName);
1991  }
1992 
1993  newPos = vfdP->seekPos + amount;
1994  if (newPos > vfdP->fileSize)
1995  {
1996  uint64 newTotal = temporary_files_size;
1997 
1998  newTotal += newPos - vfdP->fileSize;
1999  if (newTotal > (uint64) temp_file_limit * (uint64) 1024)
2000  ereport(ERROR,
2001  (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
2002  errmsg("temporary file size exceeds temp_file_limit (%dkB)",
2003  temp_file_limit)));
2004  }
2005  }
2006 
2007 retry:
2008  errno = 0;
2009  pgstat_report_wait_start(wait_event_info);
2010  returnCode = write(vfdP->fd, buffer, amount);
2012 
2013  /* if write didn't set errno, assume problem is no disk space */
2014  if (returnCode != amount && errno == 0)
2015  errno = ENOSPC;
2016 
2017  if (returnCode >= 0)
2018  {
2019  /* if seekPos is unknown, leave it that way */
2020  if (!FilePosIsUnknown(vfdP->seekPos))
2021  vfdP->seekPos += returnCode;
2022 
2023  /*
2024  * Maintain fileSize and temporary_files_size if it's a temp file.
2025  *
2026  * If seekPos is -1 (unknown), this will do nothing; but we could only
2027  * get here in that state if we're not enforcing temporary_files_size,
2028  * so we don't care.
2029  */
2030  if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
2031  {
2032  off_t newPos = vfdP->seekPos;
2033 
2034  if (newPos > vfdP->fileSize)
2035  {
2036  temporary_files_size += newPos - vfdP->fileSize;
2037  vfdP->fileSize = newPos;
2038  }
2039  }
2040  }
2041  else
2042  {
2043  /*
2044  * See comments in FileRead()
2045  */
2046 #ifdef WIN32
2047  DWORD error = GetLastError();
2048 
2049  switch (error)
2050  {
2051  case ERROR_NO_SYSTEM_RESOURCES:
2052  pg_usleep(1000L);
2053  errno = EINTR;
2054  break;
2055  default:
2056  _dosmaperr(error);
2057  break;
2058  }
2059 #endif
2060  /* OK to retry if interrupted */
2061  if (errno == EINTR)
2062  goto retry;
2063 
2064  /* Trouble, so assume we don't know the file position anymore */
2065  vfdP->seekPos = FileUnknownPos;
2066  }
2067 
2068  return returnCode;
2069 }
static void error(void)
Definition: sql-dyntest.c:147
#define write(a, b, c)
Definition: win32.h:14
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:182
#define DO_DB(A)
Definition: fd.c:159
void _dosmaperr(unsigned long)
Definition: win32error.c:171
static Vfd * VfdCache
Definition: fd.c:205
int errcode(int sqlerrcode)
Definition: elog.c:575
#define LOG
Definition: elog.h:26
#define FilePosIsUnknown(pos)
Definition: fd.c:177
void pg_usleep(long microsec)
Definition: signal.c:53
#define ERROR
Definition: elog.h:43
char * fileName
Definition: fd.c:194
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1260
off_t seekPos
Definition: fd.c:192
unsigned short fdstate
Definition: fd.c:187
Definition: fd.c:184
off_t fileSize
Definition: fd.c:193
int fd
Definition: fd.c:186
#define ereport(elevel, rest)
Definition: elog.h:122
#define FileIsValid(file)
Definition: fd.c:165
static uint64 temporary_files_size
Definition: fd.c:225
static int FileAccess(File file)
Definition: fd.c:1268
#define Assert(condition)
Definition: c.h:699
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
#define INT64_FORMAT
Definition: c.h:367
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define EINTR
Definition: win32_port.h:334
#define FileUnknownPos
Definition: fd.c:176
int temp_file_limit
Definition: guc.c:460

◆ FileWriteback()

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

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

1861 {
1862  int returnCode;
1863 
1864  Assert(FileIsValid(file));
1865 
1866  DO_DB(elog(LOG, "FileWriteback: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
1867  file, VfdCache[file].fileName,
1868  (int64) offset, (int64) nbytes));
1869 
1870  /*
1871  * Caution: do not call pg_flush_data with nbytes = 0, it could trash the
1872  * file's seek position. We prefer to define that as a no-op here.
1873  */
1874  if (nbytes <= 0)
1875  return;
1876 
1877  returnCode = FileAccess(file);
1878  if (returnCode < 0)
1879  return;
1880 
1881  pgstat_report_wait_start(wait_event_info);
1882  pg_flush_data(VfdCache[file].fd, offset, nbytes);
1884 }
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
#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:1260
void pg_flush_data(int fd, off_t offset, off_t nbytes)
Definition: fd.c:415
#define FileIsValid(file)
Definition: fd.c:165
static int FileAccess(File file)
Definition: fd.c:1268
#define Assert(condition)
Definition: c.h:699
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
#define INT64_FORMAT
Definition: c.h:367
#define elog
Definition: elog.h:219

◆ FreeDesc()

static int FreeDesc ( AllocateDesc desc)
static

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

2500 {
2501  int result;
2502 
2503  /* Close the underlying object */
2504  switch (desc->kind)
2505  {
2506  case AllocateDescFile:
2507  result = fclose(desc->desc.file);
2508  break;
2509  case AllocateDescPipe:
2510  result = pclose(desc->desc.file);
2511  break;
2512  case AllocateDescDir:
2513  result = closedir(desc->desc.dir);
2514  break;
2515  case AllocateDescRawFD:
2516  result = close(desc->desc.fd);
2517  break;
2518  default:
2519  elog(ERROR, "AllocateDesc kind not recognized");
2520  result = 0; /* keep compiler quiet */
2521  break;
2522  }
2523 
2524  /* Compact storage in the allocatedDescs array */
2527 
2528  return result;
2529 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
DIR * dir
Definition: fd.c:246
int closedir(DIR *)
Definition: dirent.c:111
AllocateDescKind kind
Definition: fd.c:241
#define ERROR
Definition: elog.h:43
FILE * file
Definition: fd.c:245
int fd
Definition: fd.c:247
union AllocateDesc::@27 desc
#define elog
Definition: elog.h:219
#define close(a)
Definition: win32.h:12
static int numAllocatedDescs
Definition: fd.c:251

◆ FreeDir()

int FreeDir ( DIR dir)

Definition at line 2718 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(), ReorderBufferCleanupSerializedTXNs(), ResetUnloggedRelations(), ResetUnloggedRelationsInDbspaceDir(), ResetUnloggedRelationsInTablespaceDir(), restoreTwoPhaseData(), scan_directory_ci(), sendDir(), SlruScanDirectory(), StartupReorderBuffer(), StartupReplicationSlots(), UpdateLogicalMappings(), and walkdir().

2719 {
2720  int i;
2721 
2722  /* Nothing to do if AllocateDir failed */
2723  if (dir == NULL)
2724  return 0;
2725 
2726  DO_DB(elog(LOG, "FreeDir: Allocated %d", numAllocatedDescs));
2727 
2728  /* Remove dir from list of allocated dirs, if it's present */
2729  for (i = numAllocatedDescs; --i >= 0;)
2730  {
2731  AllocateDesc *desc = &allocatedDescs[i];
2732 
2733  if (desc->kind == AllocateDescDir && desc->desc.dir == dir)
2734  return FreeDesc(desc);
2735  }
2736 
2737  /* Only get here if someone passes us a dir not in allocatedDescs */
2738  elog(WARNING, "dir passed to FreeDir was not obtained from AllocateDir");
2739 
2740  return closedir(dir);
2741 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
DIR * dir
Definition: fd.c:246
#define DO_DB(A)
Definition: fd.c:159
int closedir(DIR *)
Definition: dirent.c:111
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:241
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2499
#define WARNING
Definition: elog.h:40
union AllocateDesc::@27 desc
int i
#define elog
Definition: elog.h:219
static int numAllocatedDescs
Definition: fd.c:251

◆ FreeFile()

int FreeFile ( FILE *  file)

Definition at line 2538 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(), PGSharedMemoryIsInUse(), 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(), readRecoveryCommandFile(), readTimeLineHistory(), sendFile(), tokenize_inc_file(), tsearch_readline_end(), ValidatePgVersion(), write_relcache_init_file(), XLogArchiveForceDone(), and XLogArchiveNotify().

2539 {
2540  int i;
2541 
2542  DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedDescs));
2543 
2544  /* Remove file from list of allocated files, if it's present */
2545  for (i = numAllocatedDescs; --i >= 0;)
2546  {
2547  AllocateDesc *desc = &allocatedDescs[i];
2548 
2549  if (desc->kind == AllocateDescFile && desc->desc.file == file)
2550  return FreeDesc(desc);
2551  }
2552 
2553  /* Only get here if someone passes us a file not in allocatedDescs */
2554  elog(WARNING, "file passed to FreeFile was not obtained from AllocateFile");
2555 
2556  return fclose(file);
2557 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
#define DO_DB(A)
Definition: fd.c:159
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:241
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2499
#define WARNING
Definition: elog.h:40
FILE * file
Definition: fd.c:245
union AllocateDesc::@27 desc
int i
#define elog
Definition: elog.h:219
static int numAllocatedDescs
Definition: fd.c:251

◆ FreeVfd()

static void FreeVfd ( File  file)
static

Definition at line 1248 of file fd.c.

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

Referenced by FileClose(), and PathNameOpenFilePerm().

1249 {
1250  Vfd *vfdP = &VfdCache[file];
1251 
1252  DO_DB(elog(LOG, "FreeVfd: %d (%s)",
1253  file, vfdP->fileName ? vfdP->fileName : ""));
1254 
1255  if (vfdP->fileName != NULL)
1256  {
1257  free(vfdP->fileName);
1258  vfdP->fileName = NULL;
1259  }
1260  vfdP->fdstate = 0x0;
1261 
1262  vfdP->nextFree = VfdCache[0].nextFree;
1263  VfdCache[0].nextFree = file;
1264 }
File nextFree
Definition: fd.c:189
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
#define LOG
Definition: elog.h:26
char * fileName
Definition: fd.c:194
unsigned short fdstate
Definition: fd.c:187
Definition: fd.c:184
#define free(a)
Definition: header.h:65
#define elog
Definition: elog.h:219

◆ fsync_fname()

void fsync_fname ( const char *  fname,
bool  isdir 
)

◆ fsync_fname_ext()

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

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

3462 {
3463  int fd;
3464  int flags;
3465  int returncode;
3466 
3467  /*
3468  * Some OSs require directories to be opened read-only whereas other
3469  * systems don't allow us to fsync files opened read-only; so we need both
3470  * cases here. Using O_RDWR will cause us to fail to fsync files that are
3471  * not writable by our userid, but we assume that's OK.
3472  */
3473  flags = PG_BINARY;
3474  if (!isdir)
3475  flags |= O_RDWR;
3476  else
3477  flags |= O_RDONLY;
3478 
3479  fd = OpenTransientFile(fname, flags);
3480 
3481  /*
3482  * Some OSs don't allow us to open directories at all (Windows returns
3483  * EACCES), just ignore the error in that case. If desired also silently
3484  * ignoring errors about unreadable files. Log others.
3485  */
3486  if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
3487  return 0;
3488  else if (fd < 0 && ignore_perm && errno == EACCES)
3489  return 0;
3490  else if (fd < 0)
3491  {
3492  ereport(elevel,
3494  errmsg("could not open file \"%s\": %m", fname)));
3495  return -1;
3496  }
3497 
3498  returncode = pg_fsync(fd);
3499 
3500  /*
3501  * Some OSes don't allow us to fsync directories at all, so we can ignore
3502  * those errors. Anything else needs to be logged.
3503  */
3504  if (returncode != 0 && !(isdir && errno == EBADF))
3505  {
3506  int save_errno;
3507 
3508  /* close file upon error, might not be in transaction context */
3509  save_errno = errno;
3510  (void) CloseTransientFile(fd);
3511  errno = save_errno;
3512 
3513  ereport(elevel,
3515  errmsg("could not fsync file \"%s\": %m", fname)));
3516  return -1;
3517  }
3518 
3519  (void) CloseTransientFile(fd);
3520 
3521  return 0;
3522 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1080
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2396
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
int CloseTransientFile(int fd)
Definition: fd.c:2566
static int elevel
Definition: vacuumlazy.c:144
int errmsg(const char *fmt,...)
Definition: elog.c:797
int pg_fsync(int fd)
Definition: fd.c:341

◆ fsync_parent_path()

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

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

3532 {
3533  char parentpath[MAXPGPATH];
3534 
3535  strlcpy(parentpath, fname, MAXPGPATH);
3536  get_parent_directory(parentpath);
3537 
3538  /*
3539  * get_parent_directory() returns an empty string if the input argument is
3540  * just a file name (see comments in path.c), so handle that as being the
3541  * current directory.
3542  */
3543  if (strlen(parentpath) == 0)
3544  strlcpy(parentpath, ".", MAXPGPATH);
3545 
3546  if (fsync_fname_ext(parentpath, true, false, elevel) != 0)
3547  return -1;
3548 
3549  return 0;
3550 }
#define MAXPGPATH
void get_parent_directory(char *path)
Definition: path.c:854
static int elevel
Definition: vacuumlazy.c:144
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:3461

◆ GetNextTempTableSpace()

Oid GetNextTempTableSpace ( void  )

Definition at line 2861 of file fd.c.

References InvalidOid, nextTempTableSpace, numTempTableSpaces, and tempTableSpaces.

Referenced by GetDefaultTablespace(), and OpenTemporaryFile().

2862 {
2863  if (numTempTableSpaces > 0)
2864  {
2865  /* Advance nextTempTableSpace counter with wraparound */
2867  nextTempTableSpace = 0;
2869  }
2870  return InvalidOid;
2871 }
static int numTempTableSpaces
Definition: fd.c:266
static int nextTempTableSpace
Definition: fd.c:267
#define InvalidOid
Definition: postgres_ext.h:36
static Oid * tempTableSpaces
Definition: fd.c:265

◆ GetTempTablespaces()

int GetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2843 of file fd.c.

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

Referenced by SharedFileSetInit().

2844 {
2845  int i;
2846 
2848  for (i = 0; i < numTempTableSpaces && i < numSpaces; ++i)
2849  tableSpaces[i] = tempTableSpaces[i];
2850 
2851  return i;
2852 }
static int numTempTableSpaces
Definition: fd.c:266
bool TempTablespacesAreSet(void)
Definition: fd.c:2831
#define Assert(condition)
Definition: c.h:699
static Oid * tempTableSpaces
Definition: fd.c:265
int i

◆ InitFileAccess()

void InitFileAccess ( void  )

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

773 {
774  Assert(SizeVfdCache == 0); /* call me only once */
775 
776  /* initialize cache header entry */
777  VfdCache = (Vfd *) malloc(sizeof(Vfd));
778  if (VfdCache == NULL)
779  ereport(FATAL,
780  (errcode(ERRCODE_OUT_OF_MEMORY),
781  errmsg("out of memory")));
782 
783  MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
785 
786  SizeVfdCache = 1;
787 
788  /* register proc-exit hook to ensure temp files are dropped at exit */
790 }
static void AtProcExit_Files(int code, Datum arg)
Definition: fd.c:2927
static Size SizeVfdCache
Definition: fd.c:206
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:303
static Vfd * VfdCache
Definition: fd.c:205
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:908
#define malloc(a)
Definition: header.h:50
#define FATAL
Definition: elog.h:52
Definition: fd.c:184
int fd
Definition: fd.c:186
#define ereport(elevel, rest)
Definition: elog.h:122
#define VFD_CLOSED
Definition: fd.c:163
#define Assert(condition)
Definition: c.h:699
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ Insert()

static void Insert ( File  file)
static

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

1063 {
1064  Vfd *vfdP;
1065 
1066  Assert(file != 0);
1067 
1068  DO_DB(elog(LOG, "Insert %d (%s)",
1069  file, VfdCache[file].fileName));
1070  DO_DB(_dump_lru());
1071 
1072  vfdP = &VfdCache[file];
1073 
1074  vfdP->lruMoreRecently = 0;
1076  VfdCache[0].lruLessRecently = file;
1078 
1079  DO_DB(_dump_lru());
1080 }
File lruLessRecently
Definition: fd.c:191
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
#define LOG
Definition: elog.h:26
Definition: fd.c:184
#define Assert(condition)
Definition: c.h:699
File lruMoreRecently
Definition: fd.c:190
#define elog
Definition: elog.h:219

◆ looks_like_temp_rel_name()

bool looks_like_temp_rel_name ( const char *  name)

Definition at line 3189 of file fd.c.

References forkname_chars().

Referenced by RemovePgTempRelationFilesInDbspace(), and sendDir().

3190 {
3191  int pos;
3192  int savepos;
3193 
3194  /* Must start with "t". */
3195  if (name[0] != 't')
3196  return false;
3197 
3198  /* Followed by a non-empty string of digits and then an underscore. */
3199  for (pos = 1; isdigit((unsigned char) name[pos]); ++pos)
3200  ;
3201  if (pos == 1 || name[pos] != '_')
3202  return false;
3203 
3204  /* Followed by another nonempty string of digits. */
3205  for (savepos = ++pos; isdigit((unsigned char) name[pos]); ++pos)
3206  ;
3207  if (savepos == pos)
3208  return false;
3209 
3210  /* We might have _forkname or .segment or both. */
3211  if (name[pos] == '_')
3212  {
3213  int forkchar = forkname_chars(&name[pos + 1], NULL);
3214 
3215  if (forkchar <= 0)
3216  return false;
3217  pos += forkchar + 1;
3218  }
3219  if (name[pos] == '.')
3220  {
3221  int segchar;
3222 
3223  for (segchar = 1; isdigit((unsigned char) name[pos + segchar]); ++segchar)
3224  ;
3225  if (segchar <= 1)
3226  return false;
3227  pos += segchar;
3228  }
3229 
3230  /* Now we should be at the end. */
3231  if (name[pos] != '\0')
3232  return false;
3233  return true;
3234 }
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 1021 of file fd.c.

References Assert, close, Delete(), DO_DB, elog, vfd::fd, vfd::fileName, FilePosIsUnknown, LOG, nfile, vfd::seekPos, and VFD_CLOSED.

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

1022 {
1023  Vfd *vfdP;
1024 
1025  Assert(file != 0);
1026 
1027  DO_DB(elog(LOG, "LruDelete %d (%s)",
1028  file, VfdCache[file].fileName));
1029 
1030  vfdP = &VfdCache[file];
1031 
1032  /*
1033  * Normally we should know the seek position, but if for some reason we
1034  * have lost track of it, try again to get it. If we still can't get it,
1035  * we have a problem: we will be unable to restore the file seek position
1036  * when and if the file is re-opened. But we can't really throw an error
1037  * and refuse to close the file, or activities such as transaction cleanup
1038  * will be broken.
1039  */
1040  if (FilePosIsUnknown(vfdP->seekPos))
1041  {
1042  vfdP->seekPos = lseek(vfdP->fd, (off_t) 0, SEEK_CUR);
1043  if (FilePosIsUnknown(vfdP->seekPos))
1044  elog(LOG, "could not seek file \"%s\" before closing: %m",
1045  vfdP->fileName);
1046  }
1047 
1048  /*
1049  * Close the file. We aren't expecting this to fail; if it does, better
1050  * to leak the FD than to mess up our internal state.
1051  */
1052  if (close(vfdP->fd))
1053  elog(LOG, "could not close file \"%s\": %m", vfdP->fileName);
1054  vfdP->fd = VFD_CLOSED;
1055  --nfile;
1056 
1057  /* delete the vfd record from the LRU ring */
1058  Delete(file);
1059 }
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
static void Delete(File file)
Definition: fd.c:1002
#define LOG
Definition: elog.h:26
#define FilePosIsUnknown(pos)
Definition: fd.c:177
char * fileName
Definition: fd.c:194
static int nfile
Definition: fd.c:211
off_t seekPos
Definition: fd.c:192
Definition: fd.c:184
int fd
Definition: fd.c:186
#define VFD_CLOSED
Definition: fd.c:163
#define Assert(condition)
Definition: c.h:699
#define elog
Definition: elog.h:219
#define close(a)
Definition: win32.h:12

◆ LruInsert()

static int LruInsert ( File  file)
static

Definition at line 1084 of file fd.c.

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

Referenced by FileAccess().

1085 {
1086  Vfd *vfdP;
1087 
1088  Assert(file != 0);
1089 
1090  DO_DB(elog(LOG, "LruInsert %d (%s)",
1091  file, VfdCache[file].fileName));
1092 
1093  vfdP = &VfdCache[file];
1094 
1095  if (FileIsNotOpen(file))
1096  {
1097  /* Close excess kernel FDs. */
1098  ReleaseLruFiles();
1099 
1100  /*
1101  * The open could still fail for lack of file descriptors, eg due to
1102  * overall system file table being full. So, be prepared to release
1103  * another FD if necessary...
1104  */
1105  vfdP->fd = BasicOpenFilePerm(vfdP->fileName, vfdP->fileFlags,
1106  vfdP->fileMode);
1107  if (vfdP->fd < 0)
1108  {
1109  DO_DB(elog(LOG, "re-open failed: %m"));
1110  return -1;
1111  }
1112  else
1113  {
1114  ++nfile;
1115  }
1116 
1117  /*
1118  * Seek to the right position. We need no special case for seekPos
1119  * equal to FileUnknownPos, as lseek() will certainly reject that
1120  * (thus completing the logic noted in LruDelete() that we will fail
1121  * to re-open a file if we couldn't get its seek position before
1122  * closing).
1123  */
1124  if (vfdP->seekPos != (off_t) 0)
1125  {
1126  if (lseek(vfdP->fd, vfdP->seekPos, SEEK_SET) < 0)
1127  {
1128  /*
1129  * If we fail to restore the seek position, treat it like an
1130  * open() failure.
1131  */
1132  int save_errno = errno;
1133 
1134  elog(LOG, "could not seek file \"%s\" after re-opening: %m",
1135  vfdP->fileName);
1136  (void) close(vfdP->fd);
1137  vfdP->fd = VFD_CLOSED;
1138  --nfile;
1139  errno = save_errno;
1140  return -1;
1141  }
1142  }
1143  }
1144 
1145  /*
1146  * put it at the head of the Lru ring
1147  */
1148 
1149  Insert(file);
1150 
1151  return 0;
1152 }
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
#define LOG
Definition: elog.h:26
mode_t fileMode
Definition: fd.c:197
char * fileName
Definition: fd.c:194
static int nfile
Definition: fd.c:211
off_t seekPos
Definition: fd.c:192
Definition: fd.c:184
int fd
Definition: fd.c:186
static void Insert(File file)
Definition: fd.c:1062
static void ReleaseLruFiles(void)
Definition: fd.c:1180
#define FileIsNotOpen(file)
Definition: fd.c:168
#define VFD_CLOSED
Definition: fd.c:163
#define Assert(condition)
Definition: c.h:699
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:954
#define elog
Definition: elog.h:219
#define close(a)
Definition: win32.h:12
int fileFlags
Definition: fd.c:196

◆ MakePGDirectory()

int MakePGDirectory ( const char *  directoryName)

◆ OpenPipeStream()

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

Definition at line 2445 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, ReleaseLruFile(), ReleaseLruFiles(), and reserveAllocatedDesc().

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

2446 {
2447  FILE *file;
2448 
2449  DO_DB(elog(LOG, "OpenPipeStream: Allocated %d (%s)",
2450  numAllocatedDescs, command));
2451 
2452  /* Can we allocate another non-virtual FD? */
2453  if (!reserveAllocatedDesc())
2454  ereport(ERROR,
2455  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2456  errmsg("exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"",
2457  maxAllocatedDescs, command)));
2458 
2459  /* Close excess kernel FDs. */
2460  ReleaseLruFiles();
2461 
2462 TryAgain:
2463  fflush(stdout);
2464  fflush(stderr);
2465  errno = 0;
2466  if ((file = popen(command, mode)) != NULL)
2467  {
2469 
2470  desc->kind = AllocateDescPipe;
2471  desc->desc.file = file;
2474  return desc->desc.file;
2475  }
2476 
2477  if (errno == EMFILE || errno == ENFILE)
2478  {
2479  int save_errno = errno;
2480 
2481  ereport(LOG,
2482  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2483  errmsg("out of file descriptors: %m; release and retry")));
2484  errno = 0;
2485  if (ReleaseLruFile())
2486  goto TryAgain;
2487  errno = save_errno;
2488  }
2489 
2490  return NULL;
2491 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
#define DO_DB(A)
Definition: fd.c:159
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool reserveAllocatedDesc(void)
Definition: fd.c:2273
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:241
static bool ReleaseLruFile(void)
Definition: fd.c:1158
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
static void ReleaseLruFiles(void)
Definition: fd.c:1180
FILE * file
Definition: fd.c:245
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:641
SubTransactionId create_subid
Definition: fd.c:242
int errmsg(const char *fmt,...)
Definition: elog.c:797
union AllocateDesc::@27 desc
#define elog
Definition: elog.h:219
static int maxAllocatedDescs
Definition: fd.c:252
static int numAllocatedDescs
Definition: fd.c:251

◆ OpenTemporaryFile()

File OpenTemporaryFile ( bool  interXact)

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

1494 {
1495  File file = 0;
1496 
1497  /*
1498  * Make sure the current resource owner has space for this File before we
1499  * open it, if we'll be registering it below.
1500  */
1501  if (!interXact)
1503 
1504  /*
1505  * If some temp tablespace(s) have been given to us, try to use the next
1506  * one. If a given tablespace can't be found, we silently fall back to
1507  * the database's default tablespace.
1508  *
1509  * BUT: if the temp file is slated to outlive the current transaction,
1510  * force it into the database's default tablespace, so that it will not
1511  * pose a threat to possible tablespace drop attempts.
1512  */
1513  if (numTempTableSpaces > 0 && !interXact)
1514  {
1515  Oid tblspcOid = GetNextTempTableSpace();
1516 
1517  if (OidIsValid(tblspcOid))
1518  file = OpenTemporaryFileInTablespace(tblspcOid, false);
1519  }
1520 
1521  /*
1522  * If not, or if tablespace is bad, create in database's default
1523  * tablespace. MyDatabaseTableSpace should normally be set before we get
1524  * here, but just in case it isn't, fall back to pg_default tablespace.
1525  */
1526  if (file <= 0)
1529  DEFAULTTABLESPACE_OID,
1530  true);
1531 
1532  /* Mark it for deletion at close and temporary file size limit */
1534 
1535  /* Register it with the current resource owner */
1536  if (!interXact)
1537  RegisterTemporaryFile(file);
1538 
1539  return file;
1540 }
static File OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
Definition: fd.c:1571
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:182
ResourceOwner CurrentResourceOwner
Definition: resowner.c:140
#define FD_DELETE_AT_CLOSE
Definition: fd.c:180
static Vfd * VfdCache
Definition: fd.c:205
static int numTempTableSpaces
Definition: fd.c:266
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
Oid MyDatabaseTableSpace
Definition: globals.c:88
Oid GetNextTempTableSpace(void)
Definition: fd.c:2861
unsigned short fdstate
Definition: fd.c:187
static void RegisterTemporaryFile(File file)
Definition: fd.c:1323
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1188
int File
Definition: fd.h:49

◆ OpenTemporaryFileInTablespace()

static File OpenTemporaryFileInTablespace ( Oid  tblspcOid,
bool  rejectError 
)
static

Definition at line 1571 of file fd.c.

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

Referenced by OpenTemporaryFile().

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

◆ OpenTransientFile()

◆ OpenTransientFilePerm()

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

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

2406 {
2407  int fd;
2408 
2409  DO_DB(elog(LOG, "OpenTransientFile: Allocated %d (%s)",
2410  numAllocatedDescs, fileName));
2411 
2412  /* Can we allocate another non-virtual FD? */
2413  if (!reserveAllocatedDesc())
2414  ereport(ERROR,
2415  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2416  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2417  maxAllocatedDescs, fileName)));
2418 
2419  /* Close excess kernel FDs. */
2420  ReleaseLruFiles();
2421 
2422  fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
2423 
2424  if (fd >= 0)
2425  {
2427 
2428  desc->kind = AllocateDescRawFD;
2429  desc->desc.fd = fd;
2432 
2433  return fd;
2434  }
2435 
2436  return -1; /* failure */
2437 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
#define DO_DB(A)
Definition: fd.c:159
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool reserveAllocatedDesc(void)
Definition: fd.c:2273
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:241
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:122
static void ReleaseLruFiles(void)
Definition: fd.c:1180
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:641
SubTransactionId create_subid
Definition: fd.c:242
int fd
Definition: fd.c:247
int errmsg(const char *fmt,...)
Definition: elog.c:797
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:954
union AllocateDesc::@27 desc
#define elog
Definition: elog.h:219
static int maxAllocatedDescs
Definition: fd.c:252
static int numAllocatedDescs
Definition: fd.c:251

◆ PathNameCreateTemporaryDir()

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

Definition at line 1429 of file fd.c.

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

Referenced by SharedFileSetCreate().

1430 {
1431  if (MakePGDirectory(directory) < 0)
1432  {
1433  if (errno == EEXIST)
1434  return;
1435 
1436  /*
1437  * Failed. Try to create basedir first in case it's missing. Tolerate
1438  * EEXIST to close a race against another process following the same
1439  * algorithm.
1440  */
1441  if (MakePGDirectory(basedir) < 0 && errno != EEXIST)
1442  ereport(ERROR,
1444  errmsg("cannot create temporary directory \"%s\": %m",
1445  basedir)));
1446 
1447  /* Try again. */
1448  if (MakePGDirectory(directory) < 0 && errno != EEXIST)
1449  ereport(ERROR,
1451  errmsg("cannot create temporary subdirectory \"%s\": %m",
1452  directory)));
1453  }
1454 }
static char * basedir
Definition: pg_basebackup.c:80
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3571
static const char * directory
Definition: zic.c:567
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ PathNameCreateTemporaryFile()

File PathNameCreateTemporaryFile ( const char *  path,
bool  error_on_failure 
)

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

1629 {
1630  File file;
1631 
1633 
1634  /*
1635  * Open the file. Note: we don't use O_EXCL, in case there is an orphaned
1636  * temp file that can be reused.
1637  */
1638  file = PathNameOpenFile(path, O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1639  if (file <= 0)
1640  {
1641  if (error_on_failure)
1642  ereport(ERROR,
1644  errmsg("could not create temporary file \"%s\": %m",
1645  path)));
1646  else
1647  return file;
1648  }
1649 
1650  /* Mark it for temp_file_limit accounting. */
1652 
1653  /* Register it for automatic close. */
1654  RegisterTemporaryFile(file);
1655 
1656  return file;
1657 }
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1351
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:182
ResourceOwner CurrentResourceOwner
Definition: resowner.c:140
static Vfd * VfdCache
Definition: fd.c:205
#define PG_BINARY
Definition: c.h:1080
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
unsigned short fdstate
Definition: fd.c:187
#define ereport(elevel, rest)
Definition: elog.h:122
static void RegisterTemporaryFile(File file)
Definition: fd.c:1323
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1188
int File
Definition: fd.h:49

◆ PathNameDeleteTemporaryDir()

void PathNameDeleteTemporaryDir ( const char *  dirname)

Definition at line 1460 of file fd.c.

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

Referenced by SharedFileSetDeleteAll().

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

◆ PathNameDeleteTemporaryFile()

bool PathNameDeleteTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1696 of file fd.c.

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

Referenced by SharedFileSetDelete(), and unlink_if_exists_fname().

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

◆ PathNameOpenFile()

File PathNameOpenFile ( const char *  fileName,
int  fileFlags 
)

Definition at line 1351 of file fd.c.

References PathNameOpenFilePerm(), and pg_file_create_mode.

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

1352 {
1353  return PathNameOpenFilePerm(fileName, fileFlags, pg_file_create_mode);
1354 }
File PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1364
int pg_file_create_mode
Definition: file_perm.c:20

◆ PathNameOpenFilePerm()

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

Definition at line 1364 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(), vfd::resowner, and vfd::seekPos.

Referenced by PathNameOpenFile().

1365 {
1366  char *fnamecopy;
1367  File file;
1368  Vfd *vfdP;
1369 
1370  DO_DB(elog(LOG, "PathNameOpenFilePerm: %s %x %o",
1371  fileName, fileFlags, fileMode));
1372 
1373  /*
1374  * We need a malloc'd copy of the file name; fail cleanly if no room.
1375  */
1376  fnamecopy = strdup(fileName);
1377  if (fnamecopy == NULL)
1378  ereport(ERROR,
1379  (errcode(ERRCODE_OUT_OF_MEMORY),
1380  errmsg("out of memory")));
1381 
1382  file = AllocateVfd();
1383  vfdP = &VfdCache[file];
1384 
1385  /* Close excess kernel FDs. */
1386  ReleaseLruFiles();
1387 
1388  vfdP->fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
1389 
1390  if (vfdP->fd < 0)
1391  {
1392  int save_errno = errno;
1393 
1394  FreeVfd(file);
1395  free(fnamecopy);
1396  errno = save_errno;
1397  return -1;
1398  }
1399  ++nfile;
1400  DO_DB(elog(LOG, "PathNameOpenFile: success %d",
1401  vfdP->fd));
1402 
1403  Insert(file);
1404 
1405  vfdP->fileName = fnamecopy;
1406  /* Saved flags are adjusted to be OK for re-opening file */
1407  vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
1408  vfdP->fileMode = fileMode;
1409  vfdP->seekPos = 0;
1410  vfdP->fileSize = 0;
1411  vfdP->fdstate = 0x0;
1412  vfdP->resowner = NULL;
1413 
1414  return file;
1415 }
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
int errcode(int sqlerrcode)
Definition: elog.c:575
#define LOG
Definition: elog.h:26
mode_t fileMode
Definition: fd.c:197
#define ERROR
Definition: elog.h:43
char * fileName
Definition: fd.c:194
static int nfile
Definition: fd.c:211
static File AllocateVfd(void)
Definition: fd.c:1190
off_t seekPos
Definition: fd.c:192
unsigned short fdstate
Definition: fd.c:187
Definition: fd.c:184
off_t fileSize
Definition: fd.c:193
int fd
Definition: fd.c:186
#define ereport(elevel, rest)
Definition: elog.h:122
static void Insert(File file)
Definition: fd.c:1062
ResourceOwner resowner
Definition: fd.c:188
static void ReleaseLruFiles(void)
Definition: fd.c:1180
#define free(a)
Definition: header.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:797
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:954
static void FreeVfd(File file)
Definition: fd.c:1248
#define elog
Definition: elog.h:219
int fileFlags
Definition: fd.c:196
int File
Definition: fd.h:49

◆ PathNameOpenTemporaryFile()

File PathNameOpenTemporaryFile ( const char *  path)

Definition at line 1666 of file fd.c.

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

Referenced by SharedFileSetOpen().

1667 {
1668  File file;
1669 
1671 
1672  /* We open the file read-only. */
1673  file = PathNameOpenFile(path, O_RDONLY | PG_BINARY);
1674 
1675  /* If no such file, then we don't raise an error. */
1676  if (file <= 0 && errno != ENOENT)
1677  ereport(ERROR,
1679  errmsg("could not open temporary file \"%s\": %m",
1680  path)));
1681 
1682  if (file > 0)
1683  {
1684  /* Register it for automatic close. */
1685  RegisterTemporaryFile(file);
1686  }
1687 
1688  return file;
1689 }
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1351
ResourceOwner CurrentResourceOwner
Definition: resowner.c:140
#define PG_BINARY
Definition: c.h:1080
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
static void RegisterTemporaryFile(File file)
Definition: fd.c:1323
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1188
int File
Definition: fd.h:49

◆ pg_fdatasync()

int pg_fdatasync ( int  fd)

Definition at line 393 of file fd.c.

References enableFsync, and fsync.

Referenced by issue_xlog_fsync().

394 {
395  if (enableFsync)
396  {
397 #ifdef HAVE_FDATASYNC
398  return fdatasync(fd);
399 #else
400  return fsync(fd);
401 #endif
402  }
403  else
404  return 0;
405 }
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:120

◆ pg_flush_data()

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

Definition at line 415 of file fd.c.

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

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

416 {
417  /*
418  * Right now file flushing is primarily used to avoid making later
419  * fsync()/fdatasync() calls have less impact. Thus don't trigger flushes
420  * if fsyncs are disabled - that's a decision we might want to make
421  * configurable at some point.
422  */
423  if (!enableFsync)
424  return;
425 
426  /*
427  * We compile all alternatives that are supported on the current platform,
428  * to find portability problems more easily.
429  */
430 #if defined(HAVE_SYNC_FILE_RANGE)
431  {
432  int rc;
433 
434  /*
435  * sync_file_range(SYNC_FILE_RANGE_WRITE), currently linux specific,
436  * tells the OS that writeback for the specified blocks should be
437  * started, but that we don't want to wait for completion. Note that
438  * this call might block if too much dirty data exists in the range.
439  * This is the preferable method on OSs supporting it, as it works
440  * reliably when available (contrast to msync()) and doesn't flush out
441  * clean data (like FADV_DONTNEED).
442  */
443  rc = sync_file_range(fd, offset, nbytes,
444  SYNC_FILE_RANGE_WRITE);
445 
446  /* don't error out, this is just a performance optimization */
447  if (rc != 0)
448  {
451  errmsg("could not flush dirty data: %m")));
452  }
453 
454  return;
455  }
456 #endif
457 #if !defined(WIN32) && defined(MS_ASYNC)
458  {
459  void *p;
460  static int pagesize = 0;
461 
462  /*
463  * On several OSs msync(MS_ASYNC) on a mmap'ed file triggers
464  * writeback. On linux it only does so if MS_SYNC is specified, but
465  * then it does the writeback synchronously. Luckily all common linux
466  * systems have sync_file_range(). This is preferable over
467  * FADV_DONTNEED because it doesn't flush out clean data.
468  *
469  * We map the file (mmap()), tell the kernel to sync back the contents
470  * (msync()), and then remove the mapping again (munmap()).
471  */
472 
473  /* mmap() needs actual length if we want to map whole file */
474  if (offset == 0 && nbytes == 0)
475  {
476  nbytes = lseek(fd, 0, SEEK_END);
477  if (nbytes < 0)
478  {
481  errmsg("could not determine dirty data size: %m")));
482  return;
483  }
484  }
485 
486  /*
487  * Some platforms reject partial-page mmap() attempts. To deal with
488  * that, just truncate the request to a page boundary. If any extra
489  * bytes don't get flushed, well, it's only a hint anyway.
490  */
491 
492  /* fetch pagesize only once */
493  if (pagesize == 0)
494  pagesize = sysconf(_SC_PAGESIZE);
495 
496  /* align length to pagesize, dropping any fractional page */
497  if (pagesize > 0)
498  nbytes = (nbytes / pagesize) * pagesize;
499 
500  /* fractional-page request is a no-op */
501  if (nbytes <= 0)
502  return;
503 
504  /*
505  * mmap could well fail, particularly on 32-bit platforms where there
506  * may simply not be enough address space. If so, silently fall
507  * through to the next implementation.
508  */
509  if (nbytes <= (off_t) SSIZE_MAX)
510  p = mmap(NULL, nbytes, PROT_READ, MAP_SHARED, fd, offset);
511  else
512  p = MAP_FAILED;
513 
514  if (p != MAP_FAILED)
515  {
516  int rc;
517 
518  rc = msync(p, (size_t) nbytes, MS_ASYNC);
519  if (rc != 0)
520  {
523  errmsg("could not flush dirty data: %m")));
524  /* NB: need to fall through to munmap()! */
525  }
526 
527  rc = munmap(p, (size_t) nbytes);
528  if (rc != 0)
529  {
530  /* FATAL error because mapping would remain */
531  ereport(FATAL,
533  errmsg("could not munmap() while flushing data: %m")));
534  }
535 
536  return;
537  }
538  }
539 #endif
540 #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
541  {
542  int rc;
543 
544  /*
545  * Signal the kernel that the passed in range should not be cached
546  * anymore. This has the, desired, side effect of writing out dirty
547  * data, and the, undesired, side effect of likely discarding useful
548  * clean cached blocks. For the latter reason this is the least
549  * preferable method.
550  */
551 
552  rc = posix_fadvise(fd, offset, nbytes, POSIX_FADV_DONTNEED);
553 
554  if (rc != 0)
555  {
556  /* don't error out, this is just a performance optimization */
559  errmsg("could not flush dirty data: %m")));
560  }
561 
562  return;
563  }
564 #endif
565 }
#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:598
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
bool enableFsync
Definition: globals.c:120
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ pg_fsync()

int pg_fsync ( int  fd)

Definition at line 341 of file fd.c.

References pg_fsync_no_writethrough(), pg_fsync_writethrough(), 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(), RecreateTwoPhaseFile(), RestoreSlotFromDisk(), SaveSlotToPath(), SimpleLruFlush(), SlruPhysicalWritePage(), SnapBuildSerialize(), UpdateControlFile(), write_auto_conf_file(), write_relmap_file(), WriteControlFile(), writeTimeLineHistory(), writeTimeLineHistoryFile(), XLogFileCopy(), and XLogFileInit().

342 {
343  /* #if is to skip the sync_method test if there's no need for it */
344 #if defined(HAVE_FSYNC_WRITETHROUGH) && !defined(FSYNC_WRITETHROUGH_IS_FSYNC)
346  return pg_fsync_writethrough(fd);
347  else
348 #endif
350 }
#define SYNC_METHOD_FSYNC_WRITETHROUGH
Definition: xlog.h:28
int pg_fsync_writethrough(int fd)
Definition: fd.c:370
int pg_fsync_no_writethrough(int fd)
Definition: fd.c:358
static int fd(const char *x, int i)
Definition: preproc-init.c:105
int sync_method
Definition: xlog.c:103

◆ pg_fsync_no_writethrough()

int pg_fsync_no_writethrough ( int  fd)

Definition at line 358 of file fd.c.

References enableFsync, and fsync.

Referenced by issue_xlog_fsync(), and pg_fsync().

359 {
360  if (enableFsync)
361  return fsync(fd);
362  else
363  return 0;
364 }
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:120

◆ pg_fsync_writethrough()

int pg_fsync_writethrough ( int  fd)

Definition at line 370 of file fd.c.

References enableFsync.

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

371 {
372  if (enableFsync)
373  {
374 #ifdef WIN32
375  return _commit(fd);
376 #elif defined(F_FULLFSYNC)
377  return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
378 #else
379  errno = ENOSYS;
380  return -1;
381 #endif
382  }
383  else
384  return 0;
385 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
bool enableFsync
Definition: globals.c:120

◆ ReadDir()

◆ ReadDirExtended()

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

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

2682 {
2683  struct dirent *dent;
2684 
2685  /* Give a generic message for AllocateDir failure, if caller didn't */
2686  if (dir == NULL)
2687  {
2688  ereport(elevel,
2690  errmsg("could not open directory \"%s\": %m",
2691  dirname)));
2692  return NULL;
2693  }
2694 
2695  errno = 0;
2696  if ((dent = readdir(dir)) != NULL)
2697  return dent;
2698 
2699  if (errno)
2700  ereport(elevel,
2702  errmsg("could not read directory \"%s\": %m",
2703  dirname)));
2704  return NULL;
2705 }
Definition: dirent.h:9
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
static int elevel
Definition: vacuumlazy.c:144
struct dirent * readdir(DIR *)
Definition: dirent.c:77
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ RegisterTemporaryFile()

static void RegisterTemporaryFile ( File  file)
static

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

1324 {
1327 
1328  /* Backup mechanism for closing at end of xact. */
1331 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:140
static Vfd * VfdCache
Definition: fd.c:205
static bool have_xact_temporary_files
Definition: fd.c:217
void ResourceOwnerRememberFile(ResourceOwner owner, File file)
Definition: resowner.c:1199
unsigned short fdstate
Definition: fd.c:187
ResourceOwner resowner
Definition: fd.c:188
#define FD_CLOSE_AT_EOXACT
Definition: fd.c:181

◆ ReleaseLruFile()

static bool ReleaseLruFile ( void  )
static

Definition at line 1158 of file fd.c.

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

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

1159 {
1160  DO_DB(elog(LOG, "ReleaseLruFile. Opened %d", nfile));
1161 
1162  if (nfile > 0)
1163  {
1164  /*
1165  * There are opened files and so there should be at least one used vfd
1166  * in the ring.
1167  */
1168  Assert(VfdCache[0].lruMoreRecently != 0);
1169  LruDelete(VfdCache[0].lruMoreRecently);
1170  return true; /* freed a file */
1171  }
1172  return false; /* no files available to free */
1173 }
#define DO_DB(A)
Definition: fd.c:159
static Vfd * VfdCache
Definition: fd.c:205
#define LOG
Definition: elog.h:26
static void LruDelete(File file)
Definition: fd.c:1021
static int nfile
Definition: fd.c:211
#define Assert(condition)
Definition: c.h:699
#define elog
Definition: elog.h:219

◆ ReleaseLruFiles()

static void ReleaseLruFiles ( void  )
static

Definition at line 1180 of file fd.c.

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

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

1181 {
1182  while (nfile + numAllocatedDescs >= max_safe_fds)
1183  {
1184  if (!ReleaseLruFile())
1185  break;
1186  }
1187 }
int max_safe_fds
Definition: fd.c:146
static bool ReleaseLruFile(void)
Definition: fd.c:1158
static int nfile
Definition: fd.c:211
static int numAllocatedDescs
Definition: fd.c:251

◆ RemovePgTempFiles()

void RemovePgTempFiles ( void  )

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

3008 {
3009  char temp_path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY) + sizeof(PG_TEMP_FILES_DIR)];
3010  DIR *spc_dir;
3011  struct dirent *spc_de;
3012 
3013  /*
3014  * First process temp files in pg_default ($PGDATA/base)
3015  */
3016  snprintf(temp_path, sizeof(temp_path), "base/%s", PG_TEMP_FILES_DIR);
3017  RemovePgTempFilesInDir(temp_path, true, false);
3018  RemovePgTempRelationFiles("base");
3019 
3020  /*
3021  * Cycle through temp directories for all non-default tablespaces.
3022  */
3023  spc_dir = AllocateDir("pg_tblspc");
3024 
3025  while ((spc_de = ReadDirExtended(spc_dir, "pg_tblspc", LOG)) != NULL)
3026  {
3027  if (strcmp(spc_de->d_name, ".") == 0 ||
3028  strcmp(spc_de->d_name, "..") == 0)
3029  continue;
3030 
3031  snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s/%s",
3033  RemovePgTempFilesInDir(temp_path, true, false);
3034 
3035  snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s",
3037  RemovePgTempRelationFiles(temp_path);
3038  }
3039 
3040  FreeDir(spc_dir);
3041 
3042  /*
3043  * In EXEC_BACKEND case there is a pgsql_tmp directory at the top level of
3044  * DataDir as well.
3045  */
3046 #ifdef EXEC_BACKEND
3048 #endif
3049 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2681
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
static void RemovePgTempRelationFiles(const char *tsdirname)
Definition: fd.c:3133
Definition: dirent.c:25
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2600
static void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, bool unlink_all)
Definition: fd.c:3067
#define PG_TEMP_FILES_DIR
Definition: fd.h:144
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2718

◆ RemovePgTempFilesInDir()

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

Definition at line 3067 of file fd.c.

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

Referenced by RemovePgTempFiles().

3068 {
3069  DIR *temp_dir;
3070  struct dirent *temp_de;
3071  char rm_path[MAXPGPATH * 2];
3072 
3073  temp_dir = AllocateDir(tmpdirname);
3074 
3075  if (temp_dir == NULL && errno == ENOENT && missing_ok)
3076  return;
3077 
3078  while ((temp_de = ReadDirExtended(temp_dir, tmpdirname, LOG)) != NULL)
3079  {
3080  if (strcmp(temp_de->d_name, ".") == 0 ||
3081  strcmp(temp_de->d_name, "..") == 0)
3082  continue;
3083 
3084  snprintf(rm_path, sizeof(rm_path), "%s/%s",
3085  tmpdirname, temp_de->d_name);
3086 
3087  if (unlink_all ||
3088  strncmp(temp_de->d_name,
3090  strlen(PG_TEMP_FILE_PREFIX)) == 0)
3091  {
3092  struct stat statbuf;
3093 
3094  if (lstat(rm_path, &statbuf) < 0)
3095  {
3096  ereport(LOG,
3098  errmsg("could not stat file \"%s\": %m", rm_path)));
3099  continue;
3100  }
3101 
3102  if (S_ISDIR(statbuf.st_mode))
3103  {
3104  /* recursively remove contents, then directory itself */
3105  RemovePgTempFilesInDir(rm_path, false, true);
3106 
3107  if (rmdir(rm_path) < 0)
3108  ereport(LOG,
3110  errmsg("could not remove directory \"%s\": %m",
3111  rm_path)));
3112  }
3113  else
3114  {
3115  if (unlink(rm_path) < 0)
3116  ereport(LOG,
3118  errmsg("could not remove file \"%s\": %m",
3119  rm_path)));
3120  }
3121  }
3122  else
3123  ereport(LOG,
3124  (errmsg("unexpected file found in temporary-files directory: \"%s\"",
3125  rm_path)));
3126  }
3127 
3128  FreeDir(temp_dir);
3129 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2681
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define PG_TEMP_FILE_PREFIX
Definition: fd.h:145
#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:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2600
#define ereport(elevel, rest)
Definition: elog.h:122
#define stat(a, b)
Definition: win32_port.h:266
static void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, bool unlink_all)
Definition: fd.c:3067
#define S_ISDIR(m)
Definition: win32_port.h:307
#define lstat(path, sb)
Definition: win32_port.h:255
int errmsg(const char *fmt,...)
Definition: elog.c:797
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2718

◆ RemovePgTempRelationFiles()

static void RemovePgTempRelationFiles ( const char *  tsdirname)
static

Definition at line 3133 of file fd.c.

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

Referenced by RemovePgTempFiles().

3134 {
3135  DIR *ts_dir;
3136  struct dirent *de;
3137  char dbspace_path[MAXPGPATH * 2];
3138 
3139  ts_dir = AllocateDir(tsdirname);
3140 
3141  while ((de = ReadDirExtended(ts_dir, tsdirname, LOG)) != NULL)
3142  {
3143  /*
3144  * We're only interested in the per-database directories, which have
3145  * numeric names. Note that this code will also (properly) ignore "."
3146  * and "..".
3147  */
3148  if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
3149  continue;
3150 
3151  snprintf(dbspace_path, sizeof(dbspace_path), "%s/%s",
3152  tsdirname, de->d_name);
3153  RemovePgTempRelationFilesInDbspace(dbspace_path);
3154  }
3155 
3156  FreeDir(ts_dir);
3157 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2681
static void RemovePgTempRelationFilesInDbspace(const char *dbspacedirname)
Definition: fd.c:3161
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2600
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2718

◆ RemovePgTempRelationFilesInDbspace()

static void RemovePgTempRelationFilesInDbspace ( const char *  dbspacedirname)
static

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

3162 {
3163  DIR *dbspace_dir;
3164  struct dirent *de;
3165  char rm_path[MAXPGPATH * 2];
3166 
3167  dbspace_dir = AllocateDir(dbspacedirname);
3168 
3169  while ((de = ReadDirExtended(dbspace_dir, dbspacedirname, LOG)) != NULL)
3170  {
3171  if (!looks_like_temp_rel_name(de->d_name))
3172  continue;
3173 
3174  snprintf(rm_path, sizeof(rm_path), "%s/%s",
3175  dbspacedirname, de->d_name);
3176 
3177  if (unlink(rm_path) < 0)
3178  ereport(LOG,
3180  errmsg("could not remove file \"%s\": %m",
3181  rm_path)));
3182  }
3183 
3184  FreeDir(dbspace_dir);
3185 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2681
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#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:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2600
#define ereport(elevel, rest)
Definition: elog.h:122
bool looks_like_temp_rel_name(const char *name)
Definition: fd.c:3189
int errmsg(const char *fmt,...)
Definition: elog.c:797
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2718

◆ ReportTemporaryFileUsage()

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

Definition at line 1304 of file fd.c.

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

Referenced by FileClose(), and PathNameDeleteTemporaryFile().

1305 {
1306  pgstat_report_tempfile(size);
1307 
1308  if (log_temp_files >= 0)
1309  {
1310  if ((size / 1024) >= log_temp_files)
1311  ereport(LOG,
1312  (errmsg("temporary file: path \"%s\", size %lu",
1313  path, (unsigned long) size)));
1314  }
1315 }
int log_temp_files
Definition: guc.c:457
void pgstat_report_tempfile(size_t filesize)
Definition: pgstat.c:1525
#define LOG
Definition: elog.h:26
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ reserveAllocatedDesc()

static bool reserveAllocatedDesc ( void  )
static

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

2274 {
2275  AllocateDesc *newDescs;
2276  int newMax;
2277 
2278  /* Quick out if array already has a free slot. */
2280  return true;
2281 
2282  /*
2283  * If the array hasn't yet been created in the current process, initialize
2284  * it with FD_MINFREE / 2 elements. In many scenarios this is as many as
2285  * we will ever need, anyway. We don't want to look at max_safe_fds
2286  * immediately because set_max_safe_fds() may not have run yet.
2287  */
2288  if (allocatedDescs == NULL)
2289  {
2290  newMax = FD_MINFREE / 2;
2291  newDescs = (AllocateDesc *) malloc(newMax * sizeof(AllocateDesc));
2292  /* Out of memory already? Treat as fatal error. */
2293  if (newDescs == NULL)
2294  ereport(ERROR,
2295  (errcode(ERRCODE_OUT_OF_MEMORY),
2296  errmsg("out of memory")));
2297  allocatedDescs = newDescs;
2298  maxAllocatedDescs = newMax;
2299  return true;
2300  }
2301 
2302  /*
2303  * Consider enlarging the array beyond the initial allocation used above.
2304  * By the time this happens, max_safe_fds should be known accurately.
2305  *
2306  * We mustn't let allocated descriptors hog all the available FDs, and in
2307  * practice we'd better leave a reasonable number of FDs for VFD use. So
2308  * set the maximum to max_safe_fds / 2. (This should certainly be at
2309  * least as large as the initial size, FD_MINFREE / 2.)
2310  */
2311  newMax = max_safe_fds / 2;
2312  if (newMax > maxAllocatedDescs)
2313  {
2314  newDescs = (AllocateDesc *) realloc(allocatedDescs,
2315  newMax * sizeof(AllocateDesc));
2316  /* Treat out-of-memory as a non-fatal error. */
2317  if (newDescs == NULL)
2318  return false;
2319  allocatedDescs = newDescs;
2320  maxAllocatedDescs = newMax;
2321  return true;
2322  }
2323 
2324  /* Can't enlarge allocatedDescs[] any more. */
2325  return false;
2326 }
static AllocateDesc * allocatedDescs
Definition: fd.c:253
int max_safe_fds
Definition: fd.c:146
int errcode(int sqlerrcode)
Definition: elog.c:575
#define malloc(a)
Definition: header.h:50
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define FD_MINFREE
Definition: fd.c:125
#define realloc(a, b)
Definition: header.h:60
int errmsg(const char *fmt,...)
Definition: elog.c:797
static int maxAllocatedDescs
Definition: fd.c:252
static int numAllocatedDescs
Definition: fd.c:251

◆ set_max_safe_fds()

void set_max_safe_fds ( void  )

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

890 {
891  int usable_fds;
892  int already_open;
893 
894  /*----------
895  * We want to set max_safe_fds to
896  * MIN(usable_fds, max_files_per_process - already_open)
897  * less the slop factor for files that are opened without consulting
898  * fd.c. This ensures that we won't exceed either max_files_per_process
899  * or the experimentally-determined EMFILE limit.
900  *----------
901  */
903  &usable_fds, &already_open);
904 
905  max_safe_fds = Min(usable_fds, max_files_per_process - already_open);
906 
907  /*
908  * Take off the FDs reserved for system() etc.
909  */
911 
912  /*
913  * Make sure we still have enough to get by.
914  */
915  if (max_safe_fds < FD_MINFREE)
916  ereport(FATAL,
917  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
918  errmsg("insufficient file descriptors available to start server process"),
919  errdetail("System allows %d, we need at least %d.",
922 
923  elog(DEBUG2, "max_safe_fds = %d, usable_fds = %d, already_open = %d",
924  max_safe_fds, usable_fds, already_open);
925 }
static void count_usable_fds(int max_to_probe, int *usable_fds, int *already_open)
Definition: fd.c:805
#define NUM_RESERVED_FDS
Definition: fd.c:119
int max_safe_fds
Definition: fd.c:146
#define Min(x, y)
Definition: c.h:857
int errcode(int sqlerrcode)
Definition: elog.c:575
#define FATAL
Definition: elog.h:52
#define DEBUG2
Definition: elog.h:24
int errdetail(const char *fmt,...)
Definition: elog.c:873
int max_files_per_process
Definition: fd.c:133
#define ereport(elevel, rest)
Definition: elog.h:122
#define FD_MINFREE
Definition: fd.c:125
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219

◆ SetTempTablespaces()

void SetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2803 of file fd.c.

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

Referenced by assign_temp_tablespaces(), and PrepareTempTablespaces().

2804 {
2805  Assert(numSpaces >= 0);
2806  tempTableSpaces = tableSpaces;
2807  numTempTableSpaces = numSpaces;
2808 
2809  /*
2810  * Select a random starting point in the list. This is to minimize
2811  * conflicts between backends that are most likely sharing the same list
2812  * of temp tablespaces. Note that if we create multiple temp files in the
2813  * same transaction, we'll advance circularly through the list --- this
2814  * ensures that large temporary sort files are nicely spread across all
2815  * available tablespaces.
2816  */
2817  if (numSpaces > 1)
2818  nextTempTableSpace = random() % numSpaces;
2819  else
2820  nextTempTableSpace = 0;
2821 }
long random(void)
Definition: random.c:22
static int numTempTableSpaces
Definition: fd.c:266
static int nextTempTableSpace
Definition: fd.c:267
#define Assert(condition)
Definition: c.h:699
static Oid * tempTableSpaces
Definition: fd.c:265

◆ SyncDataDirectory()

void SyncDataDirectory ( void  )

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

3257 {
3258  bool xlog_is_symlink;
3259 
3260  /* We can skip this whole thing if fsync is disabled. */
3261  if (!enableFsync)
3262  return;
3263 
3264  /*
3265  * If pg_wal is a symlink, we'll need to recurse into it separately,
3266  * because the first walkdir below will ignore it.
3267  */
3268  xlog_is_symlink = false;
3269 
3270 #ifndef WIN32
3271  {
3272  struct stat st;
3273 
3274  if (lstat("pg_wal", &st) < 0)
3275  ereport(LOG,
3277  errmsg("could not stat file \"%s\": %m",
3278  "pg_wal")));
3279  else if (S_ISLNK(st.st_mode))
3280  xlog_is_symlink = true;
3281  }
3282 #else
3283  if (pgwin32_is_junction("pg_wal"))
3284  xlog_is_symlink = true;
3285 #endif
3286 
3287  /*
3288  * If possible, hint to the kernel that we're soon going to fsync the data
3289  * directory and its contents. Errors in this step are even less
3290  * interesting than normal, so log them only at DEBUG1.
3291  */
3292 #ifdef PG_FLUSH_DATA_WORKS
3293  walkdir(".", pre_sync_fname, false, DEBUG1);
3294  if (xlog_is_symlink)
3295  walkdir("pg_wal", pre_sync_fname, false, DEBUG1);
3296  walkdir("pg_tblspc", pre_sync_fname, true, DEBUG1);
3297 #endif
3298 
3299  /*
3300  * Now we do the fsync()s in the same order.
3301  *
3302  * The main call ignores symlinks, so in addition to specially processing
3303  * pg_wal if it's a symlink, pg_tblspc has to be visited separately with
3304  * process_symlinks = true. Note that if there are any plain directories
3305  * in pg_tblspc, they'll get fsync'd twice. That's not an expected case
3306  * so we don't worry about optimizing it.
3307  */
3308  walkdir(".", datadir_fsync_fname, false, LOG);
3309  if (xlog_is_symlink)
3310  walkdir("pg_wal", datadir_fsync_fname, false, LOG);
3311  walkdir("pg_tblspc", datadir_fsync_fname, true, LOG);
3312 }
#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:3329
#define LOG
Definition: elog.h:26
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
static void datadir_fsync_fname(const char *fname, bool isdir, int elevel)
Definition: fd.c:3426
#define stat(a, b)
Definition: win32_port.h:266
#define lstat(path, sb)
Definition: win32_port.h:255
bool enableFsync
Definition: globals.c:120
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool pgwin32_is_junction(const char *path)

◆ TempTablespacePath()

void TempTablespacePath ( char *  path,
Oid  tablespace 
)

Definition at line 1546 of file fd.c.

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

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

1547 {
1548  /*
1549  * Identify the tempfile directory for this tablespace.
1550  *
1551  * If someone tries to specify pg_global, use pg_default instead.
1552  */
1553  if (tablespace == InvalidOid ||
1554  tablespace == DEFAULTTABLESPACE_OID ||
1555  tablespace == GLOBALTABLESPACE_OID)
1556  snprintf(path, MAXPGPATH, "base/%s", PG_TEMP_FILES_DIR);
1557  else
1558  {
1559  /* All other tablespaces are accessed via symlinks */
1560  snprintf(path, MAXPGPATH, "pg_tblspc/%u/%s/%s",
1563  }
1564 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
char * tablespace
Definition: pgbench.c:155
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_TEMP_FILES_DIR
Definition: fd.h:144

◆ TempTablespacesAreSet()

bool TempTablespacesAreSet ( void  )

Definition at line 2831 of file fd.c.

References numTempTableSpaces.

Referenced by GetTempTablespaces(), and PrepareTempTablespaces().

2832 {
2833  return (numTempTableSpaces >= 0);
2834 }
static int numTempTableSpaces
Definition: fd.c:266

◆ unlink_if_exists_fname()

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

Definition at line 3436 of file fd.c.

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

Referenced by PathNameDeleteTemporaryDir().

3437 {
3438  if (isdir)
3439  {
3440  if (rmdir(fname) != 0 && errno != ENOENT)
3441  ereport(elevel,
3443  errmsg("could not rmdir directory \"%s\": %m", fname)));
3444  }
3445  else
3446  {
3447  /* Use PathNameDeleteTemporaryFile to report filesize */
3448  PathNameDeleteTemporaryFile(fname, false);
3449  }
3450 }
bool PathNameDeleteTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1696
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
static int elevel
Definition: vacuumlazy.c:144
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ 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 3329 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().

3333 {
3334  DIR *dir;
3335  struct dirent *de;
3336 
3337  dir = AllocateDir(path);
3338 
3339  while ((de = ReadDirExtended(dir, path, elevel)) != NULL)
3340  {
3341  char subpath[MAXPGPATH * 2];
3342  struct stat fst;
3343  int sret;
3344 
3346 
3347  if (strcmp(de->d_name, ".") == 0 ||
3348  strcmp(de->d_name, "..") == 0)
3349  continue;
3350 
3351  snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name);
3352 
3353  if (process_symlinks)
3354  sret = stat(subpath, &fst);
3355  else
3356  sret = lstat(subpath, &fst);
3357 
3358  if (sret < 0)
3359  {
3360  ereport(elevel,
3362  errmsg("could not stat file \"%s\": %m", subpath)));
3363  continue;
3364  }
3365 
3366  if (S_ISREG(fst.st_mode))
3367  (*action) (subpath, false, elevel);
3368  else if (S_ISDIR(fst.st_mode))
3369  walkdir(subpath, action, false, elevel);
3370  }
3371 
3372  FreeDir(dir); /* we ignore any error here */
3373 
3374  /*
3375  * It's important to fsync the destination directory itself as individual
3376  * file fsyncs don't guarantee that the directory entry for the file is
3377  * synced. However, skip this if AllocateDir failed; the action function
3378  * might not be robust against that.
3379  */
3380  if (dir)
3381  (*action) (path, true, elevel);
3382 }
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
Definition: fd.c:3329
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2681
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2600
#define ereport(elevel, rest)
Definition: elog.h:122
#define S_ISREG(m)
Definition: win32_port.h:310
#define stat(a, b)
Definition: win32_port.h:266
static int elevel
Definition: vacuumlazy.c:144
#define S_ISDIR(m)
Definition: win32_port.h:307
#define lstat(path, sb)
Definition: win32_port.h:255
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2718
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:234

Variable Documentation

◆ allocatedDescs

AllocateDesc* allocatedDescs = NULL
static

Definition at line 253 of file fd.c.

◆ have_xact_temporary_files

bool have_xact_temporary_files = false
static

Definition at line 217 of file fd.c.

Referenced by CleanupTempFiles(), and RegisterTemporaryFile().

◆ max_files_per_process

int max_files_per_process = 1000

Definition at line 133 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 267 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 206 of file fd.c.

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

◆ tempFileCounter

long tempFileCounter = 0
static

Definition at line 259 of file fd.c.

Referenced by OpenTemporaryFileInTablespace().

◆ temporary_files_size

uint64 temporary_files_size = 0
static

Definition at line 225 of file fd.c.

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

◆ tempTableSpaces

Oid* tempTableSpaces = NULL
static

◆ VfdCache

Vfd* VfdCache
static

Definition at line 205 of file fd.c.