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/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 "miscadmin.h"
#include "pgstat.h"
#include "port/pg_iovec.h"
#include "portability/mem.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "utils/guc.h"
#include "utils/resowner_private.h"
Include dependency graph for fd.c:

Go to the source code of this file.

Data Structures

struct  vfd
 
struct  AllocateDesc
 

Macros

#define NUM_RESERVED_FDS   10
 
#define FD_MINFREE   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)
 
int durable_rename_excl (const char *oldfile, const char *newfile, 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)
 
ssize_t pg_pwritev_with_retry (int fd, const struct iovec *iov, int iovcnt, off_t offset)
 

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

◆ FD_CLOSE_AT_EOXACT

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

Definition at line 189 of file fd.c.

Referenced by CleanupTempFiles(), and RegisterTemporaryFile().

◆ FD_DELETE_AT_CLOSE

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

Definition at line 188 of file fd.c.

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

◆ FD_MINFREE

#define FD_MINFREE   48

Definition at line 137 of file fd.c.

Referenced by reserveAllocatedDesc(), and set_max_safe_fds().

◆ FD_TEMP_FILE_LIMIT

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

◆ FileIsNotOpen

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

◆ FileIsValid

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

◆ NUM_RESERVED_FDS

#define NUM_RESERVED_FDS   10

Definition at line 128 of file fd.c.

Referenced by set_max_safe_fds().

◆ VFD_CLOSED

#define VFD_CLOSED   (-1)

Definition at line 180 of file fd.c.

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

Typedef Documentation

◆ Vfd

typedef struct vfd Vfd

Enumeration Type Documentation

◆ AllocateDescKind

Enumerator
AllocateDescFile 
AllocateDescPipe 
AllocateDescDir 
AllocateDescRawFD 

Definition at line 243 of file fd.c.

Function Documentation

◆ AcquireExternalFD()

bool AcquireExternalFD ( void  )

Definition at line 1175 of file fd.c.

References max_safe_fds, numExternalFDs, and ReserveExternalFD().

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

1176 {
1177  /*
1178  * We don't want more than max_safe_fds / 3 FDs to be consumed for
1179  * "external" FDs.
1180  */
1181  if (numExternalFDs < max_safe_fds / 3)
1182  {
1184  return true;
1185  }
1186  errno = EMFILE;
1187  return false;
1188 }
static int numExternalFDs
Definition: fd.c:270
int max_safe_fds
Definition: fd.c:158
void ReserveExternalFD(void)
Definition: fd.c:1210

◆ AllocateDir()

DIR* AllocateDir ( const char *  dirname)

Definition at line 2720 of file fd.c.

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

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

2721 {
2722  DIR *dir;
2723 
2724  DO_DB(elog(LOG, "AllocateDir: Allocated %d (%s)",
2725  numAllocatedDescs, dirname));
2726 
2727  /* Can we allocate another non-virtual FD? */
2728  if (!reserveAllocatedDesc())
2729  ereport(ERROR,
2730  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2731  errmsg("exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"",
2732  maxAllocatedDescs, dirname)));
2733 
2734  /* Close excess kernel FDs. */
2735  ReleaseLruFiles();
2736 
2737 TryAgain:
2738  if ((dir = opendir(dirname)) != NULL)
2739  {
2741 
2742  desc->kind = AllocateDescDir;
2743  desc->desc.dir = dir;
2746  return desc->desc.dir;
2747  }
2748 
2749  if (errno == EMFILE || errno == ENFILE)
2750  {
2751  int save_errno = errno;
2752 
2753  ereport(LOG,
2754  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2755  errmsg("out of file descriptors: %m; release and retry")));
2756  errno = 0;
2757  if (ReleaseLruFile())
2758  goto TryAgain;
2759  errno = save_errno;
2760  }
2761 
2762  return NULL;
2763 }
union AllocateDesc::@18 desc
static AllocateDesc * allocatedDescs
Definition: fd.c:265
DIR * dir
Definition: fd.c:258
#define DO_DB(A)
Definition: fd.c:176
int errcode(int sqlerrcode)
Definition: elog.c:698
static bool reserveAllocatedDesc(void)
Definition: fd.c:2384
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:253
static bool ReleaseLruFile(void)
Definition: fd.c:1371
Definition: dirent.c:25
#define ERROR
Definition: elog.h:46
DIR * opendir(const char *)
Definition: dirent.c:33
static void ReleaseLruFiles(void)
Definition: fd.c:1393
#define ereport(elevel,...)
Definition: elog.h:157
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:724
SubTransactionId create_subid
Definition: fd.c:254
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
static int maxAllocatedDescs
Definition: fd.c:264
static int numAllocatedDescs
Definition: fd.c:263

◆ AllocateFile()

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

Definition at line 2459 of file fd.c.

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

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

2460 {
2461  FILE *file;
2462 
2463  DO_DB(elog(LOG, "AllocateFile: Allocated %d (%s)",
2465 
2466  /* Can we allocate another non-virtual FD? */
2467  if (!reserveAllocatedDesc())
2468  ereport(ERROR,
2469  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2470  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2471  maxAllocatedDescs, name)));
2472 
2473  /* Close excess kernel FDs. */
2474  ReleaseLruFiles();
2475 
2476 TryAgain:
2477  if ((file = fopen(name, mode)) != NULL)
2478  {
2480 
2481  desc->kind = AllocateDescFile;
2482  desc->desc.file = file;
2485  return desc->desc.file;
2486  }
2487 
2488  if (errno == EMFILE || errno == ENFILE)
2489  {
2490  int save_errno = errno;
2491 
2492  ereport(LOG,
2493  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2494  errmsg("out of file descriptors: %m; release and retry")));
2495  errno = 0;
2496  if (ReleaseLruFile())
2497  goto TryAgain;
2498  errno = save_errno;
2499  }
2500 
2501  return NULL;
2502 }
static PgChecksumMode mode
Definition: pg_checksums.c:65
union AllocateDesc::@18 desc
static AllocateDesc * allocatedDescs
Definition: fd.c:265
#define DO_DB(A)
Definition: fd.c:176
int errcode(int sqlerrcode)
Definition: elog.c:698
static bool reserveAllocatedDesc(void)
Definition: fd.c:2384
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:253
static bool ReleaseLruFile(void)
Definition: fd.c:1371
#define ERROR
Definition: elog.h:46
static void ReleaseLruFiles(void)
Definition: fd.c:1393
FILE * file
Definition: fd.c:257
#define ereport(elevel,...)
Definition: elog.h:157
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:724
SubTransactionId create_subid
Definition: fd.c:254
const char * name
Definition: encode.c:561
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
static int maxAllocatedDescs
Definition: fd.c:264
static int numAllocatedDescs
Definition: fd.c:263

◆ AllocateVfd()

static File AllocateVfd ( void  )
static

Definition at line 1403 of file fd.c.

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

Referenced by PathNameOpenFilePerm().

1404 {
1405  Index i;
1406  File file;
1407 
1408  DO_DB(elog(LOG, "AllocateVfd. Size %zu", SizeVfdCache));
1409 
1410  Assert(SizeVfdCache > 0); /* InitFileAccess not called? */
1411 
1412  if (VfdCache[0].nextFree == 0)
1413  {
1414  /*
1415  * The free list is empty so it is time to increase the size of the
1416  * array. We choose to double it each time this happens. However,
1417  * there's not much point in starting *real* small.
1418  */
1419  Size newCacheSize = SizeVfdCache * 2;
1420  Vfd *newVfdCache;
1421 
1422  if (newCacheSize < 32)
1423  newCacheSize = 32;
1424 
1425  /*
1426  * Be careful not to clobber VfdCache ptr if realloc fails.
1427  */
1428  newVfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
1429  if (newVfdCache == NULL)
1430  ereport(ERROR,
1431  (errcode(ERRCODE_OUT_OF_MEMORY),
1432  errmsg("out of memory")));
1433  VfdCache = newVfdCache;
1434 
1435  /*
1436  * Initialize the new entries and link them into the free list.
1437  */
1438  for (i = SizeVfdCache; i < newCacheSize; i++)
1439  {
1440  MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
1441  VfdCache[i].nextFree = i + 1;
1442  VfdCache[i].fd = VFD_CLOSED;
1443  }
1444  VfdCache[newCacheSize - 1].nextFree = 0;
1446 
1447  /*
1448  * Record the new size
1449  */
1450  SizeVfdCache = newCacheSize;
1451  }
1452 
1453  file = VfdCache[0].nextFree;
1454 
1455  VfdCache[0].nextFree = VfdCache[file].nextFree;
1456 
1457  return file;
1458 }
File nextFree
Definition: fd.c:197
static Size SizeVfdCache
Definition: fd.c:213
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
int errcode(int sqlerrcode)
Definition: elog.c:698
#define MemSet(start, val, len)
Definition: c.h:1008
#define LOG
Definition: elog.h:26
#define ERROR
Definition: elog.h:46
Definition: fd.c:192
int fd
Definition: fd.c:194
unsigned int Index
Definition: c.h:549
#define VFD_CLOSED
Definition: fd.c:180
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
size_t Size
Definition: c.h:540
#define realloc(a, b)
Definition: header.h:60
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
int i
int File
Definition: fd.h:54

◆ AtEOSubXact_Files()

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

Definition at line 3008 of file fd.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

3010 {
3011  Index i;
3012 
3013  for (i = 0; i < numAllocatedDescs; i++)
3014  {
3015  if (allocatedDescs[i].create_subid == mySubid)
3016  {
3017  if (isCommit)
3018  allocatedDescs[i].create_subid = parentSubid;
3019  else
3020  {
3021  /* have to recheck the item after FreeDesc (ugly) */
3022  FreeDesc(&allocatedDescs[i--]);
3023  }
3024  }
3025  }
3026 }
static AllocateDesc * allocatedDescs
Definition: fd.c:265
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2619
unsigned int Index
Definition: c.h:549
SubTransactionId create_subid
Definition: fd.c:254
int i
static int numAllocatedDescs
Definition: fd.c:263

◆ AtEOXact_Files()

void AtEOXact_Files ( bool  isCommit)

Definition at line 3041 of file fd.c.

References CleanupTempFiles(), numTempTableSpaces, and tempTableSpaces.

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

3042 {
3043  CleanupTempFiles(isCommit, false);
3044  tempTableSpaces = NULL;
3045  numTempTableSpaces = -1;
3046 }
static int numTempTableSpaces
Definition: fd.c:285
static Oid * tempTableSpaces
Definition: fd.c:284
static void CleanupTempFiles(bool isCommit, bool isProcExit)
Definition: fd.c:3078

◆ BasicOpenFile()

int BasicOpenFile ( const char *  fileName,
int  fileFlags 
)

Definition at line 1069 of file fd.c.

References BasicOpenFilePerm(), and pg_file_create_mode.

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

1070 {
1071  return BasicOpenFilePerm(fileName, fileFlags, pg_file_create_mode);
1072 }
int pg_file_create_mode
Definition: file_perm.c:19
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1091

◆ BasicOpenFilePerm()

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

Definition at line 1091 of file fd.c.

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

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

1092 {
1093  int fd;
1094 
1095 tryAgain:
1096 #ifdef PG_O_DIRECT_USE_F_NOCACHE
1097 
1098  /*
1099  * The value we defined to stand in for O_DIRECT when simulating it with
1100  * F_NOCACHE had better not collide with any of the standard flags.
1101  */
1103  (O_APPEND |
1104  O_CREAT |
1105  O_EXCL |
1106  O_RDWR |
1107  O_RDONLY |
1108  O_SYNC |
1109  O_TRUNC |
1110  O_WRONLY)) == 0,
1111  "PG_O_DIRECT value collides with standard flag");
1112 #if defined(O_CLOEXEC)
1113  StaticAssertStmt((PG_O_DIRECT & O_CLOEXEC) == 0,
1114  "PG_O_DIRECT value collides with O_CLOEXEC");
1115 #endif
1116 #if defined(O_DSYNC)
1118  "PG_O_DIRECT value collides with O_DSYNC");
1119 #endif
1120 
1121  fd = open(fileName, fileFlags & ~PG_O_DIRECT, fileMode);
1122 #else
1123  fd = open(fileName, fileFlags, fileMode);
1124 #endif
1125 
1126  if (fd >= 0)
1127  {
1128 #ifdef PG_O_DIRECT_USE_F_NOCACHE
1129  if (fileFlags & PG_O_DIRECT)
1130  {
1131  if (fcntl(fd, F_NOCACHE, 1) < 0)
1132  {
1133  int save_errno = errno;
1134 
1135  close(fd);
1136  errno = save_errno;
1137  return -1;
1138  }
1139  }
1140 #endif
1141 
1142  return fd; /* success! */
1143  }
1144 
1145  if (errno == EMFILE || errno == ENFILE)
1146  {
1147  int save_errno = errno;
1148 
1149  ereport(LOG,
1150  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
1151  errmsg("out of file descriptors: %m; release and retry")));
1152  errno = 0;
1153  if (ReleaseLruFile())
1154  goto tryAgain;
1155  errno = save_errno;
1156  }
1157 
1158  return -1; /* failure */
1159 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:918
static bool ReleaseLruFile(void)
Definition: fd.c:1371
#define PG_O_DIRECT
Definition: fd.h:95
#define O_DSYNC
Definition: win32_port.h:336
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define close(a)
Definition: win32.h:12

◆ BeforeShmemExit_Files()

static void BeforeShmemExit_Files ( int  code,
Datum  arg 
)
static

Definition at line 3055 of file fd.c.

References CleanupTempFiles().

Referenced by InitTemporaryFileAccess().

3056 {
3057  CleanupTempFiles(false, true);
3058 
3059  /* prevent further temp files from being created */
3060 #ifdef USE_ASSERT_CHECKING
3061  temporary_files_allowed = false;
3062 #endif
3063 }
static void CleanupTempFiles(bool isCommit, bool isProcExit)
Definition: fd.c:3078

◆ CleanupTempFiles()

static void CleanupTempFiles ( bool  isCommit,
bool  isProcExit 
)
static

Definition at line 3078 of file fd.c.

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

Referenced by AtEOXact_Files(), and BeforeShmemExit_Files().

3079 {
3080  Index i;
3081 
3082  /*
3083  * Careful here: at proc_exit we need extra cleanup, not just
3084  * xact_temporary files.
3085  */
3086  if (isProcExit || have_xact_temporary_files)
3087  {
3088  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
3089  for (i = 1; i < SizeVfdCache; i++)
3090  {
3091  unsigned short fdstate = VfdCache[i].fdstate;
3092 
3093  if (((fdstate & FD_DELETE_AT_CLOSE) || (fdstate & FD_CLOSE_AT_EOXACT)) &&
3094  VfdCache[i].fileName != NULL)
3095  {
3096  /*
3097  * If we're in the process of exiting a backend process, close
3098  * all temporary files. Otherwise, only close temporary files
3099  * local to the current transaction. They should be closed by
3100  * the ResourceOwner mechanism already, so this is just a
3101  * debugging cross-check.
3102  */
3103  if (isProcExit)
3104  FileClose(i);
3105  else if (fdstate & FD_CLOSE_AT_EOXACT)
3106  {
3107  elog(WARNING,
3108  "temporary file %s not closed at end-of-transaction",
3109  VfdCache[i].fileName);
3110  FileClose(i);
3111  }
3112  }
3113  }
3114 
3115  have_xact_temporary_files = false;
3116  }
3117 
3118  /* Complain if any allocated files remain open at commit. */
3119  if (isCommit && numAllocatedDescs > 0)
3120  elog(WARNING, "%d temporary files and directories not closed at end-of-transaction",
3122 
3123  /* Clean up "allocated" stdio files, dirs and fds. */
3124  while (numAllocatedDescs > 0)
3125  FreeDesc(&allocatedDescs[0]);
3126 }
static AllocateDesc * allocatedDescs
Definition: fd.c:265
static Size SizeVfdCache
Definition: fd.c:213
#define FD_DELETE_AT_CLOSE
Definition: fd.c:188
static Vfd * VfdCache
Definition: fd.c:212
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2619
static bool have_xact_temporary_files
Definition: fd.c:224
unsigned short fdstate
Definition: fd.c:195
#define WARNING
Definition: elog.h:40
#define FileIsNotOpen(file)
Definition: fd.c:185
unsigned int Index
Definition: c.h:549
void FileClose(File file)
Definition: fd.c:1959
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232
int i
#define FD_CLOSE_AT_EOXACT
Definition: fd.c:189
static int numAllocatedDescs
Definition: fd.c:263

◆ closeAllVfds()

void closeAllVfds ( void  )

Definition at line 2897 of file fd.c.

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

Referenced by standard_ProcessUtility().

2898 {
2899  Index i;
2900 
2901  if (SizeVfdCache > 0)
2902  {
2903  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
2904  for (i = 1; i < SizeVfdCache; i++)
2905  {
2906  if (!FileIsNotOpen(i))
2907  LruDelete(i);
2908  }
2909  }
2910 }
static Size SizeVfdCache
Definition: fd.c:213
static void LruDelete(File file)
Definition: fd.c:1276
#define FileIsNotOpen(file)
Definition: fd.c:185
unsigned int Index
Definition: c.h:549
#define Assert(condition)
Definition: c.h:804
int i

◆ ClosePipeStream()

int ClosePipeStream ( FILE *  file)

Definition at line 2868 of file fd.c.

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

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

2869 {
2870  int i;
2871 
2872  DO_DB(elog(LOG, "ClosePipeStream: Allocated %d", numAllocatedDescs));
2873 
2874  /* Remove file from list of allocated files, if it's present */
2875  for (i = numAllocatedDescs; --i >= 0;)
2876  {
2877  AllocateDesc *desc = &allocatedDescs[i];
2878 
2879  if (desc->kind == AllocateDescPipe && desc->desc.file == file)
2880  return FreeDesc(desc);
2881  }
2882 
2883  /* Only get here if someone passes us a file not in allocatedDescs */
2884  elog(WARNING, "file passed to ClosePipeStream was not obtained from OpenPipeStream");
2885 
2886  return pclose(file);
2887 }
union AllocateDesc::@18 desc
static AllocateDesc * allocatedDescs
Definition: fd.c:265
#define DO_DB(A)
Definition: fd.c:176
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:253
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2619
#define WARNING
Definition: elog.h:40
FILE * file
Definition: fd.c:257
#define elog(elevel,...)
Definition: elog.h:232
int i
static int numAllocatedDescs
Definition: fd.c:263

◆ CloseTransientFile()

int CloseTransientFile ( int  fd)

Definition at line 2686 of file fd.c.

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

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

2687 {
2688  int i;
2689 
2690  DO_DB(elog(LOG, "CloseTransientFile: Allocated %d", numAllocatedDescs));
2691 
2692  /* Remove fd from list of allocated files, if it's present */
2693  for (i = numAllocatedDescs; --i >= 0;)
2694  {
2695  AllocateDesc *desc = &allocatedDescs[i];
2696 
2697  if (desc->kind == AllocateDescRawFD && desc->desc.fd == fd)
2698  return FreeDesc(desc);
2699  }
2700 
2701  /* Only get here if someone passes us a file not in allocatedDescs */
2702  elog(WARNING, "fd passed to CloseTransientFile was not obtained from OpenTransientFile");
2703 
2704  return close(fd);
2705 }
union AllocateDesc::@18 desc
static AllocateDesc * allocatedDescs
Definition: fd.c:265
#define DO_DB(A)
Definition: fd.c:176
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:253
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2619
#define WARNING
Definition: elog.h:40
int fd
Definition: fd.c:259
#define elog(elevel,...)
Definition: elog.h:232
int i
#define close(a)
Definition: win32.h:12
static int numAllocatedDescs
Definition: fd.c:263

◆ count_usable_fds()

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

Definition at line 942 of file fd.c.

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

Referenced by set_max_safe_fds().

943 {
944  int *fd;
945  int size;
946  int used = 0;
947  int highestfd = 0;
948  int j;
949 
950 #ifdef HAVE_GETRLIMIT
951  struct rlimit rlim;
952  int getrlimit_status;
953 #endif
954 
955  size = 1024;
956  fd = (int *) palloc(size * sizeof(int));
957 
958 #ifdef HAVE_GETRLIMIT
959 #ifdef RLIMIT_NOFILE /* most platforms use RLIMIT_NOFILE */
960  getrlimit_status = getrlimit(RLIMIT_NOFILE, &rlim);
961 #else /* but BSD doesn't ... */
962  getrlimit_status = getrlimit(RLIMIT_OFILE, &rlim);
963 #endif /* RLIMIT_NOFILE */
964  if (getrlimit_status != 0)
965  ereport(WARNING, (errmsg("getrlimit failed: %m")));
966 #endif /* HAVE_GETRLIMIT */
967 
968  /* dup until failure or probe limit reached */
969  for (;;)
970  {
971  int thisfd;
972 
973 #ifdef HAVE_GETRLIMIT
974 
975  /*
976  * don't go beyond RLIMIT_NOFILE; causes irritating kernel logs on
977  * some platforms
978  */
979  if (getrlimit_status == 0 && highestfd >= rlim.rlim_cur - 1)
980  break;
981 #endif
982 
983  thisfd = dup(2);
984  if (thisfd < 0)
985  {
986  /* Expect EMFILE or ENFILE, else it's fishy */
987  if (errno != EMFILE && errno != ENFILE)
988  elog(WARNING, "duplicating stderr file descriptor failed after %d successes: %m", used);
989  break;
990  }
991 
992  if (used >= size)
993  {
994  size *= 2;
995  fd = (int *) repalloc(fd, size * sizeof(int));
996  }
997  fd[used++] = thisfd;
998 
999  if (highestfd < thisfd)
1000  highestfd = thisfd;
1001 
1002  if (used >= max_to_probe)
1003  break;
1004  }
1005 
1006  /* release the files we opened */
1007  for (j = 0; j < used; j++)
1008  close(fd[j]);
1009 
1010  pfree(fd);
1011 
1012  /*
1013  * Return results. usable_fds is just the number of successful dups. We
1014  * assume that the system limit is highestfd+1 (remember 0 is a legal FD
1015  * number) and so already_open is highestfd+1 - usable_fds.
1016  */
1017  *usable_fds = used;
1018  *already_open = highestfd + 1 - used;
1019 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
void pfree(void *pointer)
Definition: mcxt.c:1169
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:157
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define close(a)
Definition: win32.h:12

◆ data_sync_elevel()

◆ datadir_fsync_fname()

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

Definition at line 3631 of file fd.c.

References fsync_fname_ext().

Referenced by SyncDataDirectory().

3632 {
3633  /*
3634  * We want to silently ignoring errors about unreadable files. Pass that
3635  * desire on to fsync_fname_ext().
3636  */
3637  fsync_fname_ext(fname, isdir, true, elevel);
3638 }
static int elevel
Definition: vacuumlazy.c:401
int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3666

◆ Delete()

static void Delete ( File  file)
static

Definition at line 1257 of file fd.c.

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

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

1258 {
1259  Vfd *vfdP;
1260 
1261  Assert(file != 0);
1262 
1263  DO_DB(elog(LOG, "Delete %d (%s)",
1264  file, VfdCache[file].fileName));
1265  DO_DB(_dump_lru());
1266 
1267  vfdP = &VfdCache[file];
1268 
1271 
1272  DO_DB(_dump_lru());
1273 }
File lruLessRecently
Definition: fd.c:199
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
Definition: fd.c:192
#define Assert(condition)
Definition: c.h:804
File lruMoreRecently
Definition: fd.c:198
#define elog(elevel,...)
Definition: elog.h:232

◆ durable_rename()

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

Definition at line 697 of file fd.c.

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

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

698 {
699  int fd;
700 
701  /*
702  * First fsync the old and target path (if it exists), to ensure that they
703  * are properly persistent on disk. Syncing the target file is not
704  * strictly necessary, but it makes it easier to reason about crashes;
705  * because it's then guaranteed that either source or target file exists
706  * after a crash.
707  */
708  if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
709  return -1;
710 
711  fd = OpenTransientFile(newfile, PG_BINARY | O_RDWR);
712  if (fd < 0)
713  {
714  if (errno != ENOENT)
715  {
716  ereport(elevel,
718  errmsg("could not open file \"%s\": %m", newfile)));
719  return -1;
720  }
721  }
722  else
723  {
724  if (pg_fsync(fd) != 0)
725  {
726  int save_errno;
727 
728  /* close file upon error, might not be in transaction context */
729  save_errno = errno;
730  CloseTransientFile(fd);
731  errno = save_errno;
732 
733  ereport(elevel,
735  errmsg("could not fsync file \"%s\": %m", newfile)));
736  return -1;
737  }
738 
739  if (CloseTransientFile(fd) != 0)
740  {
741  ereport(elevel,
743  errmsg("could not close file \"%s\": %m", newfile)));
744  return -1;
745  }
746  }
747 
748  /* Time to do the real deal... */
749  if (rename(oldfile, newfile) < 0)
750  {
751  ereport(elevel,
753  errmsg("could not rename file \"%s\" to \"%s\": %m",
754  oldfile, newfile)));
755  return -1;
756  }
757 
758  /*
759  * To guarantee renaming the file is persistent, fsync the file with its
760  * new name, and its containing directory.
761  */
762  if (fsync_fname_ext(newfile, false, false, elevel) != 0)
763  return -1;
764 
765  if (fsync_parent_path(newfile, elevel) != 0)
766  return -1;
767 
768  return 0;
769 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1271
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2509
int errcode_for_file_access(void)
Definition: elog.c:721
int CloseTransientFile(int fd)
Definition: fd.c:2686
static int elevel
Definition: vacuumlazy.c:401
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
int pg_fsync(int fd)
Definition: fd.c:357
int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3666
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3742

◆ durable_rename_excl()

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

Definition at line 827 of file fd.c.

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

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

828 {
829  /*
830  * Ensure that, if we crash directly after the rename/link, a file with
831  * valid contents is moved into place.
832  */
833  if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
834  return -1;
835 
836 #ifdef HAVE_WORKING_LINK
837  if (link(oldfile, newfile) < 0)
838  {
839  ereport(elevel,
841  errmsg("could not link file \"%s\" to \"%s\": %m",
842  oldfile, newfile)));
843  return -1;
844  }
845  unlink(oldfile);
846 #else
847  if (rename(oldfile, newfile) < 0)
848  {
849  ereport(elevel,
851  errmsg("could not rename file \"%s\" to \"%s\": %m",
852  oldfile, newfile)));
853  return -1;
854  }
855 #endif
856 
857  /*
858  * Make change persistent in case of an OS crash, both the new entry and
859  * its parent directory need to be flushed.
860  */
861  if (fsync_fname_ext(newfile, false, false, elevel) != 0)
862  return -1;
863 
864  /* Same for parent directory */
865  if (fsync_parent_path(newfile, elevel) != 0)
866  return -1;
867 
868  return 0;
869 }
int errcode_for_file_access(void)
Definition: elog.c:721
static int elevel
Definition: vacuumlazy.c:401
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
int link(const char *src, const char *dst)
int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3666
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3742

◆ durable_unlink()

int durable_unlink ( const char *  fname,
int  elevel 
)

Definition at line 787 of file fd.c.

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

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

788 {
789  if (unlink(fname) < 0)
790  {
791  ereport(elevel,
793  errmsg("could not remove file \"%s\": %m",
794  fname)));
795  return -1;
796  }
797 
798  /*
799  * To guarantee that the removal of the file is persistent, fsync its
800  * parent directory.
801  */
802  if (fsync_parent_path(fname, elevel) != 0)
803  return -1;
804 
805  return 0;
806 }
int errcode_for_file_access(void)
Definition: elog.c:721
static int elevel
Definition: vacuumlazy.c:401
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3742

◆ FileAccess()

static int FileAccess ( File  file)
static

Definition at line 1481 of file fd.c.

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

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

1482 {
1483  int returnValue;
1484 
1485  DO_DB(elog(LOG, "FileAccess %d (%s)",
1486  file, VfdCache[file].fileName));
1487 
1488  /*
1489  * Is the file open? If not, open it and put it at the head of the LRU
1490  * ring (possibly closing the least recently used file to get an FD).
1491  */
1492 
1493  if (FileIsNotOpen(file))
1494  {
1495  returnValue = LruInsert(file);
1496  if (returnValue != 0)
1497  return returnValue;
1498  }
1499  else if (VfdCache[0].lruLessRecently != file)
1500  {
1501  /*
1502  * We now know that the file is open and that it is not the last one
1503  * accessed, so we need to move it to the head of the Lru ring.
1504  */
1505 
1506  Delete(file);
1507  Insert(file);
1508  }
1509 
1510  return 0;
1511 }
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
static void Delete(File file)
Definition: fd.c:1257
#define LOG
Definition: elog.h:26
static int LruInsert(File file)
Definition: fd.c:1324
static void Insert(File file)
Definition: fd.c:1302
#define FileIsNotOpen(file)
Definition: fd.c:185
#define elog(elevel,...)
Definition: elog.h:232

◆ FileClose()

void FileClose ( File  file)

Definition at line 1959 of file fd.c.

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, and VFD_CLOSED.

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

1960 {
1961  Vfd *vfdP;
1962 
1963  Assert(FileIsValid(file));
1964 
1965  DO_DB(elog(LOG, "FileClose: %d (%s)",
1966  file, VfdCache[file].fileName));
1967 
1968  vfdP = &VfdCache[file];
1969 
1970  if (!FileIsNotOpen(file))
1971  {
1972  /* close the file */
1973  if (close(vfdP->fd) != 0)
1974  {
1975  /*
1976  * We may need to panic on failure to close non-temporary files;
1977  * see LruDelete.
1978  */
1980  "could not close file \"%s\": %m", vfdP->fileName);
1981  }
1982 
1983  --nfile;
1984  vfdP->fd = VFD_CLOSED;
1985 
1986  /* remove the file from the lru ring */
1987  Delete(file);
1988  }
1989 
1990  if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
1991  {
1992  /* Subtract its size from current usage (do first in case of error) */
1993  temporary_files_size -= vfdP->fileSize;
1994  vfdP->fileSize = 0;
1995  }
1996 
1997  /*
1998  * Delete the file if it was temporary, and make a log entry if wanted
1999  */
2000  if (vfdP->fdstate & FD_DELETE_AT_CLOSE)
2001  {
2002  struct stat filestats;
2003  int stat_errno;
2004 
2005  /*
2006  * If we get an error, as could happen within the ereport/elog calls,
2007  * we'll come right back here during transaction abort. Reset the
2008  * flag to ensure that we can't get into an infinite loop. This code
2009  * is arranged to ensure that the worst-case consequence is failing to
2010  * emit log message(s), not failing to attempt the unlink.
2011  */
2012  vfdP->fdstate &= ~FD_DELETE_AT_CLOSE;
2013 
2014 
2015  /* first try the stat() */
2016  if (stat(vfdP->fileName, &filestats))
2017  stat_errno = errno;
2018  else
2019  stat_errno = 0;
2020 
2021  /* in any case do the unlink */
2022  if (unlink(vfdP->fileName))
2023  ereport(LOG,
2025  errmsg("could not delete file \"%s\": %m", vfdP->fileName)));
2026 
2027  /* and last report the stat results */
2028  if (stat_errno == 0)
2029  ReportTemporaryFileUsage(vfdP->fileName, filestats.st_size);
2030  else
2031  {
2032  errno = stat_errno;
2033  ereport(LOG,
2035  errmsg("could not stat file \"%s\": %m", vfdP->fileName)));
2036  }
2037  }
2038 
2039  /* Unregister it from the resource owner */
2040  if (vfdP->resowner)
2041  ResourceOwnerForgetFile(vfdP->resowner, file);
2042 
2043  /*
2044  * Return the Vfd slot to the free list
2045  */
2046  FreeVfd(file);
2047 }
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:190
#define DO_DB(A)
Definition: fd.c:176
#define FD_DELETE_AT_CLOSE
Definition: fd.c:188
static Vfd * VfdCache
Definition: fd.c:212
static void Delete(File file)
Definition: fd.c:1257
#define LOG
Definition: elog.h:26
char * fileName
Definition: fd.c:201
int errcode_for_file_access(void)
Definition: elog.c:721
static int nfile
Definition: fd.c:218
unsigned short fdstate
Definition: fd.c:195
Definition: fd.c:192
off_t fileSize
Definition: fd.c:200
int fd
Definition: fd.c:194
ResourceOwner resowner
Definition: fd.c:196
static void ReportTemporaryFileUsage(const char *path, off_t size)
Definition: fd.c:1517
#define FileIsNotOpen(file)
Definition: fd.c:185
int data_sync_elevel(int elevel)
Definition: fd.c:3805
#define FileIsValid(file)
Definition: fd.c:182
#define VFD_CLOSED
Definition: fd.c:180
static uint64 temporary_files_size
Definition: fd.c:232
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
static void FreeVfd(File file)
Definition: fd.c:1461
#define close(a)
Definition: win32.h:12
void ResourceOwnerForgetFile(ResourceOwner owner, File file)
Definition: resowner.c:1306
#define stat
Definition: win32_port.h:283

◆ FileGetRawDesc()

int FileGetRawDesc ( File  file)

Definition at line 2353 of file fd.c.

References Assert, vfd::fd, and FileIsValid.

2354 {
2355  Assert(FileIsValid(file));
2356  return VfdCache[file].fd;
2357 }
static Vfd * VfdCache
Definition: fd.c:212
int fd
Definition: fd.c:194
#define FileIsValid(file)
Definition: fd.c:182
#define Assert(condition)
Definition: c.h:804

◆ FileGetRawFlags()

int FileGetRawFlags ( File  file)

Definition at line 2363 of file fd.c.

References Assert, vfd::fileFlags, and FileIsValid.

2364 {
2365  Assert(FileIsValid(file));
2366  return VfdCache[file].fileFlags;
2367 }
static Vfd * VfdCache
Definition: fd.c:212
#define FileIsValid(file)
Definition: fd.c:182
#define Assert(condition)
Definition: c.h:804
int fileFlags
Definition: fd.c:203

◆ FileGetRawMode()

mode_t FileGetRawMode ( File  file)

Definition at line 2373 of file fd.c.

References Assert, FileIsValid, and vfd::fileMode.

2374 {
2375  Assert(FileIsValid(file));
2376  return VfdCache[file].fileMode;
2377 }
static Vfd * VfdCache
Definition: fd.c:212
mode_t fileMode
Definition: fd.c:204
#define FileIsValid(file)
Definition: fd.c:182
#define Assert(condition)
Definition: c.h:804

◆ FilePathName()

char* FilePathName ( File  file)

Definition at line 2337 of file fd.c.

References Assert, FileIsValid, and vfd::fileName.

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

2338 {
2339  Assert(FileIsValid(file));
2340 
2341  return VfdCache[file].fileName;
2342 }
static Vfd * VfdCache
Definition: fd.c:212
char * fileName
Definition: fd.c:201
#define FileIsValid(file)
Definition: fd.c:182
#define Assert(condition)
Definition: c.h:804

◆ FilePrefetch()

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

Definition at line 2059 of file fd.c.

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

Referenced by mdprefetch().

2060 {
2061 #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
2062  int returnCode;
2063 
2064  Assert(FileIsValid(file));
2065 
2066  DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " %d",
2067  file, VfdCache[file].fileName,
2068  (int64) offset, amount));
2069 
2070  returnCode = FileAccess(file);
2071  if (returnCode < 0)
2072  return returnCode;
2073 
2074  pgstat_report_wait_start(wait_event_info);
2075  returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
2076  POSIX_FADV_WILLNEED);
2078 
2079  return returnCode;
2080 #else
2081  Assert(FileIsValid(file));
2082  return 0;
2083 #endif
2084 }
static void pgstat_report_wait_end(void)
Definition: wait_event.h:274
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:258
#define FileIsValid(file)
Definition: fd.c:182
static int FileAccess(File file)
Definition: fd.c:1481
#define Assert(condition)
Definition: c.h:804
#define INT64_FORMAT
Definition: c.h:483
#define elog(elevel,...)
Definition: elog.h:232

◆ FileRead()

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

Definition at line 2110 of file fd.c.

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

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

2112 {
2113  int returnCode;
2114  Vfd *vfdP;
2115 
2116  Assert(FileIsValid(file));
2117 
2118  DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p",
2119  file, VfdCache[file].fileName,
2120  (int64) offset,
2121  amount, buffer));
2122 
2123  returnCode = FileAccess(file);
2124  if (returnCode < 0)
2125  return returnCode;
2126 
2127  vfdP = &VfdCache[file];
2128 
2129 retry:
2130  pgstat_report_wait_start(wait_event_info);
2131  returnCode = pg_pread(vfdP->fd, buffer, amount, offset);
2133 
2134  if (returnCode < 0)
2135  {
2136  /*
2137  * Windows may run out of kernel buffers and return "Insufficient
2138  * system resources" error. Wait a bit and retry to solve it.
2139  *
2140  * It is rumored that EINTR is also possible on some Unix filesystems,
2141  * in which case immediate retry is indicated.
2142  */
2143 #ifdef WIN32
2144  DWORD error = GetLastError();
2145 
2146  switch (error)
2147  {
2148  case ERROR_NO_SYSTEM_RESOURCES:
2149  pg_usleep(1000L);
2150  errno = EINTR;
2151  break;
2152  default:
2153  _dosmaperr(error);
2154  break;
2155  }
2156 #endif
2157  /* OK to retry if interrupted */
2158  if (errno == EINTR)
2159  goto retry;
2160  }
2161 
2162  return returnCode;
2163 }
static void pgstat_report_wait_end(void)
Definition: wait_event.h:274
static void error(void)
Definition: sql-dyntest.c:147
#define DO_DB(A)
Definition: fd.c:176
void _dosmaperr(unsigned long)
Definition: win32error.c:171
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
ssize_t pg_pread(int fd, void *buf, size_t nbyte, off_t offset)
Definition: pread.c:27
void pg_usleep(long microsec)
Definition: signal.c:53
Definition: fd.c:192
int fd
Definition: fd.c:194
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:258
#define FileIsValid(file)
Definition: fd.c:182
static int FileAccess(File file)
Definition: fd.c:1481
#define Assert(condition)
Definition: c.h:804
#define INT64_FORMAT
Definition: c.h:483
#define elog(elevel,...)
Definition: elog.h:232
#define EINTR
Definition: win32_port.h:351

◆ FileSize()

off_t FileSize ( File  file)

Definition at line 2285 of file fd.c.

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

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

2286 {
2287  Assert(FileIsValid(file));
2288 
2289  DO_DB(elog(LOG, "FileSize %d (%s)",
2290  file, VfdCache[file].fileName));
2291 
2292  if (FileIsNotOpen(file))
2293  {
2294  if (FileAccess(file) < 0)
2295  return (off_t) -1;
2296  }
2297 
2298  return lseek(VfdCache[file].fd, 0, SEEK_END);
2299 }
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define FileIsNotOpen(file)
Definition: fd.c:185
#define FileIsValid(file)
Definition: fd.c:182
static int FileAccess(File file)
Definition: fd.c:1481
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232

◆ FileSync()

int FileSync ( File  file,
uint32  wait_event_info 
)

Definition at line 2264 of file fd.c.

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

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

2265 {
2266  int returnCode;
2267 
2268  Assert(FileIsValid(file));
2269 
2270  DO_DB(elog(LOG, "FileSync: %d (%s)",
2271  file, VfdCache[file].fileName));
2272 
2273  returnCode = FileAccess(file);
2274  if (returnCode < 0)
2275  return returnCode;
2276 
2277  pgstat_report_wait_start(wait_event_info);
2278  returnCode = pg_fsync(VfdCache[file].fd);
2280 
2281  return returnCode;
2282 }
static void pgstat_report_wait_end(void)
Definition: wait_event.h:274
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:258
#define FileIsValid(file)
Definition: fd.c:182
static int FileAccess(File file)
Definition: fd.c:1481
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232
int pg_fsync(int fd)
Definition: fd.c:357

◆ FileTruncate()

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

Definition at line 2302 of file fd.c.

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

Referenced by BufFileTruncateFileSet(), and mdtruncate().

2303 {
2304  int returnCode;
2305 
2306  Assert(FileIsValid(file));
2307 
2308  DO_DB(elog(LOG, "FileTruncate %d (%s)",
2309  file, VfdCache[file].fileName));
2310 
2311  returnCode = FileAccess(file);
2312  if (returnCode < 0)
2313  return returnCode;
2314 
2315  pgstat_report_wait_start(wait_event_info);
2316  returnCode = ftruncate(VfdCache[file].fd, offset);
2318 
2319  if (returnCode == 0 && VfdCache[file].fileSize > offset)
2320  {
2321  /* adjust our state for truncation of a temp file */
2322  Assert(VfdCache[file].fdstate & FD_TEMP_FILE_LIMIT);
2323  temporary_files_size -= VfdCache[file].fileSize - offset;
2324  VfdCache[file].fileSize = offset;
2325  }
2326 
2327  return returnCode;
2328 }
static void pgstat_report_wait_end(void)
Definition: wait_event.h:274
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:190
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
off_t fileSize
Definition: fd.c:200
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:258
#define FileIsValid(file)
Definition: fd.c:182
static uint64 temporary_files_size
Definition: fd.c:232
static int FileAccess(File file)
Definition: fd.c:1481
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232
#define ftruncate(a, b)
Definition: win32_port.h:73

◆ FileWrite()

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

Definition at line 2166 of file fd.c.

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

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

2168 {
2169  int returnCode;
2170  Vfd *vfdP;
2171 
2172  Assert(FileIsValid(file));
2173 
2174  DO_DB(elog(LOG, "FileWrite: %d (%s) " INT64_FORMAT " %d %p",
2175  file, VfdCache[file].fileName,
2176  (int64) offset,
2177  amount, buffer));
2178 
2179  returnCode = FileAccess(file);
2180  if (returnCode < 0)
2181  return returnCode;
2182 
2183  vfdP = &VfdCache[file];
2184 
2185  /*
2186  * If enforcing temp_file_limit and it's a temp file, check to see if the
2187  * write would overrun temp_file_limit, and throw error if so. Note: it's
2188  * really a modularity violation to throw error here; we should set errno
2189  * and return -1. However, there's no way to report a suitable error
2190  * message if we do that. All current callers would just throw error
2191  * immediately anyway, so this is safe at present.
2192  */
2193  if (temp_file_limit >= 0 && (vfdP->fdstate & FD_TEMP_FILE_LIMIT))
2194  {
2195  off_t past_write = offset + amount;
2196 
2197  if (past_write > vfdP->fileSize)
2198  {
2199  uint64 newTotal = temporary_files_size;
2200 
2201  newTotal += past_write - vfdP->fileSize;
2202  if (newTotal > (uint64) temp_file_limit * (uint64) 1024)
2203  ereport(ERROR,
2204  (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
2205  errmsg("temporary file size exceeds temp_file_limit (%dkB)",
2206  temp_file_limit)));
2207  }
2208  }
2209 
2210 retry:
2211  errno = 0;
2212  pgstat_report_wait_start(wait_event_info);
2213  returnCode = pg_pwrite(VfdCache[file].fd, buffer, amount, offset);
2215 
2216  /* if write didn't set errno, assume problem is no disk space */
2217  if (returnCode != amount && errno == 0)
2218  errno = ENOSPC;
2219 
2220  if (returnCode >= 0)
2221  {
2222  /*
2223  * Maintain fileSize and temporary_files_size if it's a temp file.
2224  */
2225  if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
2226  {
2227  off_t past_write = offset + amount;
2228 
2229  if (past_write > vfdP->fileSize)
2230  {
2231  temporary_files_size += past_write - vfdP->fileSize;
2232  vfdP->fileSize = past_write;
2233  }
2234  }
2235  }
2236  else
2237  {
2238  /*
2239  * See comments in FileRead()
2240  */
2241 #ifdef WIN32
2242  DWORD error = GetLastError();
2243 
2244  switch (error)
2245  {
2246  case ERROR_NO_SYSTEM_RESOURCES:
2247  pg_usleep(1000L);
2248  errno = EINTR;
2249  break;
2250  default:
2251  _dosmaperr(error);
2252  break;
2253  }
2254 #endif
2255  /* OK to retry if interrupted */
2256  if (errno == EINTR)
2257  goto retry;
2258  }
2259 
2260  return returnCode;
2261 }
static void pgstat_report_wait_end(void)
Definition: wait_event.h:274
static void error(void)
Definition: sql-dyntest.c:147
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:190
#define DO_DB(A)
Definition: fd.c:176
void _dosmaperr(unsigned long)
Definition: win32error.c:171
static Vfd * VfdCache
Definition: fd.c:212
int errcode(int sqlerrcode)
Definition: elog.c:698
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset)
Definition: pwrite.c:27
void pg_usleep(long microsec)
Definition: signal.c:53
#define ERROR
Definition: elog.h:46
unsigned short fdstate
Definition: fd.c:195
Definition: fd.c:192
off_t fileSize
Definition: fd.c:200
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:258
#define FileIsValid(file)
Definition: fd.c:182
static uint64 temporary_files_size
Definition: fd.c:232
#define ereport(elevel,...)
Definition: elog.h:157
static int FileAccess(File file)
Definition: fd.c:1481
#define Assert(condition)
Definition: c.h:804
#define INT64_FORMAT
Definition: c.h:483
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define EINTR
Definition: win32_port.h:351
int temp_file_limit
Definition: guc.c:609

◆ FileWriteback()

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

Definition at line 2087 of file fd.c.

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

Referenced by mdwriteback().

2088 {
2089  int returnCode;
2090 
2091  Assert(FileIsValid(file));
2092 
2093  DO_DB(elog(LOG, "FileWriteback: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
2094  file, VfdCache[file].fileName,
2095  (int64) offset, (int64) nbytes));
2096 
2097  if (nbytes <= 0)
2098  return;
2099 
2100  returnCode = FileAccess(file);
2101  if (returnCode < 0)
2102  return;
2103 
2104  pgstat_report_wait_start(wait_event_info);
2105  pg_flush_data(VfdCache[file].fd, offset, nbytes);
2107 }
static void pgstat_report_wait_end(void)
Definition: wait_event.h:274
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:258
void pg_flush_data(int fd, off_t offset, off_t nbytes)
Definition: fd.c:467
#define FileIsValid(file)
Definition: fd.c:182
static int FileAccess(File file)
Definition: fd.c:1481
#define Assert(condition)
Definition: c.h:804
#define INT64_FORMAT
Definition: c.h:483
#define elog(elevel,...)
Definition: elog.h:232

◆ FreeDesc()

static int FreeDesc ( AllocateDesc desc)
static

Definition at line 2619 of file fd.c.

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

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

2620 {
2621  int result;
2622 
2623  /* Close the underlying object */
2624  switch (desc->kind)
2625  {
2626  case AllocateDescFile:
2627  result = fclose(desc->desc.file);
2628  break;
2629  case AllocateDescPipe:
2630  result = pclose(desc->desc.file);
2631  break;
2632  case AllocateDescDir:
2633  result = closedir(desc->desc.dir);
2634  break;
2635  case AllocateDescRawFD:
2636  result = close(desc->desc.fd);
2637  break;
2638  default:
2639  elog(ERROR, "AllocateDesc kind not recognized");
2640  result = 0; /* keep compiler quiet */
2641  break;
2642  }
2643 
2644  /* Compact storage in the allocatedDescs array */
2647 
2648  return result;
2649 }
union AllocateDesc::@18 desc
static AllocateDesc * allocatedDescs
Definition: fd.c:265
DIR * dir
Definition: fd.c:258
int closedir(DIR *)
Definition: dirent.c:123
AllocateDescKind kind
Definition: fd.c:253
#define ERROR
Definition: elog.h:46
FILE * file
Definition: fd.c:257
int fd
Definition: fd.c:259
#define elog(elevel,...)
Definition: elog.h:232
#define close(a)
Definition: win32.h:12
static int numAllocatedDescs
Definition: fd.c:263

◆ FreeDir()

int FreeDir ( DIR dir)

Definition at line 2838 of file fd.c.

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

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

2839 {
2840  int i;
2841 
2842  /* Nothing to do if AllocateDir failed */
2843  if (dir == NULL)
2844  return 0;
2845 
2846  DO_DB(elog(LOG, "FreeDir: Allocated %d", numAllocatedDescs));
2847 
2848  /* Remove dir from list of allocated dirs, if it's present */
2849  for (i = numAllocatedDescs; --i >= 0;)
2850  {
2851  AllocateDesc *desc = &allocatedDescs[i];
2852 
2853  if (desc->kind == AllocateDescDir && desc->desc.dir == dir)
2854  return FreeDesc(desc);
2855  }
2856 
2857  /* Only get here if someone passes us a dir not in allocatedDescs */
2858  elog(WARNING, "dir passed to FreeDir was not obtained from AllocateDir");
2859 
2860  return closedir(dir);
2861 }
union AllocateDesc::@18 desc
static AllocateDesc * allocatedDescs
Definition: fd.c:265
DIR * dir
Definition: fd.c:258
#define DO_DB(A)
Definition: fd.c:176
int closedir(DIR *)
Definition: dirent.c:123
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:253
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2619
#define WARNING
Definition: elog.h:40
#define elog(elevel,...)
Definition: elog.h:232
int i
static int numAllocatedDescs
Definition: fd.c:263

◆ FreeFile()

int FreeFile ( FILE *  file)

Definition at line 2658 of file fd.c.

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

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

2659 {
2660  int i;
2661 
2662  DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedDescs));
2663 
2664  /* Remove file from list of allocated files, if it's present */
2665  for (i = numAllocatedDescs; --i >= 0;)
2666  {
2667  AllocateDesc *desc = &allocatedDescs[i];
2668 
2669  if (desc->kind == AllocateDescFile && desc->desc.file == file)
2670  return FreeDesc(desc);
2671  }
2672 
2673  /* Only get here if someone passes us a file not in allocatedDescs */
2674  elog(WARNING, "file passed to FreeFile was not obtained from AllocateFile");
2675 
2676  return fclose(file);
2677 }
union AllocateDesc::@18 desc
static AllocateDesc * allocatedDescs
Definition: fd.c:265
#define DO_DB(A)
Definition: fd.c:176
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:253
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2619
#define WARNING
Definition: elog.h:40
FILE * file
Definition: fd.c:257
#define elog(elevel,...)
Definition: elog.h:232
int i
static int numAllocatedDescs
Definition: fd.c:263

◆ FreeVfd()

static void FreeVfd ( File  file)
static

Definition at line 1461 of file fd.c.

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

Referenced by FileClose(), and PathNameOpenFilePerm().

1462 {
1463  Vfd *vfdP = &VfdCache[file];
1464 
1465  DO_DB(elog(LOG, "FreeVfd: %d (%s)",
1466  file, vfdP->fileName ? vfdP->fileName : ""));
1467 
1468  if (vfdP->fileName != NULL)
1469  {
1470  free(vfdP->fileName);
1471  vfdP->fileName = NULL;
1472  }
1473  vfdP->fdstate = 0x0;
1474 
1475  vfdP->nextFree = VfdCache[0].nextFree;
1476  VfdCache[0].nextFree = file;
1477 }
File nextFree
Definition: fd.c:197
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
char * fileName
Definition: fd.c:201
unsigned short fdstate
Definition: fd.c:195
Definition: fd.c:192
#define free(a)
Definition: header.h:65
#define elog(elevel,...)
Definition: elog.h:232

◆ fsync_fname()

void fsync_fname ( const char *  fname,
bool  isdir 
)

Definition at line 671 of file fd.c.

References data_sync_elevel(), ERROR, and fsync_fname_ext().

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

672 {
673  fsync_fname_ext(fname, isdir, false, data_sync_elevel(ERROR));
674 }
#define ERROR
Definition: elog.h:46
int data_sync_elevel(int elevel)
Definition: fd.c:3805
int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3666

◆ fsync_fname_ext()

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

Definition at line 3666 of file fd.c.

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

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

3667 {
3668  int fd;
3669  int flags;
3670  int returncode;
3671 
3672  /*
3673  * Some OSs require directories to be opened read-only whereas other
3674  * systems don't allow us to fsync files opened read-only; so we need both
3675  * cases here. Using O_RDWR will cause us to fail to fsync files that are
3676  * not writable by our userid, but we assume that's OK.
3677  */
3678  flags = PG_BINARY;
3679  if (!isdir)
3680  flags |= O_RDWR;
3681  else
3682  flags |= O_RDONLY;
3683 
3684  fd = OpenTransientFile(fname, flags);
3685 
3686  /*
3687  * Some OSs don't allow us to open directories at all (Windows returns
3688  * EACCES), just ignore the error in that case. If desired also silently
3689  * ignoring errors about unreadable files. Log others.
3690  */
3691  if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
3692  return 0;
3693  else if (fd < 0 && ignore_perm && errno == EACCES)
3694  return 0;
3695  else if (fd < 0)
3696  {
3697  ereport(elevel,
3699  errmsg("could not open file \"%s\": %m", fname)));
3700  return -1;
3701  }
3702 
3703  returncode = pg_fsync(fd);
3704 
3705  /*
3706  * Some OSes don't allow us to fsync directories at all, so we can ignore
3707  * those errors. Anything else needs to be logged.
3708  */
3709  if (returncode != 0 && !(isdir && (errno == EBADF || errno == EINVAL)))
3710  {
3711  int save_errno;
3712 
3713  /* close file upon error, might not be in transaction context */
3714  save_errno = errno;
3715  (void) CloseTransientFile(fd);
3716  errno = save_errno;
3717 
3718  ereport(elevel,
3720  errmsg("could not fsync file \"%s\": %m", fname)));
3721  return -1;
3722  }
3723 
3724  if (CloseTransientFile(fd) != 0)
3725  {
3726  ereport(elevel,
3728  errmsg("could not close file \"%s\": %m", fname)));
3729  return -1;
3730  }
3731 
3732  return 0;
3733 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1271
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2509
int errcode_for_file_access(void)
Definition: elog.c:721
int CloseTransientFile(int fd)
Definition: fd.c:2686
static int elevel
Definition: vacuumlazy.c:401
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
int pg_fsync(int fd)
Definition: fd.c:357

◆ fsync_parent_path()

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

Definition at line 3742 of file fd.c.

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

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

3743 {
3744  char parentpath[MAXPGPATH];
3745 
3746  strlcpy(parentpath, fname, MAXPGPATH);
3747  get_parent_directory(parentpath);
3748 
3749  /*
3750  * get_parent_directory() returns an empty string if the input argument is
3751  * just a file name (see comments in path.c), so handle that as being the
3752  * current directory.
3753  */
3754  if (strlen(parentpath) == 0)
3755  strlcpy(parentpath, ".", MAXPGPATH);
3756 
3757  if (fsync_fname_ext(parentpath, true, false, elevel) != 0)
3758  return -1;
3759 
3760  return 0;
3761 }
#define MAXPGPATH
void get_parent_directory(char *path)
Definition: path.c:854
static int elevel
Definition: vacuumlazy.c:401
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3666

◆ GetNextTempTableSpace()

Oid GetNextTempTableSpace ( void  )

Definition at line 2987 of file fd.c.

References InvalidOid, nextTempTableSpace, numTempTableSpaces, and tempTableSpaces.

Referenced by GetDefaultTablespace(), and OpenTemporaryFile().

2988 {
2989  if (numTempTableSpaces > 0)
2990  {
2991  /* Advance nextTempTableSpace counter with wraparound */
2993  nextTempTableSpace = 0;
2995  }
2996  return InvalidOid;
2997 }
static int numTempTableSpaces
Definition: fd.c:285
static int nextTempTableSpace
Definition: fd.c:286
#define InvalidOid
Definition: postgres_ext.h:36
static Oid * tempTableSpaces
Definition: fd.c:284

◆ GetTempTablespaces()

int GetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2969 of file fd.c.

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

Referenced by FileSetInit().

2970 {
2971  int i;
2972 
2974  for (i = 0; i < numTempTableSpaces && i < numSpaces; ++i)
2975  tableSpaces[i] = tempTableSpaces[i];
2976 
2977  return i;
2978 }
static int numTempTableSpaces
Definition: fd.c:285
bool TempTablespacesAreSet(void)
Definition: fd.c:2954
#define Assert(condition)
Definition: c.h:804
static Oid * tempTableSpaces
Definition: fd.c:284
int i

◆ InitFileAccess()

void InitFileAccess ( void  )

Definition at line 881 of file fd.c.

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

Referenced by BaseInit().

882 {
883  Assert(SizeVfdCache == 0); /* call me only once */
884 
885  /* initialize cache header entry */
886  VfdCache = (Vfd *) malloc(sizeof(Vfd));
887  if (VfdCache == NULL)
888  ereport(FATAL,
889  (errcode(ERRCODE_OUT_OF_MEMORY),
890  errmsg("out of memory")));
891 
892  MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
894 
895  SizeVfdCache = 1;
896 }
static Size SizeVfdCache
Definition: fd.c:213
static Vfd * VfdCache
Definition: fd.c:212
int errcode(int sqlerrcode)
Definition: elog.c:698
#define MemSet(start, val, len)
Definition: c.h:1008
#define malloc(a)
Definition: header.h:50
#define FATAL
Definition: elog.h:49
Definition: fd.c:192
int fd
Definition: fd.c:194
#define VFD_CLOSED
Definition: fd.c:180
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ InitTemporaryFileAccess()

void InitTemporaryFileAccess ( void  )

Definition at line 911 of file fd.c.

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

Referenced by BaseInit().

912 {
913  Assert(SizeVfdCache != 0); /* InitFileAccess() needs to have run*/
914  Assert(!temporary_files_allowed); /* call me only once */
915 
916  /*
917  * Register before-shmem-exit hook to ensure temp files are dropped while
918  * we can still report stats.
919  */
921 
922 #ifdef USE_ASSERT_CHECKING
923  temporary_files_allowed = true;
924 #endif
925 }
static void BeforeShmemExit_Files(int code, Datum arg)
Definition: fd.c:3055
static Size SizeVfdCache
Definition: fd.c:213
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:333
#define Assert(condition)
Definition: c.h:804

◆ Insert()

static void Insert ( File  file)
static

Definition at line 1302 of file fd.c.

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

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

1303 {
1304  Vfd *vfdP;
1305 
1306  Assert(file != 0);
1307 
1308  DO_DB(elog(LOG, "Insert %d (%s)",
1309  file, VfdCache[file].fileName));
1310  DO_DB(_dump_lru());
1311 
1312  vfdP = &VfdCache[file];
1313 
1314  vfdP->lruMoreRecently = 0;
1316  VfdCache[0].lruLessRecently = file;
1318 
1319  DO_DB(_dump_lru());
1320 }
File lruLessRecently
Definition: fd.c:199
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
Definition: fd.c:192
#define Assert(condition)
Definition: c.h:804
File lruMoreRecently
Definition: fd.c:198
#define elog(elevel,...)
Definition: elog.h:232

◆ looks_like_temp_rel_name()

bool looks_like_temp_rel_name ( const char *  name)

Definition at line 3331 of file fd.c.

References CloseTransientFile(), ereport, errcode_for_file_access(), errmsg(), vfd::fd, forkname_chars(), LOG, and OpenTransientFile().

Referenced by RemovePgTempRelationFilesInDbspace(), and sendDir().

3332 {
3333  int pos;
3334  int savepos;
3335 
3336  /* Must start with "t". */
3337  if (name[0] != 't')
3338  return false;
3339 
3340  /* Followed by a non-empty string of digits and then an underscore. */
3341  for (pos = 1; isdigit((unsigned char) name[pos]); ++pos)
3342  ;
3343  if (pos == 1 || name[pos] != '_')
3344  return false;
3345 
3346  /* Followed by another nonempty string of digits. */
3347  for (savepos = ++pos; isdigit((unsigned char) name[pos]); ++pos)
3348  ;
3349  if (savepos == pos)
3350  return false;
3351 
3352  /* We might have _forkname or .segment or both. */
3353  if (name[pos] == '_')
3354  {
3355  int forkchar = forkname_chars(&name[pos + 1], NULL);
3356 
3357  if (forkchar <= 0)
3358  return false;
3359  pos += forkchar + 1;
3360  }
3361  if (name[pos] == '.')
3362  {
3363  int segchar;
3364 
3365  for (segchar = 1; isdigit((unsigned char) name[pos + segchar]); ++segchar)
3366  ;
3367  if (segchar <= 1)
3368  return false;
3369  pos += segchar;
3370  }
3371 
3372  /* Now we should be at the end. */
3373  if (name[pos] != '\0')
3374  return false;
3375  return true;
3376 }
int forkname_chars(const char *str, ForkNumber *fork)
Definition: relpath.c:81
const char * name
Definition: encode.c:561

◆ LruDelete()

static void LruDelete ( File  file)
static

Definition at line 1276 of file fd.c.

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

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

1277 {
1278  Vfd *vfdP;
1279 
1280  Assert(file != 0);
1281 
1282  DO_DB(elog(LOG, "LruDelete %d (%s)",
1283  file, VfdCache[file].fileName));
1284 
1285  vfdP = &VfdCache[file];
1286 
1287  /*
1288  * Close the file. We aren't expecting this to fail; if it does, better
1289  * to leak the FD than to mess up our internal state.
1290  */
1291  if (close(vfdP->fd) != 0)
1293  "could not close file \"%s\": %m", vfdP->fileName);
1294  vfdP->fd = VFD_CLOSED;
1295  --nfile;
1296 
1297  /* delete the vfd record from the LRU ring */
1298  Delete(file);
1299 }
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:190
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
static void Delete(File file)
Definition: fd.c:1257
#define LOG
Definition: elog.h:26
char * fileName
Definition: fd.c:201
static int nfile
Definition: fd.c:218
unsigned short fdstate
Definition: fd.c:195
Definition: fd.c:192
int fd
Definition: fd.c:194
int data_sync_elevel(int elevel)
Definition: fd.c:3805
#define VFD_CLOSED
Definition: fd.c:180
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232
#define close(a)
Definition: win32.h:12

◆ LruInsert()

static int LruInsert ( File  file)
static

Definition at line 1324 of file fd.c.

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

Referenced by FileAccess().

1325 {
1326  Vfd *vfdP;
1327 
1328  Assert(file != 0);
1329 
1330  DO_DB(elog(LOG, "LruInsert %d (%s)",
1331  file, VfdCache[file].fileName));
1332 
1333  vfdP = &VfdCache[file];
1334 
1335  if (FileIsNotOpen(file))
1336  {
1337  /* Close excess kernel FDs. */
1338  ReleaseLruFiles();
1339 
1340  /*
1341  * The open could still fail for lack of file descriptors, eg due to
1342  * overall system file table being full. So, be prepared to release
1343  * another FD if necessary...
1344  */
1345  vfdP->fd = BasicOpenFilePerm(vfdP->fileName, vfdP->fileFlags,
1346  vfdP->fileMode);
1347  if (vfdP->fd < 0)
1348  {
1349  DO_DB(elog(LOG, "re-open failed: %m"));
1350  return -1;
1351  }
1352  else
1353  {
1354  ++nfile;
1355  }
1356  }
1357 
1358  /*
1359  * put it at the head of the Lru ring
1360  */
1361 
1362  Insert(file);
1363 
1364  return 0;
1365 }
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
mode_t fileMode
Definition: fd.c:204
char * fileName
Definition: fd.c:201
static int nfile
Definition: fd.c:218
Definition: fd.c:192
int fd
Definition: fd.c:194
static void Insert(File file)
Definition: fd.c:1302
static void ReleaseLruFiles(void)
Definition: fd.c:1393
#define FileIsNotOpen(file)
Definition: fd.c:185
#define Assert(condition)
Definition: c.h:804
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1091
#define elog(elevel,...)
Definition: elog.h:232
int fileFlags
Definition: fd.c:203

◆ MakePGDirectory()

int MakePGDirectory ( const char *  directoryName)

◆ OpenPipeStream()

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

Definition at line 2562 of file fd.c.

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

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

2563 {
2564  FILE *file;
2565  int save_errno;
2566 
2567  DO_DB(elog(LOG, "OpenPipeStream: Allocated %d (%s)",
2568  numAllocatedDescs, command));
2569 
2570  /* Can we allocate another non-virtual FD? */
2571  if (!reserveAllocatedDesc())
2572  ereport(ERROR,
2573  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2574  errmsg("exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"",
2575  maxAllocatedDescs, command)));
2576 
2577  /* Close excess kernel FDs. */
2578  ReleaseLruFiles();
2579 
2580 TryAgain:
2581  fflush(stdout);
2582  fflush(stderr);
2584  errno = 0;
2585  file = popen(command, mode);
2586  save_errno = errno;
2588  errno = save_errno;
2589  if (file != NULL)
2590  {
2592 
2593  desc->kind = AllocateDescPipe;
2594  desc->desc.file = file;
2597  return desc->desc.file;
2598  }
2599 
2600  if (errno == EMFILE || errno == ENFILE)
2601  {
2602  ereport(LOG,
2603  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2604  errmsg("out of file descriptors: %m; release and retry")));
2605  if (ReleaseLruFile())
2606  goto TryAgain;
2607  errno = save_errno;
2608  }
2609 
2610  return NULL;
2611 }
static PgChecksumMode mode
Definition: pg_checksums.c:65
union AllocateDesc::@18 desc
static AllocateDesc * allocatedDescs
Definition: fd.c:265
#define DO_DB(A)
Definition: fd.c:176
int errcode(int sqlerrcode)
Definition: elog.c:698
static bool reserveAllocatedDesc(void)
Definition: fd.c:2384
#define SIGPIPE
Definition: win32_port.h:172
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:253
static bool ReleaseLruFile(void)
Definition: fd.c:1371
#define ERROR
Definition: elog.h:46
#define SIG_IGN
Definition: win32_port.h:164
static void ReleaseLruFiles(void)
Definition: fd.c:1393
FILE * file
Definition: fd.c:257
#define ereport(elevel,...)
Definition: elog.h:157
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:170
#define SIG_DFL
Definition: win32_port.h:162
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:724
SubTransactionId create_subid
Definition: fd.c:254
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
static int maxAllocatedDescs
Definition: fd.c:264
static int numAllocatedDescs
Definition: fd.c:263

◆ OpenTemporaryFile()

File OpenTemporaryFile ( bool  interXact)

Definition at line 1705 of file fd.c.

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

Referenced by BufFileCreateTemp(), and extendBufFile().

1706 {
1707  File file = 0;
1708 
1709  Assert(temporary_files_allowed); /* check temp file access is up */
1710 
1711  /*
1712  * Make sure the current resource owner has space for this File before we
1713  * open it, if we'll be registering it below.
1714  */
1715  if (!interXact)
1717 
1718  /*
1719  * If some temp tablespace(s) have been given to us, try to use the next
1720  * one. If a given tablespace can't be found, we silently fall back to
1721  * the database's default tablespace.
1722  *
1723  * BUT: if the temp file is slated to outlive the current transaction,
1724  * force it into the database's default tablespace, so that it will not
1725  * pose a threat to possible tablespace drop attempts.
1726  */
1727  if (numTempTableSpaces > 0 && !interXact)
1728  {
1729  Oid tblspcOid = GetNextTempTableSpace();
1730 
1731  if (OidIsValid(tblspcOid))
1732  file = OpenTemporaryFileInTablespace(tblspcOid, false);
1733  }
1734 
1735  /*
1736  * If not, or if tablespace is bad, create in database's default
1737  * tablespace. MyDatabaseTableSpace should normally be set before we get
1738  * here, but just in case it isn't, fall back to pg_default tablespace.
1739  */
1740  if (file <= 0)
1743  DEFAULTTABLESPACE_OID,
1744  true);
1745 
1746  /* Mark it for deletion at close and temporary file size limit */
1748 
1749  /* Register it with the current resource owner */
1750  if (!interXact)
1751  RegisterTemporaryFile(file);
1752 
1753  return file;
1754 }
static File OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
Definition: fd.c:1785
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:190
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
#define FD_DELETE_AT_CLOSE
Definition: fd.c:188
static Vfd * VfdCache
Definition: fd.c:212
static int numTempTableSpaces
Definition: fd.c:285
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
Oid MyDatabaseTableSpace
Definition: globals.c:90
Oid GetNextTempTableSpace(void)
Definition: fd.c:2987
unsigned short fdstate
Definition: fd.c:195
static void RegisterTemporaryFile(File file)
Definition: fd.c:1536
#define Assert(condition)
Definition: c.h:804
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1286
int File
Definition: fd.h:54

◆ OpenTemporaryFileInTablespace()

static File OpenTemporaryFileInTablespace ( Oid  tblspcOid,
bool  rejectError 
)
static

Definition at line 1785 of file fd.c.

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

Referenced by OpenTemporaryFile().

1786 {
1787  char tempdirpath[MAXPGPATH];
1788  char tempfilepath[MAXPGPATH];
1789  File file;
1790 
1791  TempTablespacePath(tempdirpath, tblspcOid);
1792 
1793  /*
1794  * Generate a tempfile name that should be unique within the current
1795  * database instance.
1796  */
1797  snprintf(tempfilepath, sizeof(tempfilepath), "%s/%s%d.%ld",
1798  tempdirpath, PG_TEMP_FILE_PREFIX, MyProcPid, tempFileCounter++);
1799 
1800  /*
1801  * Open the file. Note: we don't use O_EXCL, in case there is an orphaned
1802  * temp file that can be reused.
1803  */
1804  file = PathNameOpenFile(tempfilepath,
1805  O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1806  if (file <= 0)
1807  {
1808  /*
1809  * We might need to create the tablespace's tempfile directory, if no
1810  * one has yet done so.
1811  *
1812  * Don't check for an error from MakePGDirectory; it could fail if
1813  * someone else just did the same thing. If it doesn't work then
1814  * we'll bomb out on the second create attempt, instead.
1815  */
1816  (void) MakePGDirectory(tempdirpath);
1817 
1818  file = PathNameOpenFile(tempfilepath,
1819  O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1820  if (file <= 0 && rejectError)
1821  elog(ERROR, "could not create temporary file \"%s\": %m",
1822  tempfilepath);
1823  }
1824 
1825  return file;
1826 }
int MyProcPid
Definition: globals.c:43
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1564
void TempTablespacePath(char *path, Oid tablespace)
Definition: fd.c:1760
#define PG_BINARY
Definition: c.h:1271
#define ERROR
Definition: elog.h:46
#define PG_TEMP_FILE_PREFIX
Definition: pg_checksums.c:63
#define MAXPGPATH
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3782
static long tempFileCounter
Definition: fd.c:276
#define elog(elevel,...)
Definition: elog.h:232
#define snprintf
Definition: port.h:217
int File
Definition: fd.h:54

◆ OpenTransientFile()

◆ OpenTransientFilePerm()

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

Definition at line 2518 of file fd.c.

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

Referenced by be_lo_export(), and OpenTransientFile().

2519 {
2520  int fd;
2521 
2522  DO_DB(elog(LOG, "OpenTransientFile: Allocated %d (%s)",
2523  numAllocatedDescs, fileName));
2524 
2525  /* Can we allocate another non-virtual FD? */
2526  if (!reserveAllocatedDesc())
2527  ereport(ERROR,
2528  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2529  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2530  maxAllocatedDescs, fileName)));
2531 
2532  /* Close excess kernel FDs. */
2533  ReleaseLruFiles();
2534 
2535  fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
2536 
2537  if (fd >= 0)
2538  {
2540 
2541  desc->kind = AllocateDescRawFD;
2542  desc->desc.fd = fd;
2545 
2546  return fd;
2547  }
2548 
2549  return -1; /* failure */
2550 }
union AllocateDesc::@18 desc
static AllocateDesc * allocatedDescs
Definition: fd.c:265
#define DO_DB(A)
Definition: fd.c:176
int errcode(int sqlerrcode)
Definition: elog.c:698
static bool reserveAllocatedDesc(void)
Definition: fd.c:2384
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:253
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define ERROR
Definition: elog.h:46
static void ReleaseLruFiles(void)
Definition: fd.c:1393
#define ereport(elevel,...)
Definition: elog.h:157
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:724
SubTransactionId create_subid
Definition: fd.c:254
int fd
Definition: fd.c:259
int errmsg(const char *fmt,...)
Definition: elog.c:909
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1091
#define elog(elevel,...)
Definition: elog.h:232
static int maxAllocatedDescs
Definition: fd.c:264
static int numAllocatedDescs
Definition: fd.c:263

◆ PathNameCreateTemporaryDir()

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

Definition at line 1641 of file fd.c.

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

Referenced by FileSetCreate().

1642 {
1643  if (MakePGDirectory(directory) < 0)
1644  {
1645  if (errno == EEXIST)
1646  return;
1647 
1648  /*
1649  * Failed. Try to create basedir first in case it's missing. Tolerate
1650  * EEXIST to close a race against another process following the same
1651  * algorithm.
1652  */
1653  if (MakePGDirectory(basedir) < 0 && errno != EEXIST)
1654  ereport(ERROR,
1656  errmsg("cannot create temporary directory \"%s\": %m",
1657  basedir)));
1658 
1659  /* Try again. */
1660  if (MakePGDirectory(directory) < 0 && errno != EEXIST)
1661  ereport(ERROR,
1663  errmsg("cannot create temporary subdirectory \"%s\": %m",
1664  directory)));
1665  }
1666 }
static char * basedir
#define ERROR
Definition: elog.h:46
int errcode_for_file_access(void)
Definition: elog.c:721
#define ereport(elevel,...)
Definition: elog.h:157
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3782
static const char * directory
Definition: zic.c:632
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ PathNameCreateTemporaryFile()

File PathNameCreateTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1842 of file fd.c.

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

Referenced by FileSetCreate().

1843 {
1844  File file;
1845 
1846  Assert(temporary_files_allowed); /* check temp file access is up */
1847 
1849 
1850  /*
1851  * Open the file. Note: we don't use O_EXCL, in case there is an orphaned
1852  * temp file that can be reused.
1853  */
1854  file = PathNameOpenFile(path, O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1855  if (file <= 0)
1856  {
1857  if (error_on_failure)
1858  ereport(ERROR,
1860  errmsg("could not create temporary file \"%s\": %m",
1861  path)));
1862  else
1863  return file;
1864  }
1865 
1866  /* Mark it for temp_file_limit accounting. */
1868 
1869  /* Register it for automatic close. */
1870  RegisterTemporaryFile(file);
1871 
1872  return file;
1873 }
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1564
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:190
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
static Vfd * VfdCache
Definition: fd.c:212
#define PG_BINARY
Definition: c.h:1271
#define ERROR
Definition: elog.h:46
int errcode_for_file_access(void)
Definition: elog.c:721
unsigned short fdstate
Definition: fd.c:195
#define ereport(elevel,...)
Definition: elog.h:157
static void RegisterTemporaryFile(File file)
Definition: fd.c:1536
#define Assert(condition)
Definition: c.h:804
int errmsg(const char *fmt,...)
Definition: elog.c:909
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1286
int File
Definition: fd.h:54

◆ PathNameDeleteTemporaryDir()

void PathNameDeleteTemporaryDir ( const char *  dirname)

Definition at line 1672 of file fd.c.

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

Referenced by FileSetDeleteAll().

1673 {
1674  struct stat statbuf;
1675 
1676  /* Silently ignore missing directory. */
1677  if (stat(dirname, &statbuf) != 0 && errno == ENOENT)
1678  return;
1679 
1680  /*
1681  * Currently, walkdir doesn't offer a way for our passed in function to
1682  * maintain state. Perhaps it should, so that we could tell the caller
1683  * whether this operation succeeded or failed. Since this operation is
1684  * used in a cleanup path, we wouldn't actually behave differently: we'll
1685  * just log failures.
1686  */
1687  walkdir(dirname, unlink_if_exists_fname, false, LOG);
1688 }
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
Definition: fd.c:3533
#define LOG
Definition: elog.h:26
static void unlink_if_exists_fname(const char *fname, bool isdir, int elevel)
Definition: fd.c:3641
#define stat
Definition: win32_port.h:283

◆ PathNameDeleteTemporaryFile()

bool PathNameDeleteTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1913 of file fd.c.

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

Referenced by FileSetDelete(), and unlink_if_exists_fname().

1914 {
1915  struct stat filestats;
1916  int stat_errno;
1917 
1918  /* Get the final size for pgstat reporting. */
1919  if (stat(path, &filestats) != 0)
1920  stat_errno = errno;
1921  else
1922  stat_errno = 0;
1923 
1924  /*
1925  * Unlike FileClose's automatic file deletion code, we tolerate
1926  * non-existence to support BufFileDeleteFileSet which doesn't know how
1927  * many segments it has to delete until it runs out.
1928  */
1929  if (stat_errno == ENOENT)
1930  return false;
1931 
1932  if (unlink(path) < 0)
1933  {
1934  if (errno != ENOENT)
1935  ereport(error_on_failure ? ERROR : LOG,
1937  errmsg("could not unlink temporary file \"%s\": %m",
1938  path)));
1939  return false;
1940  }
1941 
1942  if (stat_errno == 0)
1943  ReportTemporaryFileUsage(path, filestats.st_size);
1944  else
1945  {
1946  errno = stat_errno;
1947  ereport(LOG,
1949  errmsg("could not stat file \"%s\": %m", path)));
1950  }
1951 
1952  return true;
1953 }
#define LOG
Definition: elog.h:26
#define ERROR
Definition: elog.h:46
int errcode_for_file_access(void)
Definition: elog.c:721
static void ReportTemporaryFileUsage(const char *path, off_t size)
Definition: fd.c:1517
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define stat
Definition: win32_port.h:283

◆ PathNameOpenFile()

File PathNameOpenFile ( const char *  fileName,
int  fileFlags 
)

Definition at line 1564 of file fd.c.

References PathNameOpenFilePerm(), and pg_file_create_mode.

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

1565 {
1566  return PathNameOpenFilePerm(fileName, fileFlags, pg_file_create_mode);
1567 }
File PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1577
int pg_file_create_mode
Definition: file_perm.c:19

◆ PathNameOpenFilePerm()

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

Definition at line 1577 of file fd.c.

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

Referenced by PathNameOpenFile().

1578 {
1579  char *fnamecopy;
1580  File file;
1581  Vfd *vfdP;
1582 
1583  DO_DB(elog(LOG, "PathNameOpenFilePerm: %s %x %o",
1584  fileName, fileFlags, fileMode));
1585 
1586  /*
1587  * We need a malloc'd copy of the file name; fail cleanly if no room.
1588  */
1589  fnamecopy = strdup(fileName);
1590  if (fnamecopy == NULL)
1591  ereport(ERROR,
1592  (errcode(ERRCODE_OUT_OF_MEMORY),
1593  errmsg("out of memory")));
1594 
1595  file = AllocateVfd();
1596  vfdP = &VfdCache[file];
1597 
1598  /* Close excess kernel FDs. */
1599  ReleaseLruFiles();
1600 
1601  vfdP->fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
1602 
1603  if (vfdP->fd < 0)
1604  {
1605  int save_errno = errno;
1606 
1607  FreeVfd(file);
1608  free(fnamecopy);
1609  errno = save_errno;
1610  return -1;
1611  }
1612  ++nfile;
1613  DO_DB(elog(LOG, "PathNameOpenFile: success %d",
1614  vfdP->fd));
1615 
1616  vfdP->fileName = fnamecopy;
1617  /* Saved flags are adjusted to be OK for re-opening file */
1618  vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
1619  vfdP->fileMode = fileMode;
1620  vfdP->fileSize = 0;
1621  vfdP->fdstate = 0x0;
1622  vfdP->resowner = NULL;
1623 
1624  Insert(file);
1625 
1626  return file;
1627 }
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
int errcode(int sqlerrcode)
Definition: elog.c:698
#define LOG
Definition: elog.h:26
mode_t fileMode
Definition: fd.c:204
#define ERROR
Definition: elog.h:46
char * fileName
Definition: fd.c:201
static int nfile
Definition: fd.c:218
static File AllocateVfd(void)
Definition: fd.c:1403
unsigned short fdstate
Definition: fd.c:195
Definition: fd.c:192
off_t fileSize
Definition: fd.c:200
int fd
Definition: fd.c:194
static void Insert(File file)
Definition: fd.c:1302
ResourceOwner resowner
Definition: fd.c:196
static void ReleaseLruFiles(void)
Definition: fd.c:1393
#define ereport(elevel,...)
Definition: elog.h:157
#define free(a)
Definition: header.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:909
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1091
#define elog(elevel,...)
Definition: elog.h:232
static void FreeVfd(File file)
Definition: fd.c:1461
int fileFlags
Definition: fd.c:203
int File
Definition: fd.h:54

◆ PathNameOpenTemporaryFile()

File PathNameOpenTemporaryFile ( const char *  path,
int  mode 
)

Definition at line 1882 of file fd.c.

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

Referenced by FileSetOpen().

1883 {
1884  File file;
1885 
1886  Assert(temporary_files_allowed); /* check temp file access is up */
1887 
1889 
1890  file = PathNameOpenFile(path, mode | PG_BINARY);
1891 
1892  /* If no such file, then we don't raise an error. */
1893  if (file <= 0 && errno != ENOENT)
1894  ereport(ERROR,
1896  errmsg("could not open temporary file \"%s\": %m",
1897  path)));
1898 
1899  if (file > 0)
1900  {
1901  /* Register it for automatic close. */
1902  RegisterTemporaryFile(file);
1903  }
1904 
1905  return file;
1906 }
static PgChecksumMode mode
Definition: pg_checksums.c:65
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1564
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
#define PG_BINARY
Definition: c.h:1271
#define ERROR
Definition: elog.h:46
int errcode_for_file_access(void)
Definition: elog.c:721
#define ereport(elevel,...)
Definition: elog.h:157
static void RegisterTemporaryFile(File file)
Definition: fd.c:1536
#define Assert(condition)
Definition: c.h:804
int errmsg(const char *fmt,...)
Definition: elog.c:909
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1286
int File
Definition: fd.h:54

◆ pg_fdatasync()

int pg_fdatasync ( int  fd)

Definition at line 447 of file fd.c.

References enableFsync, and fsync.

Referenced by issue_xlog_fsync().

448 {
449  if (enableFsync)
450  {
451 #ifdef HAVE_FDATASYNC
452  return fdatasync(fd);
453 #else
454  return fsync(fd);
455 #endif
456  }
457  else
458  return 0;
459 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define fsync(fd)
Definition: win32_port.h:76
bool enableFsync
Definition: globals.c:122

◆ pg_flush_data()

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

Definition at line 467 of file fd.c.

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

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

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

◆ pg_fsync()

int pg_fsync ( int  fd)

Definition at line 357 of file fd.c.

References Assert, 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(), do_pg_start_backup(), durable_rename(), FileSync(), fsync_fname_ext(), heap_xlog_logical_rewrite(), readRecoverySignalFile(), RecreateTwoPhaseFile(), RestoreSlotFromDisk(), SaveSlotToPath(), SlruPhysicalWritePage(), SlruSyncFileTag(), SnapBuildSerialize(), update_controlfile(), write_auto_conf_file(), write_relmap_file(), WriteControlFile(), writeTimeLineHistory(), writeTimeLineHistoryFile(), XLogFileCopy(), and XLogFileInitInternal().

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

◆ pg_fsync_no_writethrough()

int pg_fsync_no_writethrough ( int  fd)

Definition at line 412 of file fd.c.

References enableFsync, and fsync.

Referenced by issue_xlog_fsync(), and pg_fsync().

413 {
414  if (enableFsync)
415  return fsync(fd);
416  else
417  return 0;
418 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define fsync(fd)
Definition: win32_port.h:76
bool enableFsync
Definition: globals.c:122

◆ pg_fsync_writethrough()

int pg_fsync_writethrough ( int  fd)

Definition at line 424 of file fd.c.

References enableFsync.

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

425 {
426  if (enableFsync)
427  {
428 #ifdef WIN32
429  return _commit(fd);
430 #elif defined(F_FULLFSYNC)
431  return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
432 #else
433  errno = ENOSYS;
434  return -1;
435 #endif
436  }
437  else
438  return 0;
439 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
bool enableFsync
Definition: globals.c:122

◆ pg_pwritev_with_retry()

ssize_t pg_pwritev_with_retry ( int  fd,
const struct iovec iov,
int  iovcnt,
off_t  offset 
)

Definition at line 3815 of file fd.c.

References Assert, iovec::iov_base, iovec::iov_len, Min, and pg_pwritev().

Referenced by XLogFileInitInternal().

3816 {
3817  struct iovec iov_copy[PG_IOV_MAX];
3818  ssize_t sum = 0;
3819  ssize_t part;
3820 
3821  /* We'd better have space to make a copy, in case we need to retry. */
3822  if (iovcnt > PG_IOV_MAX)
3823  {
3824  errno = EINVAL;
3825  return -1;
3826  }
3827 
3828  for (;;)
3829  {
3830  /* Write as much as we can. */
3831  part = pg_pwritev(fd, iov, iovcnt, offset);
3832  if (part < 0)
3833  return -1;
3834 
3835 #ifdef SIMULATE_SHORT_WRITE
3836  part = Min(part, 4096);
3837 #endif
3838 
3839  /* Count our progress. */
3840  sum += part;
3841  offset += part;
3842 
3843  /* Step over iovecs that are done. */
3844  while (iovcnt > 0 && iov->iov_len <= part)
3845  {
3846  part -= iov->iov_len;
3847  ++iov;
3848  --iovcnt;
3849  }
3850 
3851  /* Are they all done? */
3852  if (iovcnt == 0)
3853  {
3854  /* We don't expect the kernel to write more than requested. */
3855  Assert(part == 0);
3856  break;
3857  }
3858 
3859  /*
3860  * Move whatever's left to the front of our mutable copy and adjust
3861  * the leading iovec.
3862  */
3863  Assert(iovcnt > 0);
3864  memmove(iov_copy, iov, sizeof(*iov) * iovcnt);
3865  Assert(iov->iov_len > part);
3866  iov_copy[0].iov_base = (char *) iov_copy[0].iov_base + part;
3867  iov_copy[0].iov_len -= part;
3868  iov = iov_copy;
3869  }
3870 
3871  return sum;
3872 }
size_t iov_len
Definition: pg_iovec.h:27
void * iov_base
Definition: pg_iovec.h:26
#define Min(x, y)
Definition: c.h:986
static int fd(const char *x, int i)
Definition: preproc-init.c:105
ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
Definition: pwritev.c:29
#define PG_IOV_MAX
Definition: pg_iovec.h:40
Definition: pg_iovec.h:24
#define Assert(condition)
Definition: c.h:804

◆ pg_truncate()

int pg_truncate ( const char *  path,
off_t  length 
)

Definition at line 640 of file fd.c.

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

Referenced by do_truncate().

641 {
642 #ifdef WIN32
643  int save_errno;
644  int ret;
645  int fd;
646 
647  fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
648  if (fd >= 0)
649  {
650  ret = ftruncate(fd, 0);
651  save_errno = errno;
652  CloseTransientFile(fd);
653  errno = save_errno;
654  }
655  else
656  ret = -1;
657 
658  return ret;
659 #else
660  return truncate(path, length);
661 #endif
662 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1271
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2509
int CloseTransientFile(int fd)
Definition: fd.c:2686
#define ftruncate(a, b)
Definition: win32_port.h:73

◆ ReadDir()

◆ ReadDirExtended()

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

Definition at line 2801 of file fd.c.

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

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

2802 {
2803  struct dirent *dent;
2804 
2805  /* Give a generic message for AllocateDir failure, if caller didn't */
2806  if (dir == NULL)
2807  {
2808  ereport(elevel,
2810  errmsg("could not open directory \"%s\": %m",
2811  dirname)));
2812  return NULL;
2813  }
2814 
2815  errno = 0;
2816  if ((dent = readdir(dir)) != NULL)
2817  return dent;
2818 
2819  if (errno)
2820  ereport(elevel,
2822  errmsg("could not read directory \"%s\": %m",
2823  dirname)));
2824  return NULL;
2825 }
Definition: dirent.h:9
int errcode_for_file_access(void)
Definition: elog.c:721
static int elevel
Definition: vacuumlazy.c:401
#define ereport(elevel,...)
Definition: elog.h:157
struct dirent * readdir(DIR *)
Definition: dirent.c:78
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ RegisterTemporaryFile()

static void RegisterTemporaryFile ( File  file)
static

Definition at line 1536 of file fd.c.

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

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

1537 {
1540 
1541  /* Backup mechanism for closing at end of xact. */
1544 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
static Vfd * VfdCache
Definition: fd.c:212
static bool have_xact_temporary_files
Definition: fd.c:224
void ResourceOwnerRememberFile(ResourceOwner owner, File file)
Definition: resowner.c:1297
unsigned short fdstate
Definition: fd.c:195
ResourceOwner resowner
Definition: fd.c:196
#define FD_CLOSE_AT_EOXACT
Definition: fd.c:189

◆ ReleaseExternalFD()

◆ ReleaseLruFile()

static bool ReleaseLruFile ( void  )
static

Definition at line 1371 of file fd.c.

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

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

1372 {
1373  DO_DB(elog(LOG, "ReleaseLruFile. Opened %d", nfile));
1374 
1375  if (nfile > 0)
1376  {
1377  /*
1378  * There are opened files and so there should be at least one used vfd
1379  * in the ring.
1380  */
1381  Assert(VfdCache[0].lruMoreRecently != 0);
1382  LruDelete(VfdCache[0].lruMoreRecently);
1383  return true; /* freed a file */
1384  }
1385  return false; /* no files available to free */
1386 }
#define DO_DB(A)
Definition: fd.c:176
static Vfd * VfdCache
Definition: fd.c:212
#define LOG
Definition: elog.h:26
static void LruDelete(File file)
Definition: fd.c:1276
static int nfile
Definition: fd.c:218
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232

◆ ReleaseLruFiles()

static void ReleaseLruFiles ( void  )
static

Definition at line 1393 of file fd.c.

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

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

1394 {
1396  {
1397  if (!ReleaseLruFile())
1398  break;
1399  }
1400 }
static int numExternalFDs
Definition: fd.c:270
int max_safe_fds
Definition: fd.c:158
static bool ReleaseLruFile(void)
Definition: fd.c:1371
static int nfile
Definition: fd.c:218
static int numAllocatedDescs
Definition: fd.c:263

◆ RemovePgTempFiles()

void RemovePgTempFiles ( void  )

Definition at line 3150 of file fd.c.

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

Referenced by PostmasterMain(), and PostmasterStateMachine().

3151 {
3152  char temp_path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY) + sizeof(PG_TEMP_FILES_DIR)];
3153  DIR *spc_dir;
3154  struct dirent *spc_de;
3155 
3156  /*
3157  * First process temp files in pg_default ($PGDATA/base)
3158  */
3159  snprintf(temp_path, sizeof(temp_path), "base/%s", PG_TEMP_FILES_DIR);
3160  RemovePgTempFilesInDir(temp_path, true, false);
3161  RemovePgTempRelationFiles("base");
3162 
3163  /*
3164  * Cycle through temp directories for all non-default tablespaces.
3165  */
3166  spc_dir = AllocateDir("pg_tblspc");
3167 
3168  while ((spc_de = ReadDirExtended(spc_dir, "pg_tblspc", LOG)) != NULL)
3169  {
3170  if (strcmp(spc_de->d_name, ".") == 0 ||
3171  strcmp(spc_de->d_name, "..") == 0)
3172  continue;
3173 
3174  snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s/%s",
3176  RemovePgTempFilesInDir(temp_path, true, false);
3177 
3178  snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s",
3180  RemovePgTempRelationFiles(temp_path);
3181  }
3182 
3183  FreeDir(spc_dir);
3184 
3185  /*
3186  * In EXEC_BACKEND case there is a pgsql_tmp directory at the top level of
3187  * DataDir as well. However, that is *not* cleaned here because doing so
3188  * would create a race condition. It's done separately, earlier in
3189  * postmaster startup.
3190  */
3191 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2801
#define PG_TEMP_FILES_DIR
Definition: pg_checksums.c:62
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
static void RemovePgTempRelationFiles(const char *tsdirname)
Definition: fd.c:3275
Definition: dirent.c:25
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, bool unlink_all)
Definition: fd.c:3209
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2720
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217
int FreeDir(DIR *dir)
Definition: fd.c:2838

◆ RemovePgTempFilesInDir()

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

Definition at line 3209 of file fd.c.

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

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

3210 {
3211  DIR *temp_dir;
3212  struct dirent *temp_de;
3213  char rm_path[MAXPGPATH * 2];
3214 
3215  temp_dir = AllocateDir(tmpdirname);
3216 
3217  if (temp_dir == NULL && errno == ENOENT && missing_ok)
3218  return;
3219 
3220  while ((temp_de = ReadDirExtended(temp_dir, tmpdirname, LOG)) != NULL)
3221  {
3222  if (strcmp(temp_de->d_name, ".") == 0 ||
3223  strcmp(temp_de->d_name, "..") == 0)
3224  continue;
3225 
3226  snprintf(rm_path, sizeof(rm_path), "%s/%s",
3227  tmpdirname, temp_de->d_name);
3228 
3229  if (unlink_all ||
3230  strncmp(temp_de->d_name,
3232  strlen(PG_TEMP_FILE_PREFIX)) == 0)
3233  {
3234  struct stat statbuf;
3235 
3236  if (lstat(rm_path, &statbuf) < 0)
3237  {
3238  ereport(LOG,
3240  errmsg("could not stat file \"%s\": %m", rm_path)));
3241  continue;
3242  }
3243 
3244  if (S_ISDIR(statbuf.st_mode))
3245  {
3246  /* recursively remove contents, then directory itself */
3247  RemovePgTempFilesInDir(rm_path, false, true);
3248 
3249  if (rmdir(rm_path) < 0)
3250  ereport(LOG,
3252  errmsg("could not remove directory \"%s\": %m",
3253  rm_path)));
3254  }
3255  else
3256  {
3257  if (unlink(rm_path) < 0)
3258  ereport(LOG,
3260  errmsg("could not remove file \"%s\": %m",
3261  rm_path)));
3262  }
3263  }
3264  else
3265  ereport(LOG,
3266  (errmsg("unexpected file found in temporary-files directory: \"%s\"",
3267  rm_path)));
3268  }
3269 
3270  FreeDir(temp_dir);
3271 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2801
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define PG_TEMP_FILE_PREFIX
Definition: pg_checksums.c:63
#define MAXPGPATH
void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, bool unlink_all)
Definition: fd.c:3209
int errcode_for_file_access(void)
Definition: elog.c:721
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2720
#define ereport(elevel,...)
Definition: elog.h:157
#define S_ISDIR(m)
Definition: win32_port.h:324
#define lstat(path, sb)
Definition: win32_port.h:284
int errmsg(const char *fmt,...)
Definition: elog.c:909
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217
int FreeDir(DIR *dir)
Definition: fd.c:2838

◆ RemovePgTempRelationFiles()

static void RemovePgTempRelationFiles ( const char *  tsdirname)
static

Definition at line 3275 of file fd.c.

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

Referenced by RemovePgTempFiles().

3276 {
3277  DIR *ts_dir;
3278  struct dirent *de;
3279  char dbspace_path[MAXPGPATH * 2];
3280 
3281  ts_dir = AllocateDir(tsdirname);
3282 
3283  while ((de = ReadDirExtended(ts_dir, tsdirname, LOG)) != NULL)
3284  {
3285  /*
3286  * We're only interested in the per-database directories, which have
3287  * numeric names. Note that this code will also (properly) ignore "."
3288  * and "..".
3289  */
3290  if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
3291  continue;
3292 
3293  snprintf(dbspace_path, sizeof(dbspace_path), "%s/%s",
3294  tsdirname, de->d_name);
3295  RemovePgTempRelationFilesInDbspace(dbspace_path);
3296  }
3297 
3298  FreeDir(ts_dir);
3299 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2801
static void RemovePgTempRelationFilesInDbspace(const char *dbspacedirname)
Definition: fd.c:3303
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2720
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217
int FreeDir(DIR *dir)
Definition: fd.c:2838

◆ RemovePgTempRelationFilesInDbspace()

static void RemovePgTempRelationFilesInDbspace ( const char *  dbspacedirname)
static

Definition at line 3303 of file fd.c.

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

Referenced by RemovePgTempRelationFiles().

3304 {
3305  DIR *dbspace_dir;
3306  struct dirent *de;
3307  char rm_path[MAXPGPATH * 2];
3308 
3309  dbspace_dir = AllocateDir(dbspacedirname);
3310 
3311  while ((de = ReadDirExtended(dbspace_dir, dbspacedirname, LOG)) != NULL)
3312  {
3313  if (!looks_like_temp_rel_name(de->d_name))
3314  continue;
3315 
3316  snprintf(rm_path, sizeof(rm_path), "%s/%s",
3317  dbspacedirname, de->d_name);
3318 
3319  if (unlink(rm_path) < 0)
3320  ereport(LOG,
3322  errmsg("could not remove file \"%s\": %m",
3323  rm_path)));
3324  }
3325 
3326  FreeDir(dbspace_dir);
3327 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2801
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:721
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2720
#define ereport(elevel,...)
Definition: elog.h:157
bool looks_like_temp_rel_name(const char *name)
Definition: fd.c:3331
int errmsg(const char *fmt,...)
Definition: elog.c:909
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217
int FreeDir(DIR *dir)
Definition: fd.c:2838

◆ ReportTemporaryFileUsage()

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

Definition at line 1517 of file fd.c.

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

Referenced by FileClose(), and PathNameDeleteTemporaryFile().

1518 {
1519  pgstat_report_tempfile(size);
1520 
1521  if (log_temp_files >= 0)
1522  {
1523  if ((size / 1024) >= log_temp_files)
1524  ereport(LOG,
1525  (errmsg("temporary file: path \"%s\", size %lu",
1526  path, (unsigned long) size)));
1527  }
1528 }
int log_temp_files
Definition: guc.c:602
void pgstat_report_tempfile(size_t filesize)
Definition: pgstat.c:1737
#define LOG
Definition: elog.h:26
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ reserveAllocatedDesc()

static bool reserveAllocatedDesc ( void  )
static

Definition at line 2384 of file fd.c.

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

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

2385 {
2386  AllocateDesc *newDescs;
2387  int newMax;
2388 
2389  /* Quick out if array already has a free slot. */
2391  return true;
2392 
2393  /*
2394  * If the array hasn't yet been created in the current process, initialize
2395  * it with FD_MINFREE / 3 elements. In many scenarios this is as many as
2396  * we will ever need, anyway. We don't want to look at max_safe_fds
2397  * immediately because set_max_safe_fds() may not have run yet.
2398  */
2399  if (allocatedDescs == NULL)
2400  {
2401  newMax = FD_MINFREE / 3;
2402  newDescs = (AllocateDesc *) malloc(newMax * sizeof(AllocateDesc));
2403  /* Out of memory already? Treat as fatal error. */
2404  if (newDescs == NULL)
2405  ereport(ERROR,
2406  (errcode(ERRCODE_OUT_OF_MEMORY),
2407  errmsg("out of memory")));
2408  allocatedDescs = newDescs;
2409  maxAllocatedDescs = newMax;
2410  return true;
2411  }
2412 
2413  /*
2414  * Consider enlarging the array beyond the initial allocation used above.
2415  * By the time this happens, max_safe_fds should be known accurately.
2416  *
2417  * We mustn't let allocated descriptors hog all the available FDs, and in
2418  * practice we'd better leave a reasonable number of FDs for VFD use. So
2419  * set the maximum to max_safe_fds / 3. (This should certainly be at
2420  * least as large as the initial size, FD_MINFREE / 3, so we aren't
2421  * tightening the restriction here.) Recall that "external" FDs are
2422  * allowed to consume another third of max_safe_fds.
2423  */
2424  newMax = max_safe_fds / 3;
2425  if (newMax > maxAllocatedDescs)
2426  {
2427  newDescs = (AllocateDesc *) realloc(allocatedDescs,
2428  newMax * sizeof(AllocateDesc));
2429  /* Treat out-of-memory as a non-fatal error. */
2430  if (newDescs == NULL)
2431  return false;
2432  allocatedDescs = newDescs;
2433  maxAllocatedDescs = newMax;
2434  return true;
2435  }
2436 
2437  /* Can't enlarge allocatedDescs[] any more. */
2438  return false;
2439 }
static AllocateDesc * allocatedDescs
Definition: fd.c:265
int max_safe_fds
Definition: fd.c:158
int errcode(int sqlerrcode)
Definition: elog.c:698
#define malloc(a)
Definition: header.h:50
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
#define FD_MINFREE
Definition: fd.c:137
#define realloc(a, b)
Definition: header.h:60
int errmsg(const char *fmt,...)
Definition: elog.c:909
static int maxAllocatedDescs
Definition: fd.c:264
static int numAllocatedDescs
Definition: fd.c:263

◆ ReserveExternalFD()

void ReserveExternalFD ( void  )

Definition at line 1210 of file fd.c.

References numExternalFDs, and ReleaseLruFiles().

Referenced by AcquireExternalFD(), BackendInitialize(), dsm_impl_op(), InitializeLatchSupport(), InitPostmasterDeathWatchHandle(), pgstat_init(), PostmasterMarkPIDForWorkerNotify(), and XLogWrite().

1211 {
1212  /*
1213  * Release VFDs if needed to stay safe. Because we do this before
1214  * incrementing numExternalFDs, the final state will be as desired, i.e.,
1215  * nfile + numAllocatedDescs + numExternalFDs <= max_safe_fds.
1216  */
1217  ReleaseLruFiles();
1218 
1219  numExternalFDs++;
1220 }
static int numExternalFDs
Definition: fd.c:270
static void ReleaseLruFiles(void)
Definition: fd.c:1393

◆ set_max_safe_fds()

void set_max_safe_fds ( void  )

Definition at line 1026 of file fd.c.

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

Referenced by PostmasterMain().

1027 {
1028  int usable_fds;
1029  int already_open;
1030 
1031  /*----------
1032  * We want to set max_safe_fds to
1033  * MIN(usable_fds, max_files_per_process - already_open)
1034  * less the slop factor for files that are opened without consulting
1035  * fd.c. This ensures that we won't exceed either max_files_per_process
1036  * or the experimentally-determined EMFILE limit.
1037  *----------
1038  */
1040  &usable_fds, &already_open);
1041 
1042  max_safe_fds = Min(usable_fds, max_files_per_process - already_open);
1043 
1044  /*
1045  * Take off the FDs reserved for system() etc.
1046  */
1048 
1049  /*
1050  * Make sure we still have enough to get by.
1051  */
1052  if (max_safe_fds < FD_MINFREE)
1053  ereport(FATAL,
1054  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
1055  errmsg("insufficient file descriptors available to start server process"),
1056  errdetail("System allows %d, we need at least %d.",
1059 
1060  elog(DEBUG2, "max_safe_fds = %d, usable_fds = %d, already_open = %d",
1061  max_safe_fds, usable_fds, already_open);
1062 }
static void count_usable_fds(int max_to_probe, int *usable_fds, int *already_open)
Definition: fd.c:942
#define NUM_RESERVED_FDS
Definition: fd.c:128
int max_safe_fds
Definition: fd.c:158
#define Min(x, y)
Definition: c.h:986
int errcode(int sqlerrcode)
Definition: elog.c:698
#define FATAL
Definition: elog.h:49
#define DEBUG2
Definition: elog.h:24
int errdetail(const char *fmt,...)
Definition: elog.c:1042
int max_files_per_process
Definition: fd.c:145
#define ereport(elevel,...)
Definition: elog.h:157
#define FD_MINFREE
Definition: fd.c:137
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232

◆ SetTempTablespaces()

void SetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2926 of file fd.c.

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

Referenced by assign_temp_tablespaces(), and PrepareTempTablespaces().

2927 {
2928  Assert(numSpaces >= 0);
2929  tempTableSpaces = tableSpaces;
2930  numTempTableSpaces = numSpaces;
2931 
2932  /*
2933  * Select a random starting point in the list. This is to minimize
2934  * conflicts between backends that are most likely sharing the same list
2935  * of temp tablespaces. Note that if we create multiple temp files in the
2936  * same transaction, we'll advance circularly through the list --- this
2937  * ensures that large temporary sort files are nicely spread across all
2938  * available tablespaces.
2939  */
2940  if (numSpaces > 1)
2941  nextTempTableSpace = random() % numSpaces;
2942  else
2943  nextTempTableSpace = 0;
2944 }
long random(void)
Definition: random.c:22
static int numTempTableSpaces
Definition: fd.c:285
static int nextTempTableSpace
Definition: fd.c:286
#define Assert(condition)
Definition: c.h:804
static Oid * tempTableSpaces
Definition: fd.c:284

◆ SyncDataDirectory()

void SyncDataDirectory ( void  )

Definition at line 3423 of file fd.c.

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

Referenced by StartupXLOG().

3424 {
3425  bool xlog_is_symlink;
3426 
3427  /* We can skip this whole thing if fsync is disabled. */
3428  if (!enableFsync)
3429  return;
3430 
3431  /*
3432  * If pg_wal is a symlink, we'll need to recurse into it separately,
3433  * because the first walkdir below will ignore it.
3434  */
3435  xlog_is_symlink = false;
3436 
3437 #ifndef WIN32
3438  {
3439  struct stat st;
3440 
3441  if (lstat("pg_wal", &st) < 0)
3442  ereport(LOG,
3444  errmsg("could not stat file \"%s\": %m",
3445  "pg_wal")));
3446  else if (S_ISLNK(st.st_mode))
3447  xlog_is_symlink = true;
3448  }
3449 #else
3450  if (pgwin32_is_junction("pg_wal"))
3451  xlog_is_symlink = true;
3452 #endif
3453 
3454 #ifdef HAVE_SYNCFS
3456  {
3457  DIR *dir;
3458  struct dirent *de;
3459 
3460  /*
3461  * On Linux, we don't have to open every single file one by one. We
3462  * can use syncfs() to sync whole filesystems. We only expect
3463  * filesystem boundaries to exist where we tolerate symlinks, namely
3464  * pg_wal and the tablespaces, so we call syncfs() for each of those
3465  * directories.
3466  */
3467 
3468  /* Sync the top level pgdata directory. */
3469  do_syncfs(".");
3470  /* If any tablespaces are configured, sync each of those. */
3471  dir = AllocateDir("pg_tblspc");
3472  while ((de = ReadDirExtended(dir, "pg_tblspc", LOG)))
3473  {
3474  char path[MAXPGPATH];
3475 
3476  if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
3477  continue;
3478 
3479  snprintf(path, MAXPGPATH, "pg_tblspc/%s", de->d_name);
3480  do_syncfs(path);
3481  }
3482  FreeDir(dir);
3483  /* If pg_wal is a symlink, process that too. */
3484  if (xlog_is_symlink)
3485  do_syncfs("pg_wal");
3486  return;
3487  }
3488 #endif /* !HAVE_SYNCFS */
3489 
3490  /*
3491  * If possible, hint to the kernel that we're soon going to fsync the data
3492  * directory and its contents. Errors in this step are even less
3493  * interesting than normal, so log them only at DEBUG1.
3494  */
3495 #ifdef PG_FLUSH_DATA_WORKS
3496  walkdir(".", pre_sync_fname, false, DEBUG1);
3497  if (xlog_is_symlink)
3498  walkdir("pg_wal", pre_sync_fname, false, DEBUG1);
3499  walkdir("pg_tblspc", pre_sync_fname, true, DEBUG1);
3500 #endif
3501 
3502  /*
3503  * Now we do the fsync()s in the same order.
3504  *
3505  * The main call ignores symlinks, so in addition to specially processing
3506  * pg_wal if it's a symlink, pg_tblspc has to be visited separately with
3507  * process_symlinks = true. Note that if there are any plain directories
3508  * in pg_tblspc, they'll get fsync'd twice. That's not an expected case
3509  * so we don't worry about optimizing it.
3510  */
3511  walkdir(".", datadir_fsync_fname, false, LOG);
3512  if (xlog_is_symlink)
3513  walkdir("pg_wal", datadir_fsync_fname, false, LOG);
3514  walkdir("pg_tblspc", datadir_fsync_fname, true, LOG);
3515 }
#define DEBUG1
Definition: elog.h:25
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
Definition: fd.c:3533
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2801
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
int recovery_init_sync_method
Definition: fd.c:164
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:721
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2720
static void datadir_fsync_fname(const char *fname, bool isdir, int elevel)
Definition: fd.c:3631
#define ereport(elevel,...)
Definition: elog.h:157
#define lstat(path, sb)
Definition: win32_port.h:284
bool enableFsync
Definition: globals.c:122
int errmsg(const char *fmt,...)
Definition: elog.c:909
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217
int FreeDir(DIR *dir)
Definition: fd.c:2838
bool pgwin32_is_junction(const char *path)

◆ TempTablespacePath()

void TempTablespacePath ( char *  path,
Oid  tablespace 
)

Definition at line 1760 of file fd.c.

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

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

1761 {
1762  /*
1763  * Identify the tempfile directory for this tablespace.
1764  *
1765  * If someone tries to specify pg_global, use pg_default instead.
1766  */
1767  if (tablespace == InvalidOid ||
1768  tablespace == DEFAULTTABLESPACE_OID ||
1769  tablespace == GLOBALTABLESPACE_OID)
1770  snprintf(path, MAXPGPATH, "base/%s", PG_TEMP_FILES_DIR);
1771  else
1772  {
1773  /* All other tablespaces are accessed via symlinks */
1774  snprintf(path, MAXPGPATH, "pg_tblspc/%u/%s/%s",
1777  }
1778 }
#define PG_TEMP_FILES_DIR
Definition: pg_checksums.c:62
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
char * tablespace
Definition: pgbench.c:226
#define InvalidOid
Definition: postgres_ext.h:36
#define snprintf
Definition: port.h:217

◆ TempTablespacesAreSet()

bool TempTablespacesAreSet ( void  )

Definition at line 2954 of file fd.c.

References numTempTableSpaces.

Referenced by GetTempTablespaces(), and PrepareTempTablespaces().

2955 {
2956  return (numTempTableSpaces >= 0);
2957 }
static int numTempTableSpaces
Definition: fd.c:285

◆ unlink_if_exists_fname()

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

Definition at line 3641 of file fd.c.

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

Referenced by PathNameDeleteTemporaryDir().

3642 {
3643  if (isdir)
3644  {
3645  if (rmdir(fname) != 0 && errno != ENOENT)
3646  ereport(elevel,
3648  errmsg("could not remove directory \"%s\": %m", fname)));
3649  }
3650  else
3651  {
3652  /* Use PathNameDeleteTemporaryFile to report filesize */
3653  PathNameDeleteTemporaryFile(fname, false);
3654  }
3655 }
bool PathNameDeleteTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1913
int errcode_for_file_access(void)
Definition: elog.c:721
static int elevel
Definition: vacuumlazy.c:401
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

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

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

Referenced by PathNameDeleteTemporaryDir(), and SyncDataDirectory().

3537 {
3538  DIR *dir;
3539  struct dirent *de;
3540 
3541  dir = AllocateDir(path);
3542 
3543  while ((de = ReadDirExtended(dir, path, elevel)) != NULL)
3544  {
3545  char subpath[MAXPGPATH * 2];
3546 
3548 
3549  if (strcmp(de->d_name, ".") == 0 ||
3550  strcmp(de->d_name, "..") == 0)
3551  continue;
3552 
3553  snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name);
3554 
3555  switch (get_dirent_type(subpath, de, process_symlinks, elevel))
3556  {
3557  case PGFILETYPE_REG:
3558  (*action) (subpath, false, elevel);
3559  break;
3560  case PGFILETYPE_DIR:
3561  walkdir(subpath, action, false, elevel);
3562  break;
3563  default:
3564 
3565  /*
3566  * Errors are already reported directly by get_dirent_type(),
3567  * and any remaining symlinks and unknown file types are
3568  * ignored.
3569  */
3570  break;
3571  }
3572  }
3573 
3574  FreeDir(dir); /* we ignore any error here */
3575 
3576  /*
3577  * It's important to fsync the destination directory itself as individual
3578  * file fsyncs don't guarantee that the directory entry for the file is
3579  * synced. However, skip this if AllocateDir failed; the action function
3580  * might not be robust against that.
3581  */
3582  if (dir)
3583  (*action) (path, true, elevel);
3584 }
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
Definition: fd.c:3533
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2801
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2720
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:410
static int elevel
Definition: vacuumlazy.c:401
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217
int FreeDir(DIR *dir)
Definition: fd.c:2838
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:241

Variable Documentation

◆ allocatedDescs

AllocateDesc* allocatedDescs = NULL
static

Definition at line 265 of file fd.c.

◆ data_sync_retry

bool data_sync_retry = false

Definition at line 161 of file fd.c.

Referenced by data_sync_elevel().

◆ have_xact_temporary_files

bool have_xact_temporary_files = false
static

Definition at line 224 of file fd.c.

Referenced by CleanupTempFiles(), and RegisterTemporaryFile().

◆ max_files_per_process

int max_files_per_process = 1000

Definition at line 145 of file fd.c.

Referenced by set_max_safe_fds().

◆ max_safe_fds

◆ maxAllocatedDescs

int maxAllocatedDescs = 0
static

◆ nextTempTableSpace

int nextTempTableSpace = 0
static

Definition at line 286 of file fd.c.

Referenced by GetNextTempTableSpace(), and SetTempTablespaces().

◆ nfile

int nfile = 0
static

◆ numAllocatedDescs

◆ numExternalFDs

int numExternalFDs = 0
static

Definition at line 270 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 164 of file fd.c.

Referenced by SyncDataDirectory().

◆ SizeVfdCache

Size SizeVfdCache = 0
static

◆ tempFileCounter

long tempFileCounter = 0
static

Definition at line 276 of file fd.c.

Referenced by OpenTemporaryFileInTablespace().

◆ temporary_files_size

uint64 temporary_files_size = 0
static

Definition at line 232 of file fd.c.

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

◆ tempTableSpaces

Oid* tempTableSpaces = NULL
static

◆ VfdCache

Vfd* VfdCache
static

Definition at line 212 of file fd.c.