PostgreSQL Source Code  git master
fd.c File Reference
#include "postgres.h"
#include <dirent.h>
#include <sys/file.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/pg_tablespace.h"
#include "common/file_perm.h"
#include "common/file_utils.h"
#include "common/pg_prng.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "portability/mem.h"
#include "postmaster/startup.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   48
 
#define DO_DB(A)    ((void) 0)
 
#define VFD_CLOSED   (-1)
 
#define FileIsValid(file)    ((file) > 0 && (file) < (int) SizeVfdCache && VfdCache[file].fileName != NULL)
 
#define FileIsNotOpen(file)   (VfdCache[file].fd == VFD_CLOSED)
 
#define FD_DELETE_AT_CLOSE   (1 << 0) /* T = delete when closed */
 
#define FD_CLOSE_AT_EOXACT   (1 << 1) /* T = close at eoXact */
 
#define FD_TEMP_FILE_LIMIT   (1 << 2) /* T = respect temp_file_limit */
 

Typedefs

typedef struct vfd Vfd
 

Enumerations

enum  AllocateDescKind { AllocateDescFile , AllocateDescPipe , AllocateDescDir , AllocateDescRawFD }
 

Functions

static void Delete (File file)
 
static void LruDelete (File file)
 
static void Insert (File file)
 
static int LruInsert (File file)
 
static bool ReleaseLruFile (void)
 
static void ReleaseLruFiles (void)
 
static File AllocateVfd (void)
 
static void FreeVfd (File file)
 
static int FileAccess (File file)
 
static File OpenTemporaryFileInTablespace (Oid tblspcOid, bool rejectError)
 
static bool reserveAllocatedDesc (void)
 
static int FreeDesc (AllocateDesc *desc)
 
static void BeforeShmemExit_Files (int code, Datum arg)
 
static void CleanupTempFiles (bool isCommit, bool isProcExit)
 
static void RemovePgTempRelationFiles (const char *tsdirname)
 
static void RemovePgTempRelationFilesInDbspace (const char *dbspacedirname)
 
static void walkdir (const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
 
static void datadir_fsync_fname (const char *fname, bool isdir, int elevel)
 
static void unlink_if_exists_fname (const char *fname, bool isdir, int elevel)
 
static int fsync_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)
 
int pg_truncate (const char *path, off_t length)
 
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)
 
void InitFileAccess (void)
 
void InitTemporaryFileAccess (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)
 
bool AcquireExternalFD (void)
 
void ReserveExternalFD (void)
 
void ReleaseExternalFD (void)
 
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, int mode)
 
bool PathNameDeleteTemporaryFile (const char *path, bool error_on_failure)
 
void FileClose (File file)
 
int FilePrefetch (File file, off_t offset, int amount, uint32 wait_event_info)
 
void FileWriteback (File file, off_t offset, off_t nbytes, uint32 wait_event_info)
 
int FileRead (File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
 
int FileWrite (File file, char *buffer, int amount, off_t offset, uint32 wait_event_info)
 
int FileSync (File file, uint32 wait_event_info)
 
off_t FileSize (File file)
 
int FileTruncate (File file, off_t offset, uint32 wait_event_info)
 
char * FilePathName (File file)
 
int FileGetRawDesc (File file)
 
int FileGetRawFlags (File file)
 
mode_t FileGetRawMode (File file)
 
FILE * AllocateFile (const char *name, const char *mode)
 
int OpenTransientFile (const char *fileName, int fileFlags)
 
int OpenTransientFilePerm (const char *fileName, int fileFlags, mode_t fileMode)
 
FILE * OpenPipeStream (const char *command, const char *mode)
 
int FreeFile (FILE *file)
 
int CloseTransientFile (int fd)
 
DIRAllocateDir (const char *dirname)
 
struct direntReadDir (DIR *dir, const char *dirname)
 
struct direntReadDirExtended (DIR *dir, const char *dirname, int elevel)
 
int FreeDir (DIR *dir)
 
int ClosePipeStream (FILE *file)
 
void closeAllVfds (void)
 
void SetTempTablespaces (Oid *tableSpaces, int numSpaces)
 
bool TempTablespacesAreSet (void)
 
int GetTempTablespaces (Oid *tableSpaces, int numSpaces)
 
Oid GetNextTempTableSpace (void)
 
void AtEOSubXact_Files (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
void AtEOXact_Files (bool isCommit)
 
void RemovePgTempFiles (void)
 
void RemovePgTempFilesInDir (const char *tmpdirname, bool missing_ok, bool unlink_all)
 
bool looks_like_temp_rel_name (const char *name)
 
void SyncDataDirectory (void)
 
int fsync_fname_ext (const char *fname, bool isdir, bool ignore_perm, int elevel)
 
int MakePGDirectory (const char *directoryName)
 
int data_sync_elevel (int elevel)
 

Variables

int max_files_per_process = 1000
 
int max_safe_fds = FD_MINFREE
 
bool data_sync_retry = false
 
int recovery_init_sync_method = RECOVERY_INIT_SYNC_METHOD_FSYNC
 
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 int numExternalFDs = 0
 
static long tempFileCounter = 0
 
static OidtempTableSpaces = NULL
 
static int numTempTableSpaces = -1
 
static int nextTempTableSpace = 0
 

Macro Definition Documentation

◆ DO_DB

#define DO_DB (   A)     ((void) 0)

Definition at line 175 of file fd.c.

◆ FD_CLOSE_AT_EOXACT

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

Definition at line 188 of file fd.c.

◆ FD_DELETE_AT_CLOSE

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

Definition at line 187 of file fd.c.

◆ FD_MINFREE

#define FD_MINFREE   48

Definition at line 136 of file fd.c.

◆ FD_TEMP_FILE_LIMIT

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

Definition at line 189 of file fd.c.

◆ FileIsNotOpen

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

Definition at line 184 of file fd.c.

◆ FileIsValid

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

Definition at line 181 of file fd.c.

◆ NUM_RESERVED_FDS

#define NUM_RESERVED_FDS   10

Definition at line 127 of file fd.c.

◆ VFD_CLOSED

#define VFD_CLOSED   (-1)

Definition at line 179 of file fd.c.

Typedef Documentation

◆ Vfd

typedef struct vfd Vfd

Enumeration Type Documentation

◆ AllocateDescKind

Enumerator
AllocateDescFile 
AllocateDescPipe 
AllocateDescDir 
AllocateDescRawFD 

Definition at line 242 of file fd.c.

243 {
AllocateDescKind
Definition: fd.c:243
@ AllocateDescDir
Definition: fd.c:246
@ AllocateDescPipe
Definition: fd.c:245
@ AllocateDescFile
Definition: fd.c:244
@ AllocateDescRawFD
Definition: fd.c:247

Function Documentation

◆ AcquireExternalFD()

bool AcquireExternalFD ( void  )

Definition at line 1099 of file fd.c.

1100 {
1101  /*
1102  * We don't want more than max_safe_fds / 3 FDs to be consumed for
1103  * "external" FDs.
1104  */
1105  if (numExternalFDs < max_safe_fds / 3)
1106  {
1108  return true;
1109  }
1110  errno = EMFILE;
1111  return false;
1112 }
int max_safe_fds
Definition: fd.c:157
void ReserveExternalFD(void)
Definition: fd.c:1134
static int numExternalFDs
Definition: fd.c:269

References max_safe_fds, numExternalFDs, and ReserveExternalFD().

Referenced by connect_pg_server(), CreateWaitEventSet(), dblink_connect(), and dblink_get_conn().

◆ AllocateDir()

DIR* AllocateDir ( const char *  dirname)

Definition at line 2643 of file fd.c.

2644 {
2645  DIR *dir;
2646 
2647  DO_DB(elog(LOG, "AllocateDir: Allocated %d (%s)",
2648  numAllocatedDescs, dirname));
2649 
2650  /* Can we allocate another non-virtual FD? */
2651  if (!reserveAllocatedDesc())
2652  ereport(ERROR,
2653  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2654  errmsg("exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"",
2655  maxAllocatedDescs, dirname)));
2656 
2657  /* Close excess kernel FDs. */
2658  ReleaseLruFiles();
2659 
2660 TryAgain:
2661  if ((dir = opendir(dirname)) != NULL)
2662  {
2664 
2665  desc->kind = AllocateDescDir;
2666  desc->desc.dir = dir;
2669  return desc->desc.dir;
2670  }
2671 
2672  if (errno == EMFILE || errno == ENFILE)
2673  {
2674  int save_errno = errno;
2675 
2676  ereport(LOG,
2677  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2678  errmsg("out of file descriptors: %m; release and retry")));
2679  errno = 0;
2680  if (ReleaseLruFile())
2681  goto TryAgain;
2682  errno = save_errno;
2683  }
2684 
2685  return NULL;
2686 }
DIR * opendir(const char *)
Definition: dirent.c:33
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define LOG
Definition: elog.h:27
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
static bool ReleaseLruFile(void)
Definition: fd.c:1295
static int maxAllocatedDescs
Definition: fd.c:263
static int numAllocatedDescs
Definition: fd.c:262
#define DO_DB(A)
Definition: fd.c:175
static AllocateDesc * allocatedDescs
Definition: fd.c:264
static bool reserveAllocatedDesc(void)
Definition: fd.c:2308
static void ReleaseLruFiles(void)
Definition: fd.c:1317
SubTransactionId create_subid
Definition: fd.c:253
DIR * dir
Definition: fd.c:257
union AllocateDesc::@19 desc
AllocateDescKind kind
Definition: fd.c:252
Definition: dirent.c:26
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:779

References allocatedDescs, 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(), CheckTablespaceDirectory(), CleanupBackupHistory(), copydir(), db_dir_size(), DeleteAllExportedSnapshotFiles(), destroy_tablespace_directories(), directory_is_empty(), do_pg_backup_start(), dsm_cleanup_for_mmap(), extension_file_exists(), get_ext_ver_list(), GetConfFilesInDir(), 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(), RelationCacheInitFileRemove(), RelationCacheInitFileRemoveInDir(), RemoveNonParentXlogFiles(), RemoveOldXlogFiles(), RemovePgTempFiles(), RemovePgTempFilesInDir(), RemovePgTempRelationFiles(), RemovePgTempRelationFilesInDbspace(), RemoveTempXlogFiles(), ReorderBufferCleanupSerializedTXNs(), ResetUnloggedRelations(), ResetUnloggedRelationsInDbspaceDir(), ResetUnloggedRelationsInTablespaceDir(), restoreTwoPhaseData(), scan_directory_ci(), sendDir(), SlruScanDirectory(), StartupReorderBuffer(), StartupReplicationSlots(), SyncDataDirectory(), UpdateLogicalMappings(), and walkdir().

◆ AllocateFile()

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

Definition at line 2383 of file fd.c.

2384 {
2385  FILE *file;
2386 
2387  DO_DB(elog(LOG, "AllocateFile: Allocated %d (%s)",
2389 
2390  /* Can we allocate another non-virtual FD? */
2391  if (!reserveAllocatedDesc())
2392  ereport(ERROR,
2393  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2394  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2395  maxAllocatedDescs, name)));
2396 
2397  /* Close excess kernel FDs. */
2398  ReleaseLruFiles();
2399 
2400 TryAgain:
2401  if ((file = fopen(name, mode)) != NULL)
2402  {
2404 
2405  desc->kind = AllocateDescFile;
2406  desc->desc.file = file;
2409  return desc->desc.file;
2410  }
2411 
2412  if (errno == EMFILE || errno == ENFILE)
2413  {
2414  int save_errno = errno;
2415 
2416  ereport(LOG,
2417  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2418  errmsg("out of file descriptors: %m; release and retry")));
2419  errno = 0;
2420  if (ReleaseLruFile())
2421  goto TryAgain;
2422  errno = save_errno;
2423  }
2424 
2425  return NULL;
2426 }
const char * name
Definition: encode.c:561
static PgChecksumMode mode
Definition: pg_checksums.c:65
FILE * file
Definition: fd.c:256

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

Referenced by AlterSystemSetConfigFile(), apw_dump_now(), apw_load_buffers(), BeginCopyFrom(), BeginCopyTo(), checkControlFile(), do_pg_backup_stop(), entry_reset(), existsTimeLineHistory(), ExportSnapshot(), gc_qtexts(), GetHugePageSize(), ImportSnapshot(), load_dh_file(), load_relcache_init_file(), open_auth_file(), parse_extension_control_file(), ParseTzFile(), pg_current_logfile(), pg_file_write_internal(), pg_promote(), pgss_shmem_shutdown(), pgss_shmem_startup(), pgstat_read_statsfile(), pgstat_write_statsfile(), read_backup_label(), read_binary_file(), read_tablespace_map(), read_whole_file(), readTimeLineHistory(), tsearch_readline_begin(), ValidatePgVersion(), write_relcache_init_file(), XLogArchiveForceDone(), and XLogArchiveNotify().

◆ AllocateVfd()

static File AllocateVfd ( void  )
static

Definition at line 1327 of file fd.c.

1328 {
1329  Index i;
1330  File file;
1331 
1332  DO_DB(elog(LOG, "AllocateVfd. Size %zu", SizeVfdCache));
1333 
1334  Assert(SizeVfdCache > 0); /* InitFileAccess not called? */
1335 
1336  if (VfdCache[0].nextFree == 0)
1337  {
1338  /*
1339  * The free list is empty so it is time to increase the size of the
1340  * array. We choose to double it each time this happens. However,
1341  * there's not much point in starting *real* small.
1342  */
1343  Size newCacheSize = SizeVfdCache * 2;
1344  Vfd *newVfdCache;
1345 
1346  if (newCacheSize < 32)
1347  newCacheSize = 32;
1348 
1349  /*
1350  * Be careful not to clobber VfdCache ptr if realloc fails.
1351  */
1352  newVfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
1353  if (newVfdCache == NULL)
1354  ereport(ERROR,
1355  (errcode(ERRCODE_OUT_OF_MEMORY),
1356  errmsg("out of memory")));
1357  VfdCache = newVfdCache;
1358 
1359  /*
1360  * Initialize the new entries and link them into the free list.
1361  */
1362  for (i = SizeVfdCache; i < newCacheSize; i++)
1363  {
1364  MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
1365  VfdCache[i].nextFree = i + 1;
1366  VfdCache[i].fd = VFD_CLOSED;
1367  }
1368  VfdCache[newCacheSize - 1].nextFree = 0;
1370 
1371  /*
1372  * Record the new size
1373  */
1374  SizeVfdCache = newCacheSize;
1375  }
1376 
1377  file = VfdCache[0].nextFree;
1378 
1379  VfdCache[0].nextFree = VfdCache[file].nextFree;
1380 
1381  return file;
1382 }
unsigned int Index
Definition: c.h:550
#define MemSet(start, val, len)
Definition: c.h:953
size_t Size
Definition: c.h:541
static Size SizeVfdCache
Definition: fd.c:212
#define VFD_CLOSED
Definition: fd.c:179
static Vfd * VfdCache
Definition: fd.c:211
int File
Definition: fd.h:54
#define realloc(a, b)
Definition: header.h:60
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
Definition: fd.c:192
int fd
Definition: fd.c:193
File nextFree
Definition: fd.c:196

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

Referenced by PathNameOpenFilePerm().

◆ AtEOSubXact_Files()

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

Definition at line 2932 of file fd.c.

2934 {
2935  Index i;
2936 
2937  for (i = 0; i < numAllocatedDescs; i++)
2938  {
2939  if (allocatedDescs[i].create_subid == mySubid)
2940  {
2941  if (isCommit)
2942  allocatedDescs[i].create_subid = parentSubid;
2943  else
2944  {
2945  /* have to recheck the item after FreeDesc (ugly) */
2946  FreeDesc(&allocatedDescs[i--]);
2947  }
2948  }
2949  }
2950 }
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2542

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

Referenced by AbortSubTransaction(), basic_archive_file(), and CommitSubTransaction().

◆ AtEOXact_Files()

void AtEOXact_Files ( bool  isCommit)

Definition at line 2965 of file fd.c.

2966 {
2967  CleanupTempFiles(isCommit, false);
2968  tempTableSpaces = NULL;
2969  numTempTableSpaces = -1;
2970 }
static int numTempTableSpaces
Definition: fd.c:284
static Oid * tempTableSpaces
Definition: fd.c:283
static void CleanupTempFiles(bool isCommit, bool isProcExit)
Definition: fd.c:3002

References CleanupTempFiles(), numTempTableSpaces, and tempTableSpaces.

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

◆ BasicOpenFile()

int BasicOpenFile ( const char *  fileName,
int  fileFlags 
)

Definition at line 993 of file fd.c.

994 {
995  return BasicOpenFilePerm(fileName, fileFlags, pg_file_create_mode);
996 }
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1015
int pg_file_create_mode
Definition: file_perm.c:19

References BasicOpenFilePerm(), and pg_file_create_mode.

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

◆ BasicOpenFilePerm()

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

Definition at line 1015 of file fd.c.

1016 {
1017  int fd;
1018 
1019 tryAgain:
1020 #ifdef PG_O_DIRECT_USE_F_NOCACHE
1021 
1022  /*
1023  * The value we defined to stand in for O_DIRECT when simulating it with
1024  * F_NOCACHE had better not collide with any of the standard flags.
1025  */
1027  (O_APPEND |
1028  O_CREAT |
1029  O_EXCL |
1030  O_RDWR |
1031  O_RDONLY |
1032  O_SYNC |
1033  O_TRUNC |
1034  O_WRONLY)) == 0,
1035  "PG_O_DIRECT value collides with standard flag");
1036 #if defined(O_CLOEXEC)
1037  StaticAssertStmt((PG_O_DIRECT & O_CLOEXEC) == 0,
1038  "PG_O_DIRECT value collides with O_CLOEXEC");
1039 #endif
1040 #if defined(O_DSYNC)
1042  "PG_O_DIRECT value collides with O_DSYNC");
1043 #endif
1044 
1045  fd = open(fileName, fileFlags & ~PG_O_DIRECT, fileMode);
1046 #else
1047  fd = open(fileName, fileFlags, fileMode);
1048 #endif
1049 
1050  if (fd >= 0)
1051  {
1052 #ifdef PG_O_DIRECT_USE_F_NOCACHE
1053  if (fileFlags & PG_O_DIRECT)
1054  {
1055  if (fcntl(fd, F_NOCACHE, 1) < 0)
1056  {
1057  int save_errno = errno;
1058 
1059  close(fd);
1060  errno = save_errno;
1061  return -1;
1062  }
1063  }
1064 #endif
1065 
1066  return fd; /* success! */
1067  }
1068 
1069  if (errno == EMFILE || errno == ENFILE)
1070  {
1071  int save_errno = errno;
1072 
1073  ereport(LOG,
1074  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
1075  errmsg("out of file descriptors: %m; release and retry")));
1076  errno = 0;
1077  if (ReleaseLruFile())
1078  goto tryAgain;
1079  errno = save_errno;
1080  }
1081 
1082  return -1; /* failure */
1083 }
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:869
#define PG_O_DIRECT
Definition: fd.h:93
#define close(a)
Definition: win32.h:12
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define O_DSYNC
Definition: win32_port.h:354

References close, ereport, errcode(), errmsg(), fd(), LOG, O_DSYNC, PG_O_DIRECT, ReleaseLruFile(), and StaticAssertStmt.

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

◆ BeforeShmemExit_Files()

static void BeforeShmemExit_Files ( int  code,
Datum  arg 
)
static

Definition at line 2979 of file fd.c.

2980 {
2981  CleanupTempFiles(false, true);
2982 
2983  /* prevent further temp files from being created */
2984 #ifdef USE_ASSERT_CHECKING
2985  temporary_files_allowed = false;
2986 #endif
2987 }

References CleanupTempFiles().

Referenced by InitTemporaryFileAccess().

◆ CleanupTempFiles()

static void CleanupTempFiles ( bool  isCommit,
bool  isProcExit 
)
static

Definition at line 3002 of file fd.c.

3003 {
3004  Index i;
3005 
3006  /*
3007  * Careful here: at proc_exit we need extra cleanup, not just
3008  * xact_temporary files.
3009  */
3010  if (isProcExit || have_xact_temporary_files)
3011  {
3012  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
3013  for (i = 1; i < SizeVfdCache; i++)
3014  {
3015  unsigned short fdstate = VfdCache[i].fdstate;
3016 
3017  if (((fdstate & FD_DELETE_AT_CLOSE) || (fdstate & FD_CLOSE_AT_EOXACT)) &&
3018  VfdCache[i].fileName != NULL)
3019  {
3020  /*
3021  * If we're in the process of exiting a backend process, close
3022  * all temporary files. Otherwise, only close temporary files
3023  * local to the current transaction. They should be closed by
3024  * the ResourceOwner mechanism already, so this is just a
3025  * debugging cross-check.
3026  */
3027  if (isProcExit)
3028  FileClose(i);
3029  else if (fdstate & FD_CLOSE_AT_EOXACT)
3030  {
3031  elog(WARNING,
3032  "temporary file %s not closed at end-of-transaction",
3033  VfdCache[i].fileName);
3034  FileClose(i);
3035  }
3036  }
3037  }
3038 
3039  have_xact_temporary_files = false;
3040  }
3041 
3042  /* Complain if any allocated files remain open at commit. */
3043  if (isCommit && numAllocatedDescs > 0)
3044  elog(WARNING, "%d temporary files and directories not closed at end-of-transaction",
3046 
3047  /* Clean up "allocated" stdio files, dirs and fds. */
3048  while (numAllocatedDescs > 0)
3049  FreeDesc(&allocatedDescs[0]);
3050 }
#define WARNING
Definition: elog.h:32
#define FD_DELETE_AT_CLOSE
Definition: fd.c:187
#define FD_CLOSE_AT_EOXACT
Definition: fd.c:188
void FileClose(File file)
Definition: fd.c:1883
#define FileIsNotOpen(file)
Definition: fd.c:184
static bool have_xact_temporary_files
Definition: fd.c:223
unsigned short fdstate
Definition: fd.c:194

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

Referenced by AtEOXact_Files(), and BeforeShmemExit_Files().

◆ closeAllVfds()

void closeAllVfds ( void  )

Definition at line 2820 of file fd.c.

2821 {
2822  Index i;
2823 
2824  if (SizeVfdCache > 0)
2825  {
2826  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
2827  for (i = 1; i < SizeVfdCache; i++)
2828  {
2829  if (!FileIsNotOpen(i))
2830  LruDelete(i);
2831  }
2832  }
2833 }
static void LruDelete(File file)
Definition: fd.c:1200

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

Referenced by standard_ProcessUtility().

◆ ClosePipeStream()

int ClosePipeStream ( FILE *  file)

Definition at line 2791 of file fd.c.

2792 {
2793  int i;
2794 
2795  DO_DB(elog(LOG, "ClosePipeStream: Allocated %d", numAllocatedDescs));
2796 
2797  /* Remove file from list of allocated files, if it's present */
2798  for (i = numAllocatedDescs; --i >= 0;)
2799  {
2800  AllocateDesc *desc = &allocatedDescs[i];
2801 
2802  if (desc->kind == AllocateDescPipe && desc->desc.file == file)
2803  return FreeDesc(desc);
2804  }
2805 
2806  /* Only get here if someone passes us a file not in allocatedDescs */
2807  elog(WARNING, "file passed to ClosePipeStream was not obtained from OpenPipeStream");
2808 
2809  return pclose(file);
2810 }

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

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

◆ CloseTransientFile()

int CloseTransientFile ( int  fd)

Definition at line 2609 of file fd.c.

2610 {
2611  int i;
2612 
2613  DO_DB(elog(LOG, "CloseTransientFile: Allocated %d", numAllocatedDescs));
2614 
2615  /* Remove fd from list of allocated files, if it's present */
2616  for (i = numAllocatedDescs; --i >= 0;)
2617  {
2618  AllocateDesc *desc = &allocatedDescs[i];
2619 
2620  if (desc->kind == AllocateDescRawFD && desc->desc.fd == fd)
2621  return FreeDesc(desc);
2622  }
2623 
2624  /* Only get here if someone passes us a file not in allocatedDescs */
2625  elog(WARNING, "fd passed to CloseTransientFile was not obtained from OpenTransientFile");
2626 
2627  return close(fd);
2628 }
int fd
Definition: fd.c:258

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

Referenced by ApplyLogicalMappingFile(), be_lo_export(), CheckPointLogicalRewriteHeap(), CheckPointReplicationOrigin(), compare_files(), copy_file(), CreateDirAndVersionFile(), dsm_impl_mmap(), durable_rename(), fsync_fname_ext(), get_controlfile(), heap_xlog_logical_rewrite(), lo_import_internal(), perform_base_backup(), pg_truncate(), qtext_load_file(), qtext_store(), read_relmap_file(), ReadTwoPhaseFile(), RecreateTwoPhaseFile(), ReorderBufferSerializeChange(), ReorderBufferSerializeTXN(), RestoreSlotFromDisk(), SaveSlotToPath(), sendFile(), SendTimeLineHistory(), SimpleLruDoesPhysicalPageExist(), SimpleLruWriteAll(), SlruInternalWritePage(), SlruPhysicalReadPage(), SlruPhysicalWritePage(), SlruSyncFileTag(), SnapBuildRestore(), SnapBuildRestoreContents(), SnapBuildSerialize(), StartupReplicationOrigin(), write_relmap_file(), writeTimeLineHistory(), writeTimeLineHistoryFile(), and XLogFileCopy().

◆ count_usable_fds()

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

Definition at line 870 of file fd.c.

871 {
872  int *fd;
873  int size;
874  int used = 0;
875  int highestfd = 0;
876  int j;
877 
878 #ifdef HAVE_GETRLIMIT
879  struct rlimit rlim;
880  int getrlimit_status;
881 #endif
882 
883  size = 1024;
884  fd = (int *) palloc(size * sizeof(int));
885 
886 #ifdef HAVE_GETRLIMIT
887  getrlimit_status = getrlimit(RLIMIT_NOFILE, &rlim);
888  if (getrlimit_status != 0)
889  ereport(WARNING, (errmsg("getrlimit failed: %m")));
890 #endif /* HAVE_GETRLIMIT */
891 
892  /* dup until failure or probe limit reached */
893  for (;;)
894  {
895  int thisfd;
896 
897 #ifdef HAVE_GETRLIMIT
898 
899  /*
900  * don't go beyond RLIMIT_NOFILE; causes irritating kernel logs on
901  * some platforms
902  */
903  if (getrlimit_status == 0 && highestfd >= rlim.rlim_cur - 1)
904  break;
905 #endif
906 
907  thisfd = dup(2);
908  if (thisfd < 0)
909  {
910  /* Expect EMFILE or ENFILE, else it's fishy */
911  if (errno != EMFILE && errno != ENFILE)
912  elog(WARNING, "duplicating stderr file descriptor failed after %d successes: %m", used);
913  break;
914  }
915 
916  if (used >= size)
917  {
918  size *= 2;
919  fd = (int *) repalloc(fd, size * sizeof(int));
920  }
921  fd[used++] = thisfd;
922 
923  if (highestfd < thisfd)
924  highestfd = thisfd;
925 
926  if (used >= max_to_probe)
927  break;
928  }
929 
930  /* release the files we opened */
931  for (j = 0; j < used; j++)
932  close(fd[j]);
933 
934  pfree(fd);
935 
936  /*
937  * Return results. usable_fds is just the number of successful dups. We
938  * assume that the system limit is highestfd+1 (remember 0 is a legal FD
939  * number) and so already_open is highestfd+1 - usable_fds.
940  */
941  *usable_fds = used;
942  *already_open = highestfd + 1 - used;
943 }
int j
Definition: isn.c:74
void pfree(void *pointer)
Definition: mcxt.c:1306
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1321
void * palloc(Size size)
Definition: mcxt.c:1199

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

Referenced by set_max_safe_fds().

◆ data_sync_elevel()

◆ datadir_fsync_fname()

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

Definition at line 3559 of file fd.c.

3560 {
3561  ereport_startup_progress("syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s",
3562  fname);
3563 
3564  /*
3565  * We want to silently ignoring errors about unreadable files. Pass that
3566  * desire on to fsync_fname_ext().
3567  */
3568  fsync_fname_ext(fname, isdir, true, elevel);
3569 }
int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3597
#define ereport_startup_progress(msg,...)
Definition: startup.h:18

References ereport_startup_progress, and fsync_fname_ext().

Referenced by SyncDataDirectory().

◆ Delete()

static void Delete ( File  file)
static

Definition at line 1181 of file fd.c.

1182 {
1183  Vfd *vfdP;
1184 
1185  Assert(file != 0);
1186 
1187  DO_DB(elog(LOG, "Delete %d (%s)",
1188  file, VfdCache[file].fileName));
1189  DO_DB(_dump_lru());
1190 
1191  vfdP = &VfdCache[file];
1192 
1195 
1196  DO_DB(_dump_lru());
1197 }
File lruLessRecently
Definition: fd.c:198
File lruMoreRecently
Definition: fd.c:197

References Assert(), DO_DB, elog(), LOG, vfd::lruLessRecently, vfd::lruMoreRecently, and VfdCache.

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

◆ durable_rename()

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

Definition at line 688 of file fd.c.

689 {
690  int fd;
691 
692  /*
693  * First fsync the old and target path (if it exists), to ensure that they
694  * are properly persistent on disk. Syncing the target file is not
695  * strictly necessary, but it makes it easier to reason about crashes;
696  * because it's then guaranteed that either source or target file exists
697  * after a crash.
698  */
699  if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
700  return -1;
701 
702  fd = OpenTransientFile(newfile, PG_BINARY | O_RDWR);
703  if (fd < 0)
704  {
705  if (errno != ENOENT)
706  {
707  ereport(elevel,
709  errmsg("could not open file \"%s\": %m", newfile)));
710  return -1;
711  }
712  }
713  else
714  {
715  if (pg_fsync(fd) != 0)
716  {
717  int save_errno;
718 
719  /* close file upon error, might not be in transaction context */
720  save_errno = errno;
722  errno = save_errno;
723 
724  ereport(elevel,
726  errmsg("could not fsync file \"%s\": %m", newfile)));
727  return -1;
728  }
729 
730  if (CloseTransientFile(fd) != 0)
731  {
732  ereport(elevel,
734  errmsg("could not close file \"%s\": %m", newfile)));
735  return -1;
736  }
737  }
738 
739  /* Time to do the real deal... */
740  if (rename(oldfile, newfile) < 0)
741  {
742  ereport(elevel,
744  errmsg("could not rename file \"%s\" to \"%s\": %m",
745  oldfile, newfile)));
746  return -1;
747  }
748 
749  /*
750  * To guarantee renaming the file is persistent, fsync the file with its
751  * new name, and its containing directory.
752  */
753  if (fsync_fname_ext(newfile, false, false, elevel) != 0)
754  return -1;
755 
756  if (fsync_parent_path(newfile, elevel) != 0)
757  return -1;
758 
759  return 0;
760 }
#define PG_BINARY
Definition: c.h:1209
int errcode_for_file_access(void)
Definition: elog.c:718
int CloseTransientFile(int fd)
Definition: fd.c:2609
int pg_fsync(int fd)
Definition: fd.c:356
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3673
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2433

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

Referenced by AlterSystemSetConfigFile(), apw_dump_now(), BaseBackup(), basic_archive_file_internal(), bbsink_server_end_manifest(), CheckPointReplicationOrigin(), CleanupAfterArchiveRecovery(), dir_close(), InitWalRecovery(), InstallXLogFileSegment(), KeepFileRestoredFromArchive(), pgss_shmem_shutdown(), StartupXLOG(), write_relmap_file(), writeTimeLineHistory(), writeTimeLineHistoryFile(), and XLogArchiveForceDone().

◆ durable_unlink()

int durable_unlink ( const char *  fname,
int  elevel 
)

Definition at line 778 of file fd.c.

779 {
780  if (unlink(fname) < 0)
781  {
782  ereport(elevel,
784  errmsg("could not remove file \"%s\": %m",
785  fname)));
786  return -1;
787  }
788 
789  /*
790  * To guarantee that the removal of the file is persistent, fsync its
791  * parent directory.
792  */
793  if (fsync_parent_path(fname, elevel) != 0)
794  return -1;
795 
796  return 0;
797 }

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

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

◆ FileAccess()

static int FileAccess ( File  file)
static

Definition at line 1405 of file fd.c.

1406 {
1407  int returnValue;
1408 
1409  DO_DB(elog(LOG, "FileAccess %d (%s)",
1410  file, VfdCache[file].fileName));
1411 
1412  /*
1413  * Is the file open? If not, open it and put it at the head of the LRU
1414  * ring (possibly closing the least recently used file to get an FD).
1415  */
1416 
1417  if (FileIsNotOpen(file))
1418  {
1419  returnValue = LruInsert(file);
1420  if (returnValue != 0)
1421  return returnValue;
1422  }
1423  else if (VfdCache[0].lruLessRecently != file)
1424  {
1425  /*
1426  * We now know that the file is open and that it is not the last one
1427  * accessed, so we need to move it to the head of the Lru ring.
1428  */
1429 
1430  Delete(file);
1431  Insert(file);
1432  }
1433 
1434  return 0;
1435 }
static void Delete(File file)
Definition: fd.c:1181
static void Insert(File file)
Definition: fd.c:1226
static int LruInsert(File file)
Definition: fd.c:1248

References Delete(), DO_DB, elog(), FileIsNotOpen, Insert(), LOG, LruInsert(), and VfdCache.

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

◆ FileClose()

void FileClose ( File  file)

Definition at line 1883 of file fd.c.

1884 {
1885  Vfd *vfdP;
1886 
1887  Assert(FileIsValid(file));
1888 
1889  DO_DB(elog(LOG, "FileClose: %d (%s)",
1890  file, VfdCache[file].fileName));
1891 
1892  vfdP = &VfdCache[file];
1893 
1894  if (!FileIsNotOpen(file))
1895  {
1896  /* close the file */
1897  if (close(vfdP->fd) != 0)
1898  {
1899  /*
1900  * We may need to panic on failure to close non-temporary files;
1901  * see LruDelete.
1902  */
1904  "could not close file \"%s\": %m", vfdP->fileName);
1905  }
1906 
1907  --nfile;
1908  vfdP->fd = VFD_CLOSED;
1909 
1910  /* remove the file from the lru ring */
1911  Delete(file);
1912  }
1913 
1914  if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
1915  {
1916  /* Subtract its size from current usage (do first in case of error) */
1917  temporary_files_size -= vfdP->fileSize;
1918  vfdP->fileSize = 0;
1919  }
1920 
1921  /*
1922  * Delete the file if it was temporary, and make a log entry if wanted
1923  */
1924  if (vfdP->fdstate & FD_DELETE_AT_CLOSE)
1925  {
1926  struct stat filestats;
1927  int stat_errno;
1928 
1929  /*
1930  * If we get an error, as could happen within the ereport/elog calls,
1931  * we'll come right back here during transaction abort. Reset the
1932  * flag to ensure that we can't get into an infinite loop. This code
1933  * is arranged to ensure that the worst-case consequence is failing to
1934  * emit log message(s), not failing to attempt the unlink.
1935  */
1936  vfdP->fdstate &= ~FD_DELETE_AT_CLOSE;
1937 
1938 
1939  /* first try the stat() */
1940  if (stat(vfdP->fileName, &filestats))
1941  stat_errno = errno;
1942  else
1943  stat_errno = 0;
1944 
1945  /* in any case do the unlink */
1946  if (unlink(vfdP->fileName))
1947  ereport(LOG,
1949  errmsg("could not delete file \"%s\": %m", vfdP->fileName)));
1950 
1951  /* and last report the stat results */
1952  if (stat_errno == 0)
1953  ReportTemporaryFileUsage(vfdP->fileName, filestats.st_size);
1954  else
1955  {
1956  errno = stat_errno;
1957  ereport(LOG,
1959  errmsg("could not stat file \"%s\": %m", vfdP->fileName)));
1960  }
1961  }
1962 
1963  /* Unregister it from the resource owner */
1964  if (vfdP->resowner)
1965  ResourceOwnerForgetFile(vfdP->resowner, file);
1966 
1967  /*
1968  * Return the Vfd slot to the free list
1969  */
1970  FreeVfd(file);
1971 }
#define FileIsValid(file)
Definition: fd.c:181
static int nfile
Definition: fd.c:217
static void FreeVfd(File file)
Definition: fd.c:1385
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:189
int data_sync_elevel(int elevel)
Definition: fd.c:3736
static void ReportTemporaryFileUsage(const char *path, off_t size)
Definition: fd.c:1441
static uint64 temporary_files_size
Definition: fd.c:231
void ResourceOwnerForgetFile(ResourceOwner owner, File file)
Definition: resowner.c:1310
char * fileName
Definition: fd.c:200
ResourceOwner resowner
Definition: fd.c:195
off_t fileSize
Definition: fd.c:199
#define stat
Definition: win32_port.h:286

References Assert(), close, data_sync_elevel(), Delete(), DO_DB, elog(), ereport, errcode_for_file_access(), errmsg(), 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::st_size, stat, temporary_files_size, VFD_CLOSED, and VfdCache.

Referenced by bbsink_server_end_archive(), bbsink_server_end_manifest(), BufFileClose(), BufFileTruncateFileSet(), CleanupTempFiles(), logical_end_heap_rewrite(), mdclose(), mdimmedsync(), mdsyncfiletag(), mdtruncate(), ReorderBufferIterTXNFinish(), ReorderBufferRestoreChanges(), and ResourceOwnerReleaseInternal().

◆ FileGetRawDesc()

int FileGetRawDesc ( File  file)

Definition at line 2277 of file fd.c.

2278 {
2279  Assert(FileIsValid(file));
2280  return VfdCache[file].fd;
2281 }

References Assert(), vfd::fd, FileIsValid, and VfdCache.

◆ FileGetRawFlags()

int FileGetRawFlags ( File  file)

Definition at line 2287 of file fd.c.

2288 {
2289  Assert(FileIsValid(file));
2290  return VfdCache[file].fileFlags;
2291 }
int fileFlags
Definition: fd.c:202

References Assert(), vfd::fileFlags, FileIsValid, and VfdCache.

◆ FileGetRawMode()

mode_t FileGetRawMode ( File  file)

Definition at line 2297 of file fd.c.

2298 {
2299  Assert(FileIsValid(file));
2300  return VfdCache[file].fileMode;
2301 }
mode_t fileMode
Definition: fd.c:203

References Assert(), FileIsValid, vfd::fileMode, and VfdCache.

◆ FilePathName()

◆ FilePrefetch()

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

Definition at line 1983 of file fd.c.

1984 {
1985 #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
1986  int returnCode;
1987 
1988  Assert(FileIsValid(file));
1989 
1990  DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " %d",
1991  file, VfdCache[file].fileName,
1992  (int64) offset, amount));
1993 
1994  returnCode = FileAccess(file);
1995  if (returnCode < 0)
1996  return returnCode;
1997 
1998  pgstat_report_wait_start(wait_event_info);
1999  returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
2000  POSIX_FADV_WILLNEED);
2002 
2003  return returnCode;
2004 #else
2005  Assert(FileIsValid(file));
2006  return 0;
2007 #endif
2008 }
#define INT64_FORMAT
Definition: c.h:484
static int FileAccess(File file)
Definition: fd.c:1405
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:268
static void pgstat_report_wait_end(void)
Definition: wait_event.h:284

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

Referenced by mdprefetch().

◆ FileRead()

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

Definition at line 2034 of file fd.c.

2036 {
2037  int returnCode;
2038  Vfd *vfdP;
2039 
2040  Assert(FileIsValid(file));
2041 
2042  DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p",
2043  file, VfdCache[file].fileName,
2044  (int64) offset,
2045  amount, buffer));
2046 
2047  returnCode = FileAccess(file);
2048  if (returnCode < 0)
2049  return returnCode;
2050 
2051  vfdP = &VfdCache[file];
2052 
2053 retry:
2054  pgstat_report_wait_start(wait_event_info);
2055  returnCode = pg_pread(vfdP->fd, buffer, amount, offset);
2057 
2058  if (returnCode < 0)
2059  {
2060  /*
2061  * Windows may run out of kernel buffers and return "Insufficient
2062  * system resources" error. Wait a bit and retry to solve it.
2063  *
2064  * It is rumored that EINTR is also possible on some Unix filesystems,
2065  * in which case immediate retry is indicated.
2066  */
2067 #ifdef WIN32
2068  DWORD error = GetLastError();
2069 
2070  switch (error)
2071  {
2072  case ERROR_NO_SYSTEM_RESOURCES:
2073  pg_usleep(1000L);
2074  errno = EINTR;
2075  break;
2076  default:
2077  _dosmaperr(error);
2078  break;
2079  }
2080 #endif
2081  /* OK to retry if interrupted */
2082  if (errno == EINTR)
2083  goto retry;
2084  }
2085 
2086  return returnCode;
2087 }
#define pg_pread
Definition: port.h:225
void pg_usleep(long microsec)
Definition: signal.c:53
static void error(void)
Definition: sql-dyntest.c:147
#define EINTR
Definition: win32_port.h:369
void _dosmaperr(unsigned long)
Definition: win32error.c:177

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

Referenced by BufFileLoadBuffer(), mdread(), and ReorderBufferRestoreChanges().

◆ FileSize()

off_t FileSize ( File  file)

Definition at line 2209 of file fd.c.

2210 {
2211  Assert(FileIsValid(file));
2212 
2213  DO_DB(elog(LOG, "FileSize %d (%s)",
2214  file, VfdCache[file].fileName));
2215 
2216  if (FileIsNotOpen(file))
2217  {
2218  if (FileAccess(file) < 0)
2219  return (off_t) -1;
2220  }
2221 
2222  return lseek(VfdCache[file].fd, 0, SEEK_END);
2223 }

References Assert(), DO_DB, elog(), fd(), FileAccess(), FileIsNotOpen, FileIsValid, LOG, and VfdCache.

Referenced by _mdnblocks(), BufFileSeek(), and BufFileSize().

◆ FileSync()

int FileSync ( File  file,
uint32  wait_event_info 
)

Definition at line 2188 of file fd.c.

2189 {
2190  int returnCode;
2191 
2192  Assert(FileIsValid(file));
2193 
2194  DO_DB(elog(LOG, "FileSync: %d (%s)",
2195  file, VfdCache[file].fileName));
2196 
2197  returnCode = FileAccess(file);
2198  if (returnCode < 0)
2199  return returnCode;
2200 
2201  pgstat_report_wait_start(wait_event_info);
2202  returnCode = pg_fsync(VfdCache[file].fd);
2204 
2205  return returnCode;
2206 }

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

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

◆ FileTruncate()

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

Definition at line 2226 of file fd.c.

2227 {
2228  int returnCode;
2229 
2230  Assert(FileIsValid(file));
2231 
2232  DO_DB(elog(LOG, "FileTruncate %d (%s)",
2233  file, VfdCache[file].fileName));
2234 
2235  returnCode = FileAccess(file);
2236  if (returnCode < 0)
2237  return returnCode;
2238 
2239  pgstat_report_wait_start(wait_event_info);
2240  returnCode = ftruncate(VfdCache[file].fd, offset);
2242 
2243  if (returnCode == 0 && VfdCache[file].fileSize > offset)
2244  {
2245  /* adjust our state for truncation of a temp file */
2246  Assert(VfdCache[file].fdstate & FD_TEMP_FILE_LIMIT);
2247  temporary_files_size -= VfdCache[file].fileSize - offset;
2248  VfdCache[file].fileSize = offset;
2249  }
2250 
2251  return returnCode;
2252 }
#define ftruncate(a, b)
Definition: win32_port.h:82

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

Referenced by BufFileTruncateFileSet(), and mdtruncate().

◆ FileWrite()

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

Definition at line 2090 of file fd.c.

2092 {
2093  int returnCode;
2094  Vfd *vfdP;
2095 
2096  Assert(FileIsValid(file));
2097 
2098  DO_DB(elog(LOG, "FileWrite: %d (%s) " INT64_FORMAT " %d %p",
2099  file, VfdCache[file].fileName,
2100  (int64) offset,
2101  amount, buffer));
2102 
2103  returnCode = FileAccess(file);
2104  if (returnCode < 0)
2105  return returnCode;
2106 
2107  vfdP = &VfdCache[file];
2108 
2109  /*
2110  * If enforcing temp_file_limit and it's a temp file, check to see if the
2111  * write would overrun temp_file_limit, and throw error if so. Note: it's
2112  * really a modularity violation to throw error here; we should set errno
2113  * and return -1. However, there's no way to report a suitable error
2114  * message if we do that. All current callers would just throw error
2115  * immediately anyway, so this is safe at present.
2116  */
2117  if (temp_file_limit >= 0 && (vfdP->fdstate & FD_TEMP_FILE_LIMIT))
2118  {
2119  off_t past_write = offset + amount;
2120 
2121  if (past_write > vfdP->fileSize)
2122  {
2123  uint64 newTotal = temporary_files_size;
2124 
2125  newTotal += past_write - vfdP->fileSize;
2126  if (newTotal > (uint64) temp_file_limit * (uint64) 1024)
2127  ereport(ERROR,
2128  (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
2129  errmsg("temporary file size exceeds temp_file_limit (%dkB)",
2130  temp_file_limit)));
2131  }
2132  }
2133 
2134 retry:
2135  errno = 0;
2136  pgstat_report_wait_start(wait_event_info);
2137  returnCode = pg_pwrite(VfdCache[file].fd, buffer, amount, offset);
2139 
2140  /* if write didn't set errno, assume problem is no disk space */
2141  if (returnCode != amount && errno == 0)
2142  errno = ENOSPC;
2143 
2144  if (returnCode >= 0)
2145  {
2146  /*
2147  * Maintain fileSize and temporary_files_size if it's a temp file.
2148  */
2149  if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
2150  {
2151  off_t past_write = offset + amount;
2152 
2153  if (past_write > vfdP->fileSize)
2154  {
2155  temporary_files_size += past_write - vfdP->fileSize;
2156  vfdP->fileSize = past_write;
2157  }
2158  }
2159  }
2160  else
2161  {
2162  /*
2163  * See comments in FileRead()
2164  */
2165 #ifdef WIN32
2166  DWORD error = GetLastError();
2167 
2168  switch (error)
2169  {
2170  case ERROR_NO_SYSTEM_RESOURCES:
2171  pg_usleep(1000L);
2172  errno = EINTR;
2173  break;
2174  default:
2175  _dosmaperr(error);
2176  break;
2177  }
2178 #endif
2179  /* OK to retry if interrupted */
2180  if (errno == EINTR)
2181  goto retry;
2182  }
2183 
2184  return returnCode;
2185 }
int temp_file_limit
Definition: guc_tables.c:498
#define pg_pwrite
Definition: port.h:226

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

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

◆ FileWriteback()

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

Definition at line 2011 of file fd.c.

2012 {
2013  int returnCode;
2014 
2015  Assert(FileIsValid(file));
2016 
2017  DO_DB(elog(LOG, "FileWriteback: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
2018  file, VfdCache[file].fileName,
2019  (int64) offset, (int64) nbytes));
2020 
2021  if (nbytes <= 0)
2022  return;
2023 
2024  returnCode = FileAccess(file);
2025  if (returnCode < 0)
2026  return;
2027 
2028  pgstat_report_wait_start(wait_event_info);
2029  pg_flush_data(VfdCache[file].fd, offset, nbytes);
2031 }
void pg_flush_data(int fd, off_t offset, off_t nbytes)
Definition: fd.c:458

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

Referenced by mdwriteback().

◆ FreeDesc()

static int FreeDesc ( AllocateDesc desc)
static

Definition at line 2542 of file fd.c.

2543 {
2544  int result;
2545 
2546  /* Close the underlying object */
2547  switch (desc->kind)
2548  {
2549  case AllocateDescFile:
2550  result = fclose(desc->desc.file);
2551  break;
2552  case AllocateDescPipe:
2553  result = pclose(desc->desc.file);
2554  break;
2555  case AllocateDescDir:
2556  result = closedir(desc->desc.dir);
2557  break;
2558  case AllocateDescRawFD:
2559  result = close(desc->desc.fd);
2560  break;
2561  default:
2562  elog(ERROR, "AllocateDesc kind not recognized");
2563  result = 0; /* keep compiler quiet */
2564  break;
2565  }
2566 
2567  /* Compact storage in the allocatedDescs array */
2570 
2571  return result;
2572 }
int closedir(DIR *)
Definition: dirent.c:127

References allocatedDescs, 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().

◆ FreeDir()

int FreeDir ( DIR dir)

Definition at line 2761 of file fd.c.

2762 {
2763  int i;
2764 
2765  /* Nothing to do if AllocateDir failed */
2766  if (dir == NULL)
2767  return 0;
2768 
2769  DO_DB(elog(LOG, "FreeDir: Allocated %d", numAllocatedDescs));
2770 
2771  /* Remove dir from list of allocated dirs, if it's present */
2772  for (i = numAllocatedDescs; --i >= 0;)
2773  {
2774  AllocateDesc *desc = &allocatedDescs[i];
2775 
2776  if (desc->kind == AllocateDescDir && desc->desc.dir == dir)
2777  return FreeDesc(desc);
2778  }
2779 
2780  /* Only get here if someone passes us a dir not in allocatedDescs */
2781  elog(WARNING, "dir passed to FreeDir was not obtained from AllocateDir");
2782 
2783  return closedir(dir);
2784 }

References allocatedDescs, 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_backup_start(), dsm_cleanup_for_mmap(), extension_file_exists(), get_ext_ver_list(), GetConfFilesInDir(), 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(), RelationCacheInitFileRemove(), RelationCacheInitFileRemoveInDir(), RemoveNonParentXlogFiles(), RemoveOldXlogFiles(), RemovePgTempFiles(), RemovePgTempFilesInDir(), RemovePgTempRelationFiles(), RemovePgTempRelationFilesInDbspace(), RemoveTempXlogFiles(), ReorderBufferCleanupSerializedTXNs(), ResetUnloggedRelations(), ResetUnloggedRelationsInDbspaceDir(), ResetUnloggedRelationsInTablespaceDir(), restoreTwoPhaseData(), scan_directory_ci(), sendDir(), SlruScanDirectory(), StartupReorderBuffer(), StartupReplicationSlots(), SyncDataDirectory(), UpdateLogicalMappings(), and walkdir().

◆ FreeFile()

int FreeFile ( FILE *  file)

Definition at line 2581 of file fd.c.

2582 {
2583  int i;
2584 
2585  DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedDescs));
2586 
2587  /* Remove file from list of allocated files, if it's present */
2588  for (i = numAllocatedDescs; --i >= 0;)
2589  {
2590  AllocateDesc *desc = &allocatedDescs[i];
2591 
2592  if (desc->kind == AllocateDescFile && desc->desc.file == file)
2593  return FreeDesc(desc);
2594  }
2595 
2596  /* Only get here if someone passes us a file not in allocatedDescs */
2597  elog(WARNING, "file passed to FreeFile was not obtained from AllocateFile");
2598 
2599  return fclose(file);
2600 }

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

Referenced by AlterSystemSetConfigFile(), apw_dump_now(), apw_load_buffers(), checkControlFile(), do_pg_backup_stop(), EndCopy(), EndCopyFrom(), entry_reset(), existsTimeLineHistory(), ExportSnapshot(), free_auth_file(), gc_qtexts(), GetHugePageSize(), ImportSnapshot(), load_dh_file(), load_relcache_init_file(), parse_extension_control_file(), ParseTzFile(), pg_current_logfile(), pg_file_write_internal(), pg_promote(), pgss_shmem_shutdown(), pgss_shmem_startup(), pgstat_read_statsfile(), pgstat_write_statsfile(), read_backup_label(), read_binary_file(), read_tablespace_map(), read_whole_file(), readTimeLineHistory(), tsearch_readline_end(), ValidatePgVersion(), write_relcache_init_file(), XLogArchiveForceDone(), and XLogArchiveNotify().

◆ FreeVfd()

static void FreeVfd ( File  file)
static

Definition at line 1385 of file fd.c.

1386 {
1387  Vfd *vfdP = &VfdCache[file];
1388 
1389  DO_DB(elog(LOG, "FreeVfd: %d (%s)",
1390  file, vfdP->fileName ? vfdP->fileName : ""));
1391 
1392  if (vfdP->fileName != NULL)
1393  {
1394  free(vfdP->fileName);
1395  vfdP->fileName = NULL;
1396  }
1397  vfdP->fdstate = 0x0;
1398 
1399  vfdP->nextFree = VfdCache[0].nextFree;
1400  VfdCache[0].nextFree = file;
1401 }
#define free(a)
Definition: header.h:65

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

Referenced by FileClose(), and PathNameOpenFilePerm().

◆ fsync_fname()

◆ fsync_fname_ext()

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

Definition at line 3597 of file fd.c.

3598 {
3599  int fd;
3600  int flags;
3601  int returncode;
3602 
3603  /*
3604  * Some OSs require directories to be opened read-only whereas other
3605  * systems don't allow us to fsync files opened read-only; so we need both
3606  * cases here. Using O_RDWR will cause us to fail to fsync files that are
3607  * not writable by our userid, but we assume that's OK.
3608  */
3609  flags = PG_BINARY;
3610  if (!isdir)
3611  flags |= O_RDWR;
3612  else
3613  flags |= O_RDONLY;
3614 
3615  fd = OpenTransientFile(fname, flags);
3616 
3617  /*
3618  * Some OSs don't allow us to open directories at all (Windows returns
3619  * EACCES), just ignore the error in that case. If desired also silently
3620  * ignoring errors about unreadable files. Log others.
3621  */
3622  if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
3623  return 0;
3624  else if (fd < 0 && ignore_perm && errno == EACCES)
3625  return 0;
3626  else if (fd < 0)
3627  {
3628  ereport(elevel,
3630  errmsg("could not open file \"%s\": %m", fname)));
3631  return -1;
3632  }
3633 
3634  returncode = pg_fsync(fd);
3635 
3636  /*
3637  * Some OSes don't allow us to fsync directories at all, so we can ignore
3638  * those errors. Anything else needs to be logged.
3639  */
3640  if (returncode != 0 && !(isdir && (errno == EBADF || errno == EINVAL)))
3641  {
3642  int save_errno;
3643 
3644  /* close file upon error, might not be in transaction context */
3645  save_errno = errno;
3646  (void) CloseTransientFile(fd);
3647  errno = save_errno;
3648 
3649  ereport(elevel,
3651  errmsg("could not fsync file \"%s\": %m", fname)));
3652  return -1;
3653  }
3654 
3655  if (CloseTransientFile(fd) != 0)
3656  {
3657  ereport(elevel,
3659  errmsg("could not close file \"%s\": %m", fname)));
3660  return -1;
3661  }
3662 
3663  return 0;
3664 }

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

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

◆ fsync_parent_path()

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

Definition at line 3673 of file fd.c.

3674 {
3675  char parentpath[MAXPGPATH];
3676 
3677  strlcpy(parentpath, fname, MAXPGPATH);
3678  get_parent_directory(parentpath);
3679 
3680  /*
3681  * get_parent_directory() returns an empty string if the input argument is
3682  * just a file name (see comments in path.c), so handle that as being the
3683  * current directory.
3684  */
3685  if (strlen(parentpath) == 0)
3686  strlcpy(parentpath, ".", MAXPGPATH);
3687 
3688  if (fsync_fname_ext(parentpath, true, false, elevel) != 0)
3689  return -1;
3690 
3691  return 0;
3692 }
#define MAXPGPATH
void get_parent_directory(char *path)
Definition: path.c:977
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45

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

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

◆ GetNextTempTableSpace()

Oid GetNextTempTableSpace ( void  )

Definition at line 2911 of file fd.c.

2912 {
2913  if (numTempTableSpaces > 0)
2914  {
2915  /* Advance nextTempTableSpace counter with wraparound */
2917  nextTempTableSpace = 0;
2919  }
2920  return InvalidOid;
2921 }
static int nextTempTableSpace
Definition: fd.c:285
#define InvalidOid
Definition: postgres_ext.h:36

References InvalidOid, nextTempTableSpace, numTempTableSpaces, and tempTableSpaces.

Referenced by GetDefaultTablespace(), and OpenTemporaryFile().

◆ GetTempTablespaces()

int GetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2893 of file fd.c.

2894 {
2895  int i;
2896 
2898  for (i = 0; i < numTempTableSpaces && i < numSpaces; ++i)
2899  tableSpaces[i] = tempTableSpaces[i];
2900 
2901  return i;
2902 }
bool TempTablespacesAreSet(void)
Definition: fd.c:2878

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

Referenced by FileSetInit().

◆ InitFileAccess()

void InitFileAccess ( void  )

Definition at line 809 of file fd.c.

810 {
811  Assert(SizeVfdCache == 0); /* call me only once */
812 
813  /* initialize cache header entry */
814  VfdCache = (Vfd *) malloc(sizeof(Vfd));
815  if (VfdCache == NULL)
816  ereport(FATAL,
817  (errcode(ERRCODE_OUT_OF_MEMORY),
818  errmsg("out of memory")));
819 
820  MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
822 
823  SizeVfdCache = 1;
824 }
#define FATAL
Definition: elog.h:37
#define malloc(a)
Definition: header.h:50

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

Referenced by BaseInit().

◆ InitTemporaryFileAccess()

void InitTemporaryFileAccess ( void  )

Definition at line 839 of file fd.c.

840 {
841  Assert(SizeVfdCache != 0); /* InitFileAccess() needs to have run */
842  Assert(!temporary_files_allowed); /* call me only once */
843 
844  /*
845  * Register before-shmem-exit hook to ensure temp files are dropped while
846  * we can still report stats.
847  */
849 
850 #ifdef USE_ASSERT_CHECKING
851  temporary_files_allowed = true;
852 #endif
853 }
static void BeforeShmemExit_Files(int code, Datum arg)
Definition: fd.c:2979
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:333

References Assert(), before_shmem_exit(), BeforeShmemExit_Files(), and SizeVfdCache.

Referenced by BaseInit().

◆ Insert()

static void Insert ( File  file)
static

Definition at line 1226 of file fd.c.

1227 {
1228  Vfd *vfdP;
1229 
1230  Assert(file != 0);
1231 
1232  DO_DB(elog(LOG, "Insert %d (%s)",
1233  file, VfdCache[file].fileName));
1234  DO_DB(_dump_lru());
1235 
1236  vfdP = &VfdCache[file];
1237 
1238  vfdP->lruMoreRecently = 0;
1240  VfdCache[0].lruLessRecently = file;
1242 
1243  DO_DB(_dump_lru());
1244 }

References Assert(), DO_DB, elog(), LOG, vfd::lruLessRecently, vfd::lruMoreRecently, and VfdCache.

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

◆ looks_like_temp_rel_name()

bool looks_like_temp_rel_name ( const char *  name)

Definition at line 3249 of file fd.c.

3250 {
3251  int pos;
3252  int savepos;
3253 
3254  /* Must start with "t". */
3255  if (name[0] != 't')
3256  return false;
3257 
3258  /* Followed by a non-empty string of digits and then an underscore. */
3259  for (pos = 1; isdigit((unsigned char) name[pos]); ++pos)
3260  ;
3261  if (pos == 1 || name[pos] != '_')
3262  return false;
3263 
3264  /* Followed by another nonempty string of digits. */
3265  for (savepos = ++pos; isdigit((unsigned char) name[pos]); ++pos)
3266  ;
3267  if (savepos == pos)
3268  return false;
3269 
3270  /* We might have _forkname or .segment or both. */
3271  if (name[pos] == '_')
3272  {
3273  int forkchar = forkname_chars(&name[pos + 1], NULL);
3274 
3275  if (forkchar <= 0)
3276  return false;
3277  pos += forkchar + 1;
3278  }
3279  if (name[pos] == '.')
3280  {
3281  int segchar;
3282 
3283  for (segchar = 1; isdigit((unsigned char) name[pos + segchar]); ++segchar)
3284  ;
3285  if (segchar <= 1)
3286  return false;
3287  pos += segchar;
3288  }
3289 
3290  /* Now we should be at the end. */
3291  if (name[pos] != '\0')
3292  return false;
3293  return true;
3294 }
int forkname_chars(const char *str, ForkNumber *fork)
Definition: relpath.c:81

References forkname_chars(), and name.

Referenced by RemovePgTempRelationFilesInDbspace(), and sendDir().

◆ LruDelete()

static void LruDelete ( File  file)
static

Definition at line 1200 of file fd.c.

1201 {
1202  Vfd *vfdP;
1203 
1204  Assert(file != 0);
1205 
1206  DO_DB(elog(LOG, "LruDelete %d (%s)",
1207  file, VfdCache[file].fileName));
1208 
1209  vfdP = &VfdCache[file];
1210 
1211  /*
1212  * Close the file. We aren't expecting this to fail; if it does, better
1213  * to leak the FD than to mess up our internal state.
1214  */
1215  if (close(vfdP->fd) != 0)
1217  "could not close file \"%s\": %m", vfdP->fileName);
1218  vfdP->fd = VFD_CLOSED;
1219  --nfile;
1220 
1221  /* delete the vfd record from the LRU ring */
1222  Delete(file);
1223 }

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

Referenced by closeAllVfds(), and ReleaseLruFile().

◆ LruInsert()

static int LruInsert ( File  file)
static

Definition at line 1248 of file fd.c.

1249 {
1250  Vfd *vfdP;
1251 
1252  Assert(file != 0);
1253 
1254  DO_DB(elog(LOG, "LruInsert %d (%s)",
1255  file, VfdCache[file].fileName));
1256 
1257  vfdP = &VfdCache[file];
1258 
1259  if (FileIsNotOpen(file))
1260  {
1261  /* Close excess kernel FDs. */
1262  ReleaseLruFiles();
1263 
1264  /*
1265  * The open could still fail for lack of file descriptors, eg due to
1266  * overall system file table being full. So, be prepared to release
1267  * another FD if necessary...
1268  */
1269  vfdP->fd = BasicOpenFilePerm(vfdP->fileName, vfdP->fileFlags,
1270  vfdP->fileMode);
1271  if (vfdP->fd < 0)
1272  {
1273  DO_DB(elog(LOG, "re-open failed: %m"));
1274  return -1;
1275  }
1276  else
1277  {
1278  ++nfile;
1279  }
1280  }
1281 
1282  /*
1283  * put it at the head of the Lru ring
1284  */
1285 
1286  Insert(file);
1287 
1288  return 0;
1289 }

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

Referenced by FileAccess().

◆ MakePGDirectory()

int MakePGDirectory ( const char *  directoryName)

◆ OpenPipeStream()

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

Definition at line 2486 of file fd.c.

2487 {
2488  FILE *file;
2489  int save_errno;
2490 
2491  DO_DB(elog(LOG, "OpenPipeStream: Allocated %d (%s)",
2492  numAllocatedDescs, command));
2493 
2494  /* Can we allocate another non-virtual FD? */
2495  if (!reserveAllocatedDesc())
2496  ereport(ERROR,
2497  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2498  errmsg("exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"",
2499  maxAllocatedDescs, command)));
2500 
2501  /* Close excess kernel FDs. */
2502  ReleaseLruFiles();
2503 
2504 TryAgain:
2505  fflush(NULL);
2507  errno = 0;
2508  file = popen(command, mode);
2509  save_errno = errno;
2511  errno = save_errno;
2512  if (file != NULL)
2513  {
2515 
2516  desc->kind = AllocateDescPipe;
2517  desc->desc.file = file;
2520  return desc->desc.file;
2521  }
2522 
2523  if (errno == EMFILE || errno == ENFILE)
2524  {
2525  ereport(LOG,
2526  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2527  errmsg("out of file descriptors: %m; release and retry")));
2528  if (ReleaseLruFile())
2529  goto TryAgain;
2530  errno = save_errno;
2531  }
2532 
2533  return NULL;
2534 }
static void const char fflush(stdout)
pqsigfunc pqsignal(int signo, pqsigfunc func)
#define SIG_DFL
Definition: win32_port.h:171
#define SIGPIPE
Definition: win32_port.h:181
#define SIG_IGN
Definition: win32_port.h:173

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

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

◆ OpenTemporaryFile()

File OpenTemporaryFile ( bool  interXact)

Definition at line 1629 of file fd.c.

1630 {
1631  File file = 0;
1632 
1633  Assert(temporary_files_allowed); /* check temp file access is up */
1634 
1635  /*
1636  * Make sure the current resource owner has space for this File before we
1637  * open it, if we'll be registering it below.
1638  */
1639  if (!interXact)
1641 
1642  /*
1643  * If some temp tablespace(s) have been given to us, try to use the next
1644  * one. If a given tablespace can't be found, we silently fall back to
1645  * the database's default tablespace.
1646  *
1647  * BUT: if the temp file is slated to outlive the current transaction,
1648  * force it into the database's default tablespace, so that it will not
1649  * pose a threat to possible tablespace drop attempts.
1650  */
1651  if (numTempTableSpaces > 0 && !interXact)
1652  {
1653  Oid tblspcOid = GetNextTempTableSpace();
1654 
1655  if (OidIsValid(tblspcOid))
1656  file = OpenTemporaryFileInTablespace(tblspcOid, false);
1657  }
1658 
1659  /*
1660  * If not, or if tablespace is bad, create in database's default
1661  * tablespace. MyDatabaseTableSpace should normally be set before we get
1662  * here, but just in case it isn't, fall back to pg_default tablespace.
1663  */
1664  if (file <= 0)
1667  DEFAULTTABLESPACE_OID,
1668  true);
1669 
1670  /* Mark it for deletion at close and temporary file size limit */
1672 
1673  /* Register it with the current resource owner */
1674  if (!interXact)
1675  RegisterTemporaryFile(file);
1676 
1677  return file;
1678 }
#define OidIsValid(objectId)
Definition: c.h:711
Oid GetNextTempTableSpace(void)
Definition: fd.c:2911
static File OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
Definition: fd.c:1709
static void RegisterTemporaryFile(File file)
Definition: fd.c:1460
Oid MyDatabaseTableSpace
Definition: globals.c:91
unsigned int Oid
Definition: postgres_ext.h:31
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1290
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146

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

Referenced by BufFileCreateTemp(), and extendBufFile().

◆ OpenTemporaryFileInTablespace()

static File OpenTemporaryFileInTablespace ( Oid  tblspcOid,
bool  rejectError 
)
static

Definition at line 1709 of file fd.c.

1710 {
1711  char tempdirpath[MAXPGPATH];
1712  char tempfilepath[MAXPGPATH];
1713  File file;
1714 
1715  TempTablespacePath(tempdirpath, tblspcOid);
1716 
1717  /*
1718  * Generate a tempfile name that should be unique within the current
1719  * database instance.
1720  */
1721  snprintf(tempfilepath, sizeof(tempfilepath), "%s/%s%d.%ld",
1722  tempdirpath, PG_TEMP_FILE_PREFIX, MyProcPid, tempFileCounter++);
1723 
1724  /*
1725  * Open the file. Note: we don't use O_EXCL, in case there is an orphaned
1726  * temp file that can be reused.
1727  */
1728  file = PathNameOpenFile(tempfilepath,
1729  O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1730  if (file <= 0)
1731  {
1732  /*
1733  * We might need to create the tablespace's tempfile directory, if no
1734  * one has yet done so.
1735  *
1736  * Don't check for an error from MakePGDirectory; it could fail if
1737  * someone else just did the same thing. If it doesn't work then
1738  * we'll bomb out on the second create attempt, instead.
1739  */
1740  (void) MakePGDirectory(tempdirpath);
1741 
1742  file = PathNameOpenFile(tempfilepath,
1743  O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1744  if (file <= 0 && rejectError)
1745  elog(ERROR, "could not create temporary file \"%s\": %m",
1746  tempfilepath);
1747  }
1748 
1749  return file;
1750 }
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3713
static long tempFileCounter
Definition: fd.c:275
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1488
void TempTablespacePath(char *path, Oid tablespace)
Definition: fd.c:1684
int MyProcPid
Definition: globals.c:44
#define PG_TEMP_FILE_PREFIX
Definition: pg_checksums.c:63
#define snprintf
Definition: port.h:238

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

Referenced by OpenTemporaryFile().

◆ OpenTransientFile()

◆ OpenTransientFilePerm()

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

Definition at line 2442 of file fd.c.

2443 {
2444  int fd;
2445 
2446  DO_DB(elog(LOG, "OpenTransientFile: Allocated %d (%s)",
2447  numAllocatedDescs, fileName));
2448 
2449  /* Can we allocate another non-virtual FD? */
2450  if (!reserveAllocatedDesc())
2451  ereport(ERROR,
2452  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2453  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2454  maxAllocatedDescs, fileName)));
2455 
2456  /* Close excess kernel FDs. */
2457  ReleaseLruFiles();
2458 
2459  fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
2460 
2461  if (fd >= 0)
2462  {
2464 
2465  desc->kind = AllocateDescRawFD;
2466  desc->desc.fd = fd;
2469 
2470  return fd;
2471  }
2472 
2473  return -1; /* failure */
2474 }

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

Referenced by be_lo_export(), and OpenTransientFile().

◆ PathNameCreateTemporaryDir()

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

Definition at line 1565 of file fd.c.

1566 {
1567  if (MakePGDirectory(directory) < 0)
1568  {
1569  if (errno == EEXIST)
1570  return;
1571 
1572  /*
1573  * Failed. Try to create basedir first in case it's missing. Tolerate
1574  * EEXIST to close a race against another process following the same
1575  * algorithm.
1576  */
1577  if (MakePGDirectory(basedir) < 0 && errno != EEXIST)
1578  ereport(ERROR,
1580  errmsg("cannot create temporary directory \"%s\": %m",
1581  basedir)));
1582 
1583  /* Try again. */
1584  if (MakePGDirectory(directory) < 0 && errno != EEXIST)
1585  ereport(ERROR,
1587  errmsg("cannot create temporary subdirectory \"%s\": %m",
1588  directory)));
1589  }
1590 }
static char * basedir
static const char * directory
Definition: zic.c:634

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

Referenced by FileSetCreate().

◆ PathNameCreateTemporaryFile()

File PathNameCreateTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1766 of file fd.c.

1767 {
1768  File file;
1769 
1770  Assert(temporary_files_allowed); /* check temp file access is up */
1771 
1773 
1774  /*
1775  * Open the file. Note: we don't use O_EXCL, in case there is an orphaned
1776  * temp file that can be reused.
1777  */
1778  file = PathNameOpenFile(path, O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1779  if (file <= 0)
1780  {
1781  if (error_on_failure)
1782  ereport(ERROR,
1784  errmsg("could not create temporary file \"%s\": %m",
1785  path)));
1786  else
1787  return file;
1788  }
1789 
1790  /* Mark it for temp_file_limit accounting. */
1792 
1793  /* Register it for automatic close. */
1794  RegisterTemporaryFile(file);
1795 
1796  return file;
1797 }

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

Referenced by FileSetCreate().

◆ PathNameDeleteTemporaryDir()

void PathNameDeleteTemporaryDir ( const char *  dirname)

Definition at line 1596 of file fd.c.

1597 {
1598  struct stat statbuf;
1599 
1600  /* Silently ignore missing directory. */
1601  if (stat(dirname, &statbuf) != 0 && errno == ENOENT)
1602  return;
1603 
1604  /*
1605  * Currently, walkdir doesn't offer a way for our passed in function to
1606  * maintain state. Perhaps it should, so that we could tell the caller
1607  * whether this operation succeeded or failed. Since this operation is
1608  * used in a cleanup path, we wouldn't actually behave differently: we'll
1609  * just log failures.
1610  */
1611  walkdir(dirname, unlink_if_exists_fname, false, LOG);
1612 }
static void unlink_if_exists_fname(const char *fname, bool isdir, int elevel)
Definition: fd.c:3572
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
Definition: fd.c:3458

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

Referenced by FileSetDeleteAll().

◆ PathNameDeleteTemporaryFile()

bool PathNameDeleteTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1837 of file fd.c.

1838 {
1839  struct stat filestats;
1840  int stat_errno;
1841 
1842  /* Get the final size for pgstat reporting. */
1843  if (stat(path, &filestats) != 0)
1844  stat_errno = errno;
1845  else
1846  stat_errno = 0;
1847 
1848  /*
1849  * Unlike FileClose's automatic file deletion code, we tolerate
1850  * non-existence to support BufFileDeleteFileSet which doesn't know how
1851  * many segments it has to delete until it runs out.
1852  */
1853  if (stat_errno == ENOENT)
1854  return false;
1855 
1856  if (unlink(path) < 0)
1857  {
1858  if (errno != ENOENT)
1859  ereport(error_on_failure ? ERROR : LOG,
1861  errmsg("could not unlink temporary file \"%s\": %m",
1862  path)));
1863  return false;
1864  }
1865 
1866  if (stat_errno == 0)
1867  ReportTemporaryFileUsage(path, filestats.st_size);
1868  else
1869  {
1870  errno = stat_errno;
1871  ereport(LOG,
1873  errmsg("could not stat file \"%s\": %m", path)));
1874  }
1875 
1876  return true;
1877 }

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

Referenced by FileSetDelete(), and unlink_if_exists_fname().

◆ PathNameOpenFile()

File PathNameOpenFile ( const char *  fileName,
int  fileFlags 
)

◆ PathNameOpenFilePerm()

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

Definition at line 1501 of file fd.c.

1502 {
1503  char *fnamecopy;
1504  File file;
1505  Vfd *vfdP;
1506 
1507  DO_DB(elog(LOG, "PathNameOpenFilePerm: %s %x %o",
1508  fileName, fileFlags, fileMode));
1509 
1510  /*
1511  * We need a malloc'd copy of the file name; fail cleanly if no room.
1512  */
1513  fnamecopy = strdup(fileName);
1514  if (fnamecopy == NULL)
1515  ereport(ERROR,
1516  (errcode(ERRCODE_OUT_OF_MEMORY),
1517  errmsg("out of memory")));
1518 
1519  file = AllocateVfd();
1520  vfdP = &VfdCache[file];
1521 
1522  /* Close excess kernel FDs. */
1523  ReleaseLruFiles();
1524 
1525  vfdP->fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
1526 
1527  if (vfdP->fd < 0)
1528  {
1529  int save_errno = errno;
1530 
1531  FreeVfd(file);
1532  free(fnamecopy);
1533  errno = save_errno;
1534  return -1;
1535  }
1536  ++nfile;
1537  DO_DB(elog(LOG, "PathNameOpenFile: success %d",
1538  vfdP->fd));
1539 
1540  vfdP->fileName = fnamecopy;
1541  /* Saved flags are adjusted to be OK for re-opening file */
1542  vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
1543  vfdP->fileMode = fileMode;
1544  vfdP->fileSize = 0;
1545  vfdP->fdstate = 0x0;
1546  vfdP->resowner = NULL;
1547 
1548  Insert(file);
1549 
1550  return file;
1551 }
static File AllocateVfd(void)
Definition: fd.c:1327

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 VfdCache.

Referenced by PathNameOpenFile().

◆ PathNameOpenTemporaryFile()

File PathNameOpenTemporaryFile ( const char *  path,
int  mode 
)

Definition at line 1806 of file fd.c.

1807 {
1808  File file;
1809 
1810  Assert(temporary_files_allowed); /* check temp file access is up */
1811 
1813 
1814  file = PathNameOpenFile(path, mode | PG_BINARY);
1815 
1816  /* If no such file, then we don't raise an error. */
1817  if (file <= 0 && errno != ENOENT)
1818  ereport(ERROR,
1820  errmsg("could not open temporary file \"%s\": %m",
1821  path)));
1822 
1823  if (file > 0)
1824  {
1825  /* Register it for automatic close. */
1826  RegisterTemporaryFile(file);
1827  }
1828 
1829  return file;
1830 }

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

Referenced by FileSetOpen().

◆ pg_fdatasync()

int pg_fdatasync ( int  fd)

Definition at line 444 of file fd.c.

445 {
446  if (enableFsync)
447  return fdatasync(fd);
448  else
449  return 0;
450 }
int fdatasync(int fildes)
bool enableFsync
Definition: globals.c:123

References enableFsync, fd(), and fdatasync().

Referenced by issue_xlog_fsync().

◆ pg_flush_data()

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

Definition at line 458 of file fd.c.

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

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

Referenced by copy_file(), and FileWriteback().

◆ pg_fsync()

int pg_fsync ( int  fd)

Definition at line 356 of file fd.c.

357 {
358 #if !defined(WIN32) && defined(USE_ASSERT_CHECKING)
359  struct stat st;
360 
361  /*
362  * Some operating system implementations of fsync() have requirements
363  * about the file access modes that were used when their file descriptor
364  * argument was opened, and these requirements differ depending on whether
365  * the file descriptor is for a directory.
366  *
367  * For any file descriptor that may eventually be handed to fsync(), we
368  * should have opened it with access modes that are compatible with
369  * fsync() on all supported systems, otherwise the code may not be
370  * portable, even if it runs ok on the current system.
371  *
372  * We assert here that a descriptor for a file was opened with write
373  * permissions (either O_RDWR or O_WRONLY) and for a directory without
374  * write permissions (O_RDONLY).
375  *
376  * Ignore any fstat errors and let the follow-up fsync() do its work.
377  * Doing this sanity check here counts for the case where fsync() is
378  * disabled.
379  */
380  if (fstat(fd, &st) == 0)
381  {
382  int desc_flags = fcntl(fd, F_GETFL);
383 
384  /*
385  * O_RDONLY is historically 0, so just make sure that for directories
386  * no write flags are used.
387  */
388  if (S_ISDIR(st.st_mode))
389  Assert((desc_flags & (O_RDWR | O_WRONLY)) == 0);
390  else
391  Assert((desc_flags & (O_RDWR | O_WRONLY)) != 0);
392  }
393  errno = 0;
394 #endif
395 
396  /* #if is to skip the sync_method test if there's no need for it */
397 #if defined(HAVE_FSYNC_WRITETHROUGH) && !defined(FSYNC_WRITETHROUGH_IS_FSYNC)
399  return pg_fsync_writethrough(fd);
400  else
401 #endif
403 }
int pg_fsync_no_writethrough(int fd)
Definition: fd.c:411
int pg_fsync_writethrough(int fd)
Definition: fd.c:423
#define S_ISDIR(m)
Definition: win32_port.h:327
#define fstat
Definition: win32_port.h:285
int sync_method
Definition: xlog.c:133
#define SYNC_METHOD_FSYNC_WRITETHROUGH
Definition: xlog.h:25

References Assert(), fd(), fstat, pg_fsync_no_writethrough(), pg_fsync_writethrough(), S_ISDIR, stat::st_mode, sync_method, and SYNC_METHOD_FSYNC_WRITETHROUGH.

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

◆ pg_fsync_no_writethrough()

int pg_fsync_no_writethrough ( int  fd)

Definition at line 411 of file fd.c.

412 {
413  if (enableFsync)
414  return fsync(fd);
415  else
416  return 0;
417 }
#define fsync(fd)
Definition: win32_port.h:85

References enableFsync, fd(), and fsync.

Referenced by issue_xlog_fsync(), and pg_fsync().

◆ pg_fsync_writethrough()

int pg_fsync_writethrough ( int  fd)

Definition at line 423 of file fd.c.

424 {
425  if (enableFsync)
426  {
427 #ifdef WIN32
428  return _commit(fd);
429 #elif defined(F_FULLFSYNC)
430  return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
431 #else
432  errno = ENOSYS;
433  return -1;
434 #endif
435  }
436  else
437  return 0;
438 }

References enableFsync, and fd().

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

◆ pg_truncate()

int pg_truncate ( const char *  path,
off_t  length 
)

Definition at line 631 of file fd.c.

632 {
633 #ifdef WIN32
634  int save_errno;
635  int ret;
636  int fd;
637 
638  fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
639  if (fd >= 0)
640  {
641  ret = ftruncate(fd, 0);
642  save_errno = errno;
644  errno = save_errno;
645  }
646  else
647  ret = -1;
648 
649  return ret;
650 #else
651  return truncate(path, length);
652 #endif
653 }

References CloseTransientFile(), fd(), ftruncate, OpenTransientFile(), and PG_BINARY.

Referenced by do_truncate().

◆ ReadDir()

◆ ReadDirExtended()

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

Definition at line 2724 of file fd.c.

2725 {
2726  struct dirent *dent;
2727 
2728  /* Give a generic message for AllocateDir failure, if caller didn't */
2729  if (dir == NULL)
2730  {
2731  ereport(elevel,
2733  errmsg("could not open directory \"%s\": %m",
2734  dirname)));
2735  return NULL;
2736  }
2737 
2738  errno = 0;
2739  if ((dent = readdir(dir)) != NULL)
2740  return dent;
2741 
2742  if (errno)
2743  ereport(elevel,
2745  errmsg("could not read directory \"%s\": %m",
2746  dirname)));
2747  return NULL;
2748 }
struct dirent * readdir(DIR *)
Definition: dirent.c:78
Definition: dirent.h:10

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

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

◆ RegisterTemporaryFile()

static void RegisterTemporaryFile ( File  file)
static

Definition at line 1460 of file fd.c.

1461 {
1464 
1465  /* Backup mechanism for closing at end of xact. */
1468 }
void ResourceOwnerRememberFile(ResourceOwner owner, File file)
Definition: resowner.c:1301

References CurrentResourceOwner, FD_CLOSE_AT_EOXACT, vfd::fdstate, have_xact_temporary_files, ResourceOwnerRememberFile(), vfd::resowner, and VfdCache.

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

◆ ReleaseExternalFD()

◆ ReleaseLruFile()

static bool ReleaseLruFile ( void  )
static

Definition at line 1295 of file fd.c.

1296 {
1297  DO_DB(elog(LOG, "ReleaseLruFile. Opened %d", nfile));
1298 
1299  if (nfile > 0)
1300  {
1301  /*
1302  * There are opened files and so there should be at least one used vfd
1303  * in the ring.
1304  */
1305  Assert(VfdCache[0].lruMoreRecently != 0);
1306  LruDelete(VfdCache[0].lruMoreRecently);
1307  return true; /* freed a file */
1308  }
1309  return false; /* no files available to free */
1310 }

References Assert(), DO_DB, elog(), LOG, LruDelete(), nfile, and VfdCache.

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

◆ ReleaseLruFiles()

static void ReleaseLruFiles ( void  )
static

Definition at line 1317 of file fd.c.

1318 {
1320  {
1321  if (!ReleaseLruFile())
1322  break;
1323  }
1324 }

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

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

◆ RemovePgTempFiles()

void RemovePgTempFiles ( void  )

Definition at line 3074 of file fd.c.

3075 {
3076  char temp_path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY) + sizeof(PG_TEMP_FILES_DIR)];
3077  DIR *spc_dir;
3078  struct dirent *spc_de;
3079 
3080  /*
3081  * First process temp files in pg_default ($PGDATA/base)
3082  */
3083  snprintf(temp_path, sizeof(temp_path), "base/%s", PG_TEMP_FILES_DIR);
3084  RemovePgTempFilesInDir(temp_path, true, false);
3085  RemovePgTempRelationFiles("base");
3086 
3087  /*
3088  * Cycle through temp directories for all non-default tablespaces.
3089  */
3090  spc_dir = AllocateDir("pg_tblspc");
3091 
3092  while ((spc_de = ReadDirExtended(spc_dir, "pg_tblspc", LOG)) != NULL)
3093  {
3094  if (strcmp(spc_de->d_name, ".") == 0 ||
3095  strcmp(spc_de->d_name, "..") == 0)
3096  continue;
3097 
3098  snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s/%s",
3100  RemovePgTempFilesInDir(temp_path, true, false);
3101 
3102  snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s",
3104  RemovePgTempRelationFiles(temp_path);
3105  }
3106 
3107  FreeDir(spc_dir);
3108 
3109  /*
3110  * In EXEC_BACKEND case there is a pgsql_tmp directory at the top level of
3111  * DataDir as well. However, that is *not* cleaned here because doing so
3112  * would create a race condition. It's done separately, earlier in
3113  * postmaster startup.
3114  */
3115 }
int FreeDir(DIR *dir)
Definition: fd.c:2761
static void RemovePgTempRelationFiles(const char *tsdirname)
Definition: fd.c:3193
void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, bool unlink_all)
Definition: fd.c:3133
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2643
#define PG_TEMP_FILES_DIR
Definition: pg_checksums.c:62
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:33
char d_name[MAX_PATH]
Definition: dirent.h:15

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

Referenced by PostmasterMain(), and PostmasterStateMachine().

◆ RemovePgTempFilesInDir()

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

Definition at line 3133 of file fd.c.

3134 {
3135  DIR *temp_dir;
3136  struct dirent *temp_de;
3137  char rm_path[MAXPGPATH * 2];
3138 
3139  temp_dir = AllocateDir(tmpdirname);
3140 
3141  if (temp_dir == NULL && errno == ENOENT && missing_ok)
3142  return;
3143 
3144  while ((temp_de = ReadDirExtended(temp_dir, tmpdirname, LOG)) != NULL)
3145  {
3146  if (strcmp(temp_de->d_name, ".") == 0 ||
3147  strcmp(temp_de->d_name, "..") == 0)
3148  continue;
3149 
3150  snprintf(rm_path, sizeof(rm_path), "%s/%s",
3151  tmpdirname, temp_de->d_name);
3152 
3153  if (unlink_all ||
3154  strncmp(temp_de->d_name,
3156  strlen(PG_TEMP_FILE_PREFIX)) == 0)
3157  {
3158  PGFileType type = get_dirent_type(rm_path, temp_de, false, LOG);
3159 
3160  if (type == PGFILETYPE_ERROR)
3161  continue;
3162  else if (type == PGFILETYPE_DIR)
3163  {
3164  /* recursively remove contents, then directory itself */
3165  RemovePgTempFilesInDir(rm_path, false, true);
3166 
3167  if (rmdir(rm_path) < 0)
3168  ereport(LOG,
3170  errmsg("could not remove directory \"%s\": %m",
3171  rm_path)));
3172  }
3173  else
3174  {
3175  if (unlink(rm_path) < 0)
3176  ereport(LOG,
3178  errmsg("could not remove file \"%s\": %m",
3179  rm_path)));
3180  }
3181  }
3182  else
3183  ereport(LOG,
3184  (errmsg("unexpected file found in temporary-files directory: \"%s\"",
3185  rm_path)));
3186  }
3187 
3188  FreeDir(temp_dir);
3189 }
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:406
PGFileType
Definition: file_utils.h:19
@ PGFILETYPE_DIR
Definition: file_utils.h:23
@ PGFILETYPE_ERROR
Definition: file_utils.h:20

References AllocateDir(), dirent::d_name, ereport, errcode_for_file_access(), errmsg(), FreeDir(), get_dirent_type(), LOG, MAXPGPATH, PG_TEMP_FILE_PREFIX, PGFILETYPE_DIR, PGFILETYPE_ERROR, ReadDirExtended(), snprintf, and generate_unaccent_rules::type.

Referenced by PostmasterMain(), and RemovePgTempFiles().

◆ RemovePgTempRelationFiles()

static void RemovePgTempRelationFiles ( const char *  tsdirname)
static

Definition at line 3193 of file fd.c.

3194 {
3195  DIR *ts_dir;
3196  struct dirent *de;
3197  char dbspace_path[MAXPGPATH * 2];
3198 
3199  ts_dir = AllocateDir(tsdirname);
3200 
3201  while ((de = ReadDirExtended(ts_dir, tsdirname, LOG)) != NULL)
3202  {
3203  /*
3204  * We're only interested in the per-database directories, which have
3205  * numeric names. Note that this code will also (properly) ignore "."
3206  * and "..".
3207  */
3208  if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
3209  continue;
3210 
3211  snprintf(dbspace_path, sizeof(dbspace_path), "%s/%s",
3212  tsdirname, de->d_name);
3213  RemovePgTempRelationFilesInDbspace(dbspace_path);
3214  }
3215 
3216  FreeDir(ts_dir);
3217 }
static void RemovePgTempRelationFilesInDbspace(const char *dbspacedirname)
Definition: fd.c:3221

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

Referenced by RemovePgTempFiles().

◆ RemovePgTempRelationFilesInDbspace()

static void RemovePgTempRelationFilesInDbspace ( const char *  dbspacedirname)
static

Definition at line 3221 of file fd.c.

3222 {
3223  DIR *dbspace_dir;
3224  struct dirent *de;
3225  char rm_path[MAXPGPATH * 2];
3226 
3227  dbspace_dir = AllocateDir(dbspacedirname);
3228 
3229  while ((de = ReadDirExtended(dbspace_dir, dbspacedirname, LOG)) != NULL)
3230  {
3231  if (!looks_like_temp_rel_name(de->d_name))
3232  continue;
3233 
3234  snprintf(rm_path, sizeof(rm_path), "%s/%s",
3235  dbspacedirname, de->d_name);
3236 
3237  if (unlink(rm_path) < 0)
3238  ereport(LOG,
3240  errmsg("could not remove file \"%s\": %m",
3241  rm_path)));
3242  }
3243 
3244  FreeDir(dbspace_dir);
3245 }
bool looks_like_temp_rel_name(const char *name)
Definition: fd.c:3249

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

◆ ReportTemporaryFileUsage()

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

Definition at line 1441 of file fd.c.

1442 {
1443  pgstat_report_tempfile(size);
1444 
1445  if (log_temp_files >= 0)
1446  {
1447  if ((size / 1024) >= log_temp_files)
1448  ereport(LOG,
1449  (errmsg("temporary file: path \"%s\", size %lu",
1450  path, (unsigned long) size)));
1451  }
1452 }
int log_temp_files
Definition: guc_tables.c:492
void pgstat_report_tempfile(size_t filesize)

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

Referenced by FileClose(), and PathNameDeleteTemporaryFile().

◆ reserveAllocatedDesc()

static bool reserveAllocatedDesc ( void  )
static

Definition at line 2308 of file fd.c.

2309 {
2310  AllocateDesc *newDescs;
2311  int newMax;
2312 
2313  /* Quick out if array already has a free slot. */
2315  return true;
2316 
2317  /*
2318  * If the array hasn't yet been created in the current process, initialize
2319  * it with FD_MINFREE / 3 elements. In many scenarios this is as many as
2320  * we will ever need, anyway. We don't want to look at max_safe_fds
2321  * immediately because set_max_safe_fds() may not have run yet.
2322  */
2323  if (allocatedDescs == NULL)
2324  {
2325  newMax = FD_MINFREE / 3;
2326  newDescs = (AllocateDesc *) malloc(newMax * sizeof(AllocateDesc));
2327  /* Out of memory already? Treat as fatal error. */
2328  if (newDescs == NULL)
2329  ereport(ERROR,
2330  (errcode(ERRCODE_OUT_OF_MEMORY),
2331  errmsg("out of memory")));
2332  allocatedDescs = newDescs;
2333  maxAllocatedDescs = newMax;
2334  return true;
2335  }
2336 
2337  /*
2338  * Consider enlarging the array beyond the initial allocation used above.
2339  * By the time this happens, max_safe_fds should be known accurately.
2340  *
2341  * We mustn't let allocated descriptors hog all the available FDs, and in
2342  * practice we'd better leave a reasonable number of FDs for VFD use. So
2343  * set the maximum to max_safe_fds / 3. (This should certainly be at
2344  * least as large as the initial size, FD_MINFREE / 3, so we aren't
2345  * tightening the restriction here.) Recall that "external" FDs are
2346  * allowed to consume another third of max_safe_fds.
2347  */
2348  newMax = max_safe_fds / 3;
2349  if (newMax > maxAllocatedDescs)
2350  {
2351  newDescs = (AllocateDesc *) realloc(allocatedDescs,
2352  newMax * sizeof(AllocateDesc));
2353  /* Treat out-of-memory as a non-fatal error. */
2354  if (newDescs == NULL)
2355  return false;
2356  allocatedDescs = newDescs;
2357  maxAllocatedDescs = newMax;
2358  return true;
2359  }
2360 
2361  /* Can't enlarge allocatedDescs[] any more. */
2362  return false;
2363 }
#define FD_MINFREE
Definition: fd.c:136

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

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

◆ ReserveExternalFD()

void ReserveExternalFD ( void  )

Definition at line 1134 of file fd.c.

1135 {
1136  /*
1137  * Release VFDs if needed to stay safe. Because we do this before
1138  * incrementing numExternalFDs, the final state will be as desired, i.e.,
1139  * nfile + numAllocatedDescs + numExternalFDs <= max_safe_fds.
1140  */
1141  ReleaseLruFiles();
1142 
1143  numExternalFDs++;
1144 }

References numExternalFDs, and ReleaseLruFiles().

Referenced by AcquireExternalFD(), BackendInitialize(), dsm_impl_posix(), InitializeLatchSupport(), InitPostmasterDeathWatchHandle(), and XLogWrite().

◆ set_max_safe_fds()

void set_max_safe_fds ( void  )

Definition at line 950 of file fd.c.

951 {
952  int usable_fds;
953  int already_open;
954 
955  /*----------
956  * We want to set max_safe_fds to
957  * MIN(usable_fds, max_files_per_process - already_open)
958  * less the slop factor for files that are opened without consulting
959  * fd.c. This ensures that we won't exceed either max_files_per_process
960  * or the experimentally-determined EMFILE limit.
961  *----------
962  */
964  &usable_fds, &already_open);
965 
966  max_safe_fds = Min(usable_fds, max_files_per_process - already_open);
967 
968  /*
969  * Take off the FDs reserved for system() etc.
970  */
972 
973  /*
974  * Make sure we still have enough to get by.
975  */
976  if (max_safe_fds < FD_MINFREE)
977  ereport(FATAL,
978  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
979  errmsg("insufficient file descriptors available to start server process"),
980  errdetail("System allows %d, server needs at least %d.",
983 
984  elog(DEBUG2, "max_safe_fds = %d, usable_fds = %d, already_open = %d",
985  max_safe_fds, usable_fds, already_open);
986 }
#define Min(x, y)
Definition: c.h:937
int errdetail(const char *fmt,...)
Definition: elog.c:1039
#define DEBUG2
Definition: elog.h:25
int max_files_per_process
Definition: fd.c:144
static void count_usable_fds(int max_to_probe, int *usable_fds, int *already_open)
Definition: fd.c:870
#define NUM_RESERVED_FDS
Definition: fd.c:127

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

◆ SetTempTablespaces()

void SetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2849 of file fd.c.

2850 {
2851  Assert(numSpaces >= 0);
2852  tempTableSpaces = tableSpaces;
2853  numTempTableSpaces = numSpaces;
2854 
2855  /*
2856  * Select a random starting point in the list. This is to minimize
2857  * conflicts between backends that are most likely sharing the same list
2858  * of temp tablespaces. Note that if we create multiple temp files in the
2859  * same transaction, we'll advance circularly through the list --- this
2860  * ensures that large temporary sort files are nicely spread across all
2861  * available tablespaces.
2862  */
2863  if (numSpaces > 1)
2865  0, numSpaces - 1);
2866  else
2867  nextTempTableSpace = 0;
2868 }
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition: pg_prng.c:138
pg_prng_state pg_global_prng_state
Definition: pg_prng.c:28

References Assert(), nextTempTableSpace, numTempTableSpaces, pg_global_prng_state, pg_prng_uint64_range(), and tempTableSpaces.

Referenced by assign_temp_tablespaces(), and PrepareTempTablespaces().

◆ SyncDataDirectory()

void SyncDataDirectory ( void  )

Definition at line 3344 of file fd.c.

3345 {
3346  bool xlog_is_symlink;
3347 
3348  /* We can skip this whole thing if fsync is disabled. */
3349  if (!enableFsync)
3350  return;
3351 
3352  /*
3353  * If pg_wal is a symlink, we'll need to recurse into it separately,
3354  * because the first walkdir below will ignore it.
3355  */
3356  xlog_is_symlink = false;
3357 
3358  {
3359  struct stat st;
3360 
3361  if (lstat("pg_wal", &st) < 0)
3362  ereport(LOG,
3364  errmsg("could not stat file \"%s\": %m",
3365  "pg_wal")));
3366  else if (S_ISLNK(st.st_mode))
3367  xlog_is_symlink = true;
3368  }
3369 
3370 #ifdef HAVE_SYNCFS
3372  {
3373  DIR *dir;
3374  struct dirent *de;
3375 
3376  /*
3377  * On Linux, we don't have to open every single file one by one. We
3378  * can use syncfs() to sync whole filesystems. We only expect
3379  * filesystem boundaries to exist where we tolerate symlinks, namely
3380  * pg_wal and the tablespaces, so we call syncfs() for each of those
3381  * directories.
3382  */
3383 
3384  /* Prepare to report progress syncing the data directory via syncfs. */
3386 
3387  /* Sync the top level pgdata directory. */
3388  do_syncfs(".");
3389  /* If any tablespaces are configured, sync each of those. */
3390  dir = AllocateDir("pg_tblspc");
3391  while ((de = ReadDirExtended(dir, "pg_tblspc", LOG)))
3392  {
3393  char path[MAXPGPATH];
3394 
3395  if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
3396  continue;
3397 
3398  snprintf(path, MAXPGPATH, "pg_tblspc/%s", de->d_name);
3399  do_syncfs(path);
3400  }
3401  FreeDir(dir);
3402  /* If pg_wal is a symlink, process that too. */
3403  if (xlog_is_symlink)
3404  do_syncfs("pg_wal");
3405  return;
3406  }
3407 #endif /* !HAVE_SYNCFS */
3408 
3409 #ifdef PG_FLUSH_DATA_WORKS
3410  /* Prepare to report progress of the pre-fsync phase. */
3412 
3413  /*
3414  * If possible, hint to the kernel that we're soon going to fsync the data
3415  * directory and its contents. Errors in this step are even less
3416  * interesting than normal, so log them only at DEBUG1.
3417  */
3418  walkdir(".", pre_sync_fname, false, DEBUG1);
3419  if (xlog_is_symlink)
3420  walkdir("pg_wal", pre_sync_fname, false, DEBUG1);
3421  walkdir("pg_tblspc", pre_sync_fname, true, DEBUG1);
3422 #endif
3423 
3424  /* Prepare to report progress syncing the data directory via fsync. */
3426 
3427  /*
3428  * Now we do the fsync()s in the same order.
3429  *
3430  * The main call ignores symlinks, so in addition to specially processing
3431  * pg_wal if it's a symlink, pg_tblspc has to be visited separately with
3432  * process_symlinks = true. Note that if there are any plain directories
3433  * in pg_tblspc, they'll get fsync'd twice. That's not an expected case
3434  * so we don't worry about optimizing it.
3435  */
3436  walkdir(".", datadir_fsync_fname, false, LOG);
3437  if (xlog_is_symlink)
3438  walkdir("pg_wal", datadir_fsync_fname, false, LOG);
3439  walkdir("pg_tblspc", datadir_fsync_fname, true, LOG);
3440 }
void begin_startup_progress_phase(void)
Definition: startup.c:321
#define DEBUG1
Definition: elog.h:26
int recovery_init_sync_method
Definition: fd.c:163
static void datadir_fsync_fname(const char *fname, bool isdir, int elevel)
Definition: fd.c:3559
@ RECOVERY_INIT_SYNC_METHOD_SYNCFS
Definition: fd.h:51
#define lstat(path, sb)
Definition: win32_port.h:287
#define S_ISLNK(m)
Definition: win32_port.h:346

References AllocateDir(), begin_startup_progress_phase(), dirent::d_name, datadir_fsync_fname(), DEBUG1, enableFsync, ereport, errcode_for_file_access(), errmsg(), FreeDir(), LOG, lstat, MAXPGPATH, ReadDirExtended(), recovery_init_sync_method, RECOVERY_INIT_SYNC_METHOD_SYNCFS, S_ISLNK, snprintf, stat::st_mode, and walkdir().

Referenced by StartupXLOG().

◆ TempTablespacePath()

void TempTablespacePath ( char *  path,
Oid  tablespace 
)

Definition at line 1684 of file fd.c.

1685 {
1686  /*
1687  * Identify the tempfile directory for this tablespace.
1688  *
1689  * If someone tries to specify pg_global, use pg_default instead.
1690  */
1691  if (tablespace == InvalidOid ||
1692  tablespace == DEFAULTTABLESPACE_OID ||
1693  tablespace == GLOBALTABLESPACE_OID)
1694  snprintf(path, MAXPGPATH, "base/%s", PG_TEMP_FILES_DIR);
1695  else
1696  {
1697  /* All other tablespaces are accessed via symlinks */
1698  snprintf(path, MAXPGPATH, "pg_tblspc/%u/%s/%s",
1701  }
1702 }
char * tablespace
Definition: pgbench.c:225

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

Referenced by FileSetCreate(), FileSetPath(), OpenTemporaryFileInTablespace(), and pg_ls_tmpdir().

◆ TempTablespacesAreSet()

bool TempTablespacesAreSet ( void  )

Definition at line 2878 of file fd.c.

2879 {
2880  return (numTempTableSpaces >= 0);
2881 }

References numTempTableSpaces.

Referenced by GetTempTablespaces(), and PrepareTempTablespaces().

◆ unlink_if_exists_fname()

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

Definition at line 3572 of file fd.c.

3573 {
3574  if (isdir)
3575  {
3576  if (rmdir(fname) != 0 && errno != ENOENT)
3577  ereport(elevel,
3579  errmsg("could not remove directory \"%s\": %m", fname)));
3580  }
3581  else
3582  {
3583  /* Use PathNameDeleteTemporaryFile to report filesize */
3584  PathNameDeleteTemporaryFile(fname, false);
3585  }
3586 }
bool PathNameDeleteTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1837

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

Referenced by PathNameDeleteTemporaryDir().

◆ 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 3458 of file fd.c.

3462 {
3463  DIR *dir;
3464  struct dirent *de;
3465 
3466  dir = AllocateDir(path);
3467 
3468  while ((de = ReadDirExtended(dir, path, elevel)) != NULL)
3469  {
3470  char subpath[MAXPGPATH * 2];
3471 
3473 
3474  if (strcmp(de->d_name, ".") == 0 ||
3475  strcmp(de->d_name, "..") == 0)
3476  continue;
3477 
3478  snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name);
3479 
3480  switch (get_dirent_type(subpath, de, process_symlinks, elevel))
3481  {
3482  case PGFILETYPE_REG:
3483  (*action) (subpath, false, elevel);
3484  break;
3485  case PGFILETYPE_DIR:
3486  walkdir(subpath, action, false, elevel);
3487  break;
3488  default:
3489 
3490  /*
3491  * Errors are already reported directly by get_dirent_type(),
3492  * and any remaining symlinks and unknown file types are
3493  * ignored.
3494  */
3495  break;
3496  }
3497  }
3498 
3499  FreeDir(dir); /* we ignore any error here */
3500 
3501  /*
3502  * It's important to fsync the destination directory itself as individual
3503  * file fsyncs don't guarantee that the directory entry for the file is
3504  * synced. However, skip this if AllocateDir failed; the action function
3505  * might not be robust against that.
3506  */
3507  if (dir)
3508  (*action) (path, true, elevel);
3509 }
@ PGFILETYPE_REG
Definition: file_utils.h:22
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:241
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121

References generate_unaccent_rules::action, AllocateDir(), CHECK_FOR_INTERRUPTS, dirent::d_name, FreeDir(), get_dirent_type(), MAXPGPATH, PGFILETYPE_DIR, PGFILETYPE_REG, ReadDirExtended(), snprintf, and subpath().

Referenced by PathNameDeleteTemporaryDir(), and SyncDataDirectory().

Variable Documentation

◆ allocatedDescs

◆ data_sync_retry

bool data_sync_retry = false

Definition at line 160 of file fd.c.

Referenced by data_sync_elevel().

◆ have_xact_temporary_files

bool have_xact_temporary_files = false
static

Definition at line 223 of file fd.c.

Referenced by CleanupTempFiles(), and RegisterTemporaryFile().

◆ max_files_per_process

int max_files_per_process = 1000

Definition at line 144 of file fd.c.

Referenced by set_max_safe_fds().

◆ max_safe_fds

int max_safe_fds = FD_MINFREE

Definition at line 157 of file fd.c.

Referenced by AcquireExternalFD(), ReleaseLruFiles(), reserveAllocatedDesc(), and set_max_safe_fds().

◆ maxAllocatedDescs

int maxAllocatedDescs = 0
static

◆ nextTempTableSpace

int nextTempTableSpace = 0
static

Definition at line 285 of file fd.c.

Referenced by GetNextTempTableSpace(), and SetTempTablespaces().

◆ nfile

int nfile = 0
static

◆ numAllocatedDescs

◆ numExternalFDs

int numExternalFDs = 0
static

Definition at line 269 of file fd.c.

Referenced by AcquireExternalFD(), ReleaseExternalFD(), ReleaseLruFiles(), and ReserveExternalFD().

◆ numTempTableSpaces

int numTempTableSpaces = -1
static

◆ recovery_init_sync_method

int recovery_init_sync_method = RECOVERY_INIT_SYNC_METHOD_FSYNC

Definition at line 163 of file fd.c.

Referenced by SyncDataDirectory().

◆ SizeVfdCache

Size SizeVfdCache = 0
static

◆ tempFileCounter

long tempFileCounter = 0
static

Definition at line 275 of file fd.c.

Referenced by OpenTemporaryFileInTablespace().

◆ temporary_files_size

uint64 temporary_files_size = 0
static

Definition at line 231 of file fd.c.

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

◆ tempTableSpaces

Oid* tempTableSpaces = NULL
static

◆ VfdCache