PostgreSQL Source Code  git master
fd.c File Reference
#include "postgres.h"
#include <dirent.h>
#include <sys/file.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/pg_tablespace.h"
#include "common/file_perm.h"
#include "common/file_utils.h"
#include "common/pg_prng.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "portability/mem.h"
#include "postmaster/startup.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "utils/guc.h"
#include "utils/guc_hooks.h"
#include "utils/resowner_private.h"
#include "utils/varlena.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)
 
static int pg_ftruncate (int fd, off_t length)
 
int pg_truncate (const char *path, off_t length)
 
void fsync_fname (const char *fname, bool isdir)
 
int durable_rename (const char *oldfile, const char *newfile, int elevel)
 
int durable_unlink (const char *fname, int elevel)
 
void InitFileAccess (void)
 
void InitTemporaryFileAccess (void)
 
static void count_usable_fds (int max_to_probe, int *usable_fds, int *already_open)
 
void set_max_safe_fds (void)
 
int BasicOpenFile (const char *fileName, int fileFlags)
 
int BasicOpenFilePerm (const char *fileName, int fileFlags, mode_t fileMode)
 
bool AcquireExternalFD (void)
 
void ReserveExternalFD (void)
 
void ReleaseExternalFD (void)
 
static void ReportTemporaryFileUsage (const char *path, off_t size)
 
static void RegisterTemporaryFile (File file)
 
File PathNameOpenFile (const char *fileName, int fileFlags)
 
File PathNameOpenFilePerm (const char *fileName, int fileFlags, mode_t fileMode)
 
void PathNameCreateTemporaryDir (const char *basedir, const char *directory)
 
void PathNameDeleteTemporaryDir (const char *dirname)
 
File OpenTemporaryFile (bool interXact)
 
void TempTablespacePath (char *path, Oid tablespace)
 
File PathNameCreateTemporaryFile (const char *path, bool error_on_failure)
 
File PathNameOpenTemporaryFile (const char *path, int mode)
 
bool PathNameDeleteTemporaryFile (const char *path, bool error_on_failure)
 
void FileClose (File file)
 
int FilePrefetch (File file, off_t offset, off_t amount, uint32 wait_event_info)
 
void FileWriteback (File file, off_t offset, off_t nbytes, uint32 wait_event_info)
 
int FileRead (File file, void *buffer, size_t amount, off_t offset, uint32 wait_event_info)
 
int FileWrite (File file, const void *buffer, size_t amount, off_t offset, uint32 wait_event_info)
 
int FileSync (File file, uint32 wait_event_info)
 
int FileZero (File file, off_t offset, off_t amount, uint32 wait_event_info)
 
int FileFallocate (File file, off_t offset, off_t amount, 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)
 
bool check_debug_io_direct (char **newval, void **extra, GucSource source)
 
void assign_debug_io_direct (const char *newval, void *extra)
 

Variables

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

Macro Definition Documentation

◆ DO_DB

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

Definition at line 180 of file fd.c.

◆ FD_CLOSE_AT_EOXACT

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

Definition at line 193 of file fd.c.

◆ FD_DELETE_AT_CLOSE

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

Definition at line 192 of file fd.c.

◆ FD_MINFREE

#define FD_MINFREE   48

Definition at line 138 of file fd.c.

◆ FD_TEMP_FILE_LIMIT

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

Definition at line 194 of file fd.c.

◆ FileIsNotOpen

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

Definition at line 189 of file fd.c.

◆ FileIsValid

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

Definition at line 186 of file fd.c.

◆ NUM_RESERVED_FDS

#define NUM_RESERVED_FDS   10

Definition at line 129 of file fd.c.

◆ VFD_CLOSED

#define VFD_CLOSED   (-1)

Definition at line 184 of file fd.c.

Typedef Documentation

◆ Vfd

typedef struct vfd Vfd

Enumeration Type Documentation

◆ AllocateDescKind

Enumerator
AllocateDescFile 
AllocateDescPipe 
AllocateDescDir 
AllocateDescRawFD 

Definition at line 247 of file fd.c.

248 {
AllocateDescKind
Definition: fd.c:248
@ AllocateDescDir
Definition: fd.c:251
@ AllocateDescPipe
Definition: fd.c:250
@ AllocateDescFile
Definition: fd.c:249
@ AllocateDescRawFD
Definition: fd.c:252

Function Documentation

◆ AcquireExternalFD()

bool AcquireExternalFD ( void  )

Definition at line 1138 of file fd.c.

1139 {
1140  /*
1141  * We don't want more than max_safe_fds / 3 FDs to be consumed for
1142  * "external" FDs.
1143  */
1144  if (numExternalFDs < max_safe_fds / 3)
1145  {
1147  return true;
1148  }
1149  errno = EMFILE;
1150  return false;
1151 }
int max_safe_fds
Definition: fd.c:159
void ReserveExternalFD(void)
Definition: fd.c:1173
static int numExternalFDs
Definition: fd.c:274

References max_safe_fds, numExternalFDs, and ReserveExternalFD().

Referenced by CreateWaitEventSet(), and libpqsrv_connect_prepare().

◆ AllocateDir()

DIR* AllocateDir ( const char *  dirname)

Definition at line 2788 of file fd.c.

2789 {
2790  DIR *dir;
2791 
2792  DO_DB(elog(LOG, "AllocateDir: Allocated %d (%s)",
2793  numAllocatedDescs, dirname));
2794 
2795  /* Can we allocate another non-virtual FD? */
2796  if (!reserveAllocatedDesc())
2797  ereport(ERROR,
2798  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2799  errmsg("exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"",
2800  maxAllocatedDescs, dirname)));
2801 
2802  /* Close excess kernel FDs. */
2803  ReleaseLruFiles();
2804 
2805 TryAgain:
2806  if ((dir = opendir(dirname)) != NULL)
2807  {
2809 
2810  desc->kind = AllocateDescDir;
2811  desc->desc.dir = dir;
2814  return desc->desc.dir;
2815  }
2816 
2817  if (errno == EMFILE || errno == ENFILE)
2818  {
2819  int save_errno = errno;
2820 
2821  ereport(LOG,
2822  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2823  errmsg("out of file descriptors: %m; release and retry")));
2824  errno = 0;
2825  if (ReleaseLruFile())
2826  goto TryAgain;
2827  errno = save_errno;
2828  }
2829 
2830  return NULL;
2831 }
DIR * opendir(const char *)
Definition: dirent.c:33
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define LOG
Definition: elog.h:31
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
static bool ReleaseLruFile(void)
Definition: fd.c:1334
static int maxAllocatedDescs
Definition: fd.c:268
static int numAllocatedDescs
Definition: fd.c:267
#define DO_DB(A)
Definition: fd.c:180
static AllocateDesc * allocatedDescs
Definition: fd.c:269
static bool reserveAllocatedDesc(void)
Definition: fd.c:2453
static void ReleaseLruFiles(void)
Definition: fd.c:1356
SubTransactionId create_subid
Definition: fd.c:258
DIR * dir
Definition: fd.c:262
union AllocateDesc::@19 desc
AllocateDescKind kind
Definition: fd.c:257
Definition: dirent.c:26
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:780

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

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

◆ AllocateFile()

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

Definition at line 2528 of file fd.c.

2529 {
2530  FILE *file;
2531 
2532  DO_DB(elog(LOG, "AllocateFile: Allocated %d (%s)",
2534 
2535  /* Can we allocate another non-virtual FD? */
2536  if (!reserveAllocatedDesc())
2537  ereport(ERROR,
2538  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2539  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2540  maxAllocatedDescs, name)));
2541 
2542  /* Close excess kernel FDs. */
2543  ReleaseLruFiles();
2544 
2545 TryAgain:
2546  if ((file = fopen(name, mode)) != NULL)
2547  {
2549 
2550  desc->kind = AllocateDescFile;
2551  desc->desc.file = file;
2554  return desc->desc.file;
2555  }
2556 
2557  if (errno == EMFILE || errno == ENFILE)
2558  {
2559  int save_errno = errno;
2560 
2561  ereport(LOG,
2562  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2563  errmsg("out of file descriptors: %m; release and retry")));
2564  errno = 0;
2565  if (ReleaseLruFile())
2566  goto TryAgain;
2567  errno = save_errno;
2568  }
2569 
2570  return NULL;
2571 }
static PgChecksumMode mode
Definition: pg_checksums.c:56
FILE * file
Definition: fd.c:261
const char * name

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

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

◆ AllocateVfd()

static File AllocateVfd ( void  )
static

Definition at line 1366 of file fd.c.

1367 {
1368  Index i;
1369  File file;
1370 
1371  DO_DB(elog(LOG, "AllocateVfd. Size %zu", SizeVfdCache));
1372 
1373  Assert(SizeVfdCache > 0); /* InitFileAccess not called? */
1374 
1375  if (VfdCache[0].nextFree == 0)
1376  {
1377  /*
1378  * The free list is empty so it is time to increase the size of the
1379  * array. We choose to double it each time this happens. However,
1380  * there's not much point in starting *real* small.
1381  */
1382  Size newCacheSize = SizeVfdCache * 2;
1383  Vfd *newVfdCache;
1384 
1385  if (newCacheSize < 32)
1386  newCacheSize = 32;
1387 
1388  /*
1389  * Be careful not to clobber VfdCache ptr if realloc fails.
1390  */
1391  newVfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
1392  if (newVfdCache == NULL)
1393  ereport(ERROR,
1394  (errcode(ERRCODE_OUT_OF_MEMORY),
1395  errmsg("out of memory")));
1396  VfdCache = newVfdCache;
1397 
1398  /*
1399  * Initialize the new entries and link them into the free list.
1400  */
1401  for (i = SizeVfdCache; i < newCacheSize; i++)
1402  {
1403  MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
1404  VfdCache[i].nextFree = i + 1;
1405  VfdCache[i].fd = VFD_CLOSED;
1406  }
1407  VfdCache[newCacheSize - 1].nextFree = 0;
1409 
1410  /*
1411  * Record the new size
1412  */
1413  SizeVfdCache = newCacheSize;
1414  }
1415 
1416  file = VfdCache[0].nextFree;
1417 
1418  VfdCache[0].nextFree = VfdCache[file].nextFree;
1419 
1420  return file;
1421 }
unsigned int Index
Definition: c.h:603
#define MemSet(start, val, len)
Definition: c.h:1009
size_t Size
Definition: c.h:594
static Size SizeVfdCache
Definition: fd.c:217
#define VFD_CLOSED
Definition: fd.c:184
static Vfd * VfdCache
Definition: fd.c:216
int File
Definition: fd.h:49
#define realloc(a, b)
Definition: header.h:60
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
Definition: fd.c:197
int fd
Definition: fd.c:198
File nextFree
Definition: fd.c:201

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

Referenced by PathNameOpenFilePerm().

◆ assign_debug_io_direct()

void assign_debug_io_direct ( const char *  newval,
void *  extra 
)

Definition at line 3969 of file fd.c.

3970 {
3971  int *flags = (int *) extra;
3972 
3973  io_direct_flags = *flags;
3974 }
int io_direct_flags
Definition: fd.c:168

References io_direct_flags.

◆ AtEOSubXact_Files()

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

Definition at line 3077 of file fd.c.

3079 {
3080  Index i;
3081 
3082  for (i = 0; i < numAllocatedDescs; i++)
3083  {
3084  if (allocatedDescs[i].create_subid == mySubid)
3085  {
3086  if (isCommit)
3087  allocatedDescs[i].create_subid = parentSubid;
3088  else
3089  {
3090  /* have to recheck the item after FreeDesc (ugly) */
3091  FreeDesc(&allocatedDescs[i--]);
3092  }
3093  }
3094  }
3095 }
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2687

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

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

◆ AtEOXact_Files()

void AtEOXact_Files ( bool  isCommit)

Definition at line 3110 of file fd.c.

3111 {
3112  CleanupTempFiles(isCommit, false);
3113  tempTableSpaces = NULL;
3114  numTempTableSpaces = -1;
3115 }
static int numTempTableSpaces
Definition: fd.c:289
static Oid * tempTableSpaces
Definition: fd.c:288
static void CleanupTempFiles(bool isCommit, bool isProcExit)
Definition: fd.c:3147

References CleanupTempFiles(), numTempTableSpaces, and tempTableSpaces.

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

◆ BasicOpenFile()

int BasicOpenFile ( const char *  fileName,
int  fileFlags 
)

Definition at line 1039 of file fd.c.

1040 {
1041  return BasicOpenFilePerm(fileName, fileFlags, pg_file_create_mode);
1042 }
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1061
int pg_file_create_mode
Definition: file_perm.c:19

References BasicOpenFilePerm(), and pg_file_create_mode.

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

◆ BasicOpenFilePerm()

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

Definition at line 1061 of file fd.c.

1062 {
1063  int fd;
1064 
1065 tryAgain:
1066 #ifdef PG_O_DIRECT_USE_F_NOCACHE
1067 
1068  /*
1069  * The value we defined to stand in for O_DIRECT when simulating it with
1070  * F_NOCACHE had better not collide with any of the standard flags.
1071  */
1073  (O_APPEND |
1074  O_CLOEXEC |
1075  O_CREAT |
1076  O_DSYNC |
1077  O_EXCL |
1078  O_RDWR |
1079  O_RDONLY |
1080  O_SYNC |
1081  O_TRUNC |
1082  O_WRONLY)) == 0,
1083  "PG_O_DIRECT value collides with standard flag");
1084  fd = open(fileName, fileFlags & ~PG_O_DIRECT, fileMode);
1085 #else
1086  fd = open(fileName, fileFlags, fileMode);
1087 #endif
1088 
1089  if (fd >= 0)
1090  {
1091 #ifdef PG_O_DIRECT_USE_F_NOCACHE
1092  if (fileFlags & PG_O_DIRECT)
1093  {
1094  if (fcntl(fd, F_NOCACHE, 1) < 0)
1095  {
1096  int save_errno = errno;
1097 
1098  close(fd);
1099  errno = save_errno;
1100  return -1;
1101  }
1102  }
1103 #endif
1104 
1105  return fd; /* success! */
1106  }
1107 
1108  if (errno == EMFILE || errno == ENFILE)
1109  {
1110  int save_errno = errno;
1111 
1112  ereport(LOG,
1113  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
1114  errmsg("out of file descriptors: %m; release and retry")));
1115  errno = 0;
1116  if (ReleaseLruFile())
1117  goto tryAgain;
1118  errno = save_errno;
1119  }
1120 
1121  return -1; /* failure */
1122 }
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:927
#define PG_O_DIRECT
Definition: fd.h:95
#define close(a)
Definition: win32.h:12
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define O_CLOEXEC
Definition: win32_port.h:359
#define O_DSYNC
Definition: win32_port.h:352

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

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

◆ BeforeShmemExit_Files()

static void BeforeShmemExit_Files ( int  code,
Datum  arg 
)
static

Definition at line 3124 of file fd.c.

3125 {
3126  CleanupTempFiles(false, true);
3127 
3128  /* prevent further temp files from being created */
3129 #ifdef USE_ASSERT_CHECKING
3130  temporary_files_allowed = false;
3131 #endif
3132 }

References CleanupTempFiles().

Referenced by InitTemporaryFileAccess().

◆ check_debug_io_direct()

bool check_debug_io_direct ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 3887 of file fd.c.

3888 {
3889  bool result = true;
3890  int flags;
3891 
3892 #if PG_O_DIRECT == 0
3893  if (strcmp(*newval, "") != 0)
3894  {
3895  GUC_check_errdetail("debug_io_direct is not supported on this platform.");
3896  result = false;
3897  }
3898  flags = 0;
3899 #else
3900  List *elemlist;
3901  ListCell *l;
3902  char *rawstring;
3903 
3904  /* Need a modifiable copy of string */
3905  rawstring = pstrdup(*newval);
3906 
3907  if (!SplitGUCList(rawstring, ',', &elemlist))
3908  {
3909  GUC_check_errdetail("invalid list syntax in parameter \"%s\"",
3910  "debug_io_direct");
3911  pfree(rawstring);
3912  list_free(elemlist);
3913  return false;
3914  }
3915 
3916  flags = 0;
3917  foreach(l, elemlist)
3918  {
3919  char *item = (char *) lfirst(l);
3920 
3921  if (pg_strcasecmp(item, "data") == 0)
3922  flags |= IO_DIRECT_DATA;
3923  else if (pg_strcasecmp(item, "wal") == 0)
3924  flags |= IO_DIRECT_WAL;
3925  else if (pg_strcasecmp(item, "wal_init") == 0)
3926  flags |= IO_DIRECT_WAL_INIT;
3927  else
3928  {
3929  GUC_check_errdetail("invalid option \"%s\"", item);
3930  result = false;
3931  break;
3932  }
3933  }
3934 
3935  /*
3936  * It's possible to configure block sizes smaller than our assumed I/O
3937  * alignment size, which could result in invalid I/O requests.
3938  */
3939 #if XLOG_BLCKSZ < PG_IO_ALIGN_SIZE
3940  if (result && (flags & (IO_DIRECT_WAL | IO_DIRECT_WAL_INIT)))
3941  {
3942  GUC_check_errdetail("debug_io_direct is not supported for WAL because XLOG_BLCKSZ is too small");
3943  result = false;
3944  }
3945 #endif
3946 #if BLCKSZ < PG_IO_ALIGN_SIZE
3947  if (result && (flags & IO_DIRECT_DATA))
3948  {
3949  GUC_check_errdetail("debug_io_direct is not supported for data because BLCKSZ is too small");
3950  result = false;
3951  }
3952 #endif
3953 
3954  pfree(rawstring);
3955  list_free(elemlist);
3956 #endif
3957 
3958  if (!result)
3959  return result;
3960 
3961  /* Save the flags in *extra, for use by assign_debug_io_direct */
3962  *extra = guc_malloc(ERROR, sizeof(int));
3963  *((int *) *extra) = flags;
3964 
3965  return result;
3966 }
#define IO_DIRECT_WAL
Definition: fd.h:53
#define IO_DIRECT_DATA
Definition: fd.h:52
#define IO_DIRECT_WAL_INIT
Definition: fd.h:54
void * guc_malloc(int elevel, size_t size)
Definition: guc.c:631
#define newval
#define GUC_check_errdetail
Definition: guc.h:436
void list_free(List *list)
Definition: list.c:1545
char * pstrdup(const char *in)
Definition: mcxt.c:1644
void pfree(void *pointer)
Definition: mcxt.c:1456
#define lfirst(lc)
Definition: pg_list.h:172
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
Definition: pg_list.h:54
bool SplitGUCList(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3702

References ERROR, GUC_check_errdetail, guc_malloc(), IO_DIRECT_DATA, IO_DIRECT_WAL, IO_DIRECT_WAL_INIT, lfirst, list_free(), newval, pfree(), pg_strcasecmp(), pstrdup(), and SplitGUCList().

◆ CleanupTempFiles()

static void CleanupTempFiles ( bool  isCommit,
bool  isProcExit 
)
static

Definition at line 3147 of file fd.c.

3148 {
3149  Index i;
3150 
3151  /*
3152  * Careful here: at proc_exit we need extra cleanup, not just
3153  * xact_temporary files.
3154  */
3155  if (isProcExit || have_xact_temporary_files)
3156  {
3157  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
3158  for (i = 1; i < SizeVfdCache; i++)
3159  {
3160  unsigned short fdstate = VfdCache[i].fdstate;
3161 
3162  if (((fdstate & FD_DELETE_AT_CLOSE) || (fdstate & FD_CLOSE_AT_EOXACT)) &&
3163  VfdCache[i].fileName != NULL)
3164  {
3165  /*
3166  * If we're in the process of exiting a backend process, close
3167  * all temporary files. Otherwise, only close temporary files
3168  * local to the current transaction. They should be closed by
3169  * the ResourceOwner mechanism already, so this is just a
3170  * debugging cross-check.
3171  */
3172  if (isProcExit)
3173  FileClose(i);
3174  else if (fdstate & FD_CLOSE_AT_EOXACT)
3175  {
3176  elog(WARNING,
3177  "temporary file %s not closed at end-of-transaction",
3178  VfdCache[i].fileName);
3179  FileClose(i);
3180  }
3181  }
3182  }
3183 
3184  have_xact_temporary_files = false;
3185  }
3186 
3187  /* Complain if any allocated files remain open at commit. */
3188  if (isCommit && numAllocatedDescs > 0)
3189  elog(WARNING, "%d temporary files and directories not closed at end-of-transaction",
3191 
3192  /* Clean up "allocated" stdio files, dirs and fds. */
3193  while (numAllocatedDescs > 0)
3194  FreeDesc(&allocatedDescs[0]);
3195 }
#define WARNING
Definition: elog.h:36
#define FD_DELETE_AT_CLOSE
Definition: fd.c:192
#define FD_CLOSE_AT_EOXACT
Definition: fd.c:193
void FileClose(File file)
Definition: fd.c:1930
#define FileIsNotOpen(file)
Definition: fd.c:189
static bool have_xact_temporary_files
Definition: fd.c:228
unsigned short fdstate
Definition: fd.c:199

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

Referenced by AtEOXact_Files(), and BeforeShmemExit_Files().

◆ closeAllVfds()

void closeAllVfds ( void  )

Definition at line 2965 of file fd.c.

2966 {
2967  Index i;
2968 
2969  if (SizeVfdCache > 0)
2970  {
2971  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
2972  for (i = 1; i < SizeVfdCache; i++)
2973  {
2974  if (!FileIsNotOpen(i))
2975  LruDelete(i);
2976  }
2977  }
2978 }
static void LruDelete(File file)
Definition: fd.c:1239

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

Referenced by standard_ProcessUtility().

◆ ClosePipeStream()

int ClosePipeStream ( FILE *  file)

Definition at line 2936 of file fd.c.

2937 {
2938  int i;
2939 
2940  DO_DB(elog(LOG, "ClosePipeStream: Allocated %d", numAllocatedDescs));
2941 
2942  /* Remove file from list of allocated files, if it's present */
2943  for (i = numAllocatedDescs; --i >= 0;)
2944  {
2945  AllocateDesc *desc = &allocatedDescs[i];
2946 
2947  if (desc->kind == AllocateDescPipe && desc->desc.file == file)
2948  return FreeDesc(desc);
2949  }
2950 
2951  /* Only get here if someone passes us a file not in allocatedDescs */
2952  elog(WARNING, "file passed to ClosePipeStream was not obtained from OpenPipeStream");
2953 
2954  return pclose(file);
2955 }

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

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

◆ CloseTransientFile()

int CloseTransientFile ( int  fd)

Definition at line 2754 of file fd.c.

2755 {
2756  int i;
2757 
2758  DO_DB(elog(LOG, "CloseTransientFile: Allocated %d", numAllocatedDescs));
2759 
2760  /* Remove fd from list of allocated files, if it's present */
2761  for (i = numAllocatedDescs; --i >= 0;)
2762  {
2763  AllocateDesc *desc = &allocatedDescs[i];
2764 
2765  if (desc->kind == AllocateDescRawFD && desc->desc.fd == fd)
2766  return FreeDesc(desc);
2767  }
2768 
2769  /* Only get here if someone passes us a file not in allocatedDescs */
2770  elog(WARNING, "fd passed to CloseTransientFile was not obtained from OpenTransientFile");
2771 
2772  return close(fd);
2773 }
int fd
Definition: fd.c:263

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

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

◆ count_usable_fds()

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

Definition at line 916 of file fd.c.

917 {
918  int *fd;
919  int size;
920  int used = 0;
921  int highestfd = 0;
922  int j;
923 
924 #ifdef HAVE_GETRLIMIT
925  struct rlimit rlim;
926  int getrlimit_status;
927 #endif
928 
929  size = 1024;
930  fd = (int *) palloc(size * sizeof(int));
931 
932 #ifdef HAVE_GETRLIMIT
933  getrlimit_status = getrlimit(RLIMIT_NOFILE, &rlim);
934  if (getrlimit_status != 0)
935  ereport(WARNING, (errmsg("getrlimit failed: %m")));
936 #endif /* HAVE_GETRLIMIT */
937 
938  /* dup until failure or probe limit reached */
939  for (;;)
940  {
941  int thisfd;
942 
943 #ifdef HAVE_GETRLIMIT
944 
945  /*
946  * don't go beyond RLIMIT_NOFILE; causes irritating kernel logs on
947  * some platforms
948  */
949  if (getrlimit_status == 0 && highestfd >= rlim.rlim_cur - 1)
950  break;
951 #endif
952 
953  thisfd = dup(2);
954  if (thisfd < 0)
955  {
956  /* Expect EMFILE or ENFILE, else it's fishy */
957  if (errno != EMFILE && errno != ENFILE)
958  elog(WARNING, "duplicating stderr file descriptor failed after %d successes: %m", used);
959  break;
960  }
961 
962  if (used >= size)
963  {
964  size *= 2;
965  fd = (int *) repalloc(fd, size * sizeof(int));
966  }
967  fd[used++] = thisfd;
968 
969  if (highestfd < thisfd)
970  highestfd = thisfd;
971 
972  if (used >= max_to_probe)
973  break;
974  }
975 
976  /* release the files we opened */
977  for (j = 0; j < used; j++)
978  close(fd[j]);
979 
980  pfree(fd);
981 
982  /*
983  * Return results. usable_fds is just the number of successful dups. We
984  * assume that the system limit is highestfd+1 (remember 0 is a legal FD
985  * number) and so already_open is highestfd+1 - usable_fds.
986  */
987  *usable_fds = used;
988  *already_open = highestfd + 1 - used;
989 }
int j
Definition: isn.c:74
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1476
void * palloc(Size size)
Definition: mcxt.c:1226

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

Referenced by set_max_safe_fds().

◆ data_sync_elevel()

◆ datadir_fsync_fname()

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

Definition at line 3704 of file fd.c.

3705 {
3706  ereport_startup_progress("syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s",
3707  fname);
3708 
3709  /*
3710  * We want to silently ignoring errors about unreadable files. Pass that
3711  * desire on to fsync_fname_ext().
3712  */
3713  fsync_fname_ext(fname, isdir, true, elevel);
3714 }
int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3742
#define ereport_startup_progress(msg,...)
Definition: startup.h:18

References ereport_startup_progress, and fsync_fname_ext().

Referenced by SyncDataDirectory().

◆ Delete()

static void Delete ( File  file)
static

Definition at line 1220 of file fd.c.

1221 {
1222  Vfd *vfdP;
1223 
1224  Assert(file != 0);
1225 
1226  DO_DB(elog(LOG, "Delete %d (%s)",
1227  file, VfdCache[file].fileName));
1228  DO_DB(_dump_lru());
1229 
1230  vfdP = &VfdCache[file];
1231 
1234 
1235  DO_DB(_dump_lru());
1236 }
File lruLessRecently
Definition: fd.c:203
File lruMoreRecently
Definition: fd.c:202

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

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

◆ durable_rename()

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

Definition at line 734 of file fd.c.

735 {
736  int fd;
737 
738  /*
739  * First fsync the old and target path (if it exists), to ensure that they
740  * are properly persistent on disk. Syncing the target file is not
741  * strictly necessary, but it makes it easier to reason about crashes;
742  * because it's then guaranteed that either source or target file exists
743  * after a crash.
744  */
745  if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
746  return -1;
747 
748  fd = OpenTransientFile(newfile, PG_BINARY | O_RDWR);
749  if (fd < 0)
750  {
751  if (errno != ENOENT)
752  {
753  ereport(elevel,
755  errmsg("could not open file \"%s\": %m", newfile)));
756  return -1;
757  }
758  }
759  else
760  {
761  if (pg_fsync(fd) != 0)
762  {
763  int save_errno;
764 
765  /* close file upon error, might not be in transaction context */
766  save_errno = errno;
768  errno = save_errno;
769 
770  ereport(elevel,
772  errmsg("could not fsync file \"%s\": %m", newfile)));
773  return -1;
774  }
775 
776  if (CloseTransientFile(fd) != 0)
777  {
778  ereport(elevel,
780  errmsg("could not close file \"%s\": %m", newfile)));
781  return -1;
782  }
783  }
784 
785  /* Time to do the real deal... */
786  if (rename(oldfile, newfile) < 0)
787  {
788  ereport(elevel,
790  errmsg("could not rename file \"%s\" to \"%s\": %m",
791  oldfile, newfile)));
792  return -1;
793  }
794 
795  /*
796  * To guarantee renaming the file is persistent, fsync the file with its
797  * new name, and its containing directory.
798  */
799  if (fsync_fname_ext(newfile, false, false, elevel) != 0)
800  return -1;
801 
802  if (fsync_parent_path(newfile, elevel) != 0)
803  return -1;
804 
805  return 0;
806 }
#define PG_BINARY
Definition: c.h:1283
int errcode_for_file_access(void)
Definition: elog.c:881
int CloseTransientFile(int fd)
Definition: fd.c:2754
int pg_fsync(int fd)
Definition: fd.c:361
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3818
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2578

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

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

◆ durable_unlink()

int durable_unlink ( const char *  fname,
int  elevel 
)

Definition at line 824 of file fd.c.

825 {
826  if (unlink(fname) < 0)
827  {
828  ereport(elevel,
830  errmsg("could not remove file \"%s\": %m",
831  fname)));
832  return -1;
833  }
834 
835  /*
836  * To guarantee that the removal of the file is persistent, fsync its
837  * parent directory.
838  */
839  if (fsync_parent_path(fname, elevel) != 0)
840  return -1;
841 
842  return 0;
843 }

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

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

◆ FileAccess()

static int FileAccess ( File  file)
static

Definition at line 1444 of file fd.c.

1445 {
1446  int returnValue;
1447 
1448  DO_DB(elog(LOG, "FileAccess %d (%s)",
1449  file, VfdCache[file].fileName));
1450 
1451  /*
1452  * Is the file open? If not, open it and put it at the head of the LRU
1453  * ring (possibly closing the least recently used file to get an FD).
1454  */
1455 
1456  if (FileIsNotOpen(file))
1457  {
1458  returnValue = LruInsert(file);
1459  if (returnValue != 0)
1460  return returnValue;
1461  }
1462  else if (VfdCache[0].lruLessRecently != file)
1463  {
1464  /*
1465  * We now know that the file is open and that it is not the last one
1466  * accessed, so we need to move it to the head of the Lru ring.
1467  */
1468 
1469  Delete(file);
1470  Insert(file);
1471  }
1472 
1473  return 0;
1474 }
static void Delete(File file)
Definition: fd.c:1220
static void Insert(File file)
Definition: fd.c:1265
static int LruInsert(File file)
Definition: fd.c:1287

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

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

◆ FileClose()

void FileClose ( File  file)

Definition at line 1930 of file fd.c.

1931 {
1932  Vfd *vfdP;
1933 
1934  Assert(FileIsValid(file));
1935 
1936  DO_DB(elog(LOG, "FileClose: %d (%s)",
1937  file, VfdCache[file].fileName));
1938 
1939  vfdP = &VfdCache[file];
1940 
1941  if (!FileIsNotOpen(file))
1942  {
1943  /* close the file */
1944  if (close(vfdP->fd) != 0)
1945  {
1946  /*
1947  * We may need to panic on failure to close non-temporary files;
1948  * see LruDelete.
1949  */
1951  "could not close file \"%s\": %m", vfdP->fileName);
1952  }
1953 
1954  --nfile;
1955  vfdP->fd = VFD_CLOSED;
1956 
1957  /* remove the file from the lru ring */
1958  Delete(file);
1959  }
1960 
1961  if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
1962  {
1963  /* Subtract its size from current usage (do first in case of error) */
1964  temporary_files_size -= vfdP->fileSize;
1965  vfdP->fileSize = 0;
1966  }
1967 
1968  /*
1969  * Delete the file if it was temporary, and make a log entry if wanted
1970  */
1971  if (vfdP->fdstate & FD_DELETE_AT_CLOSE)
1972  {
1973  struct stat filestats;
1974  int stat_errno;
1975 
1976  /*
1977  * If we get an error, as could happen within the ereport/elog calls,
1978  * we'll come right back here during transaction abort. Reset the
1979  * flag to ensure that we can't get into an infinite loop. This code
1980  * is arranged to ensure that the worst-case consequence is failing to
1981  * emit log message(s), not failing to attempt the unlink.
1982  */
1983  vfdP->fdstate &= ~FD_DELETE_AT_CLOSE;
1984 
1985 
1986  /* first try the stat() */
1987  if (stat(vfdP->fileName, &filestats))
1988  stat_errno = errno;
1989  else
1990  stat_errno = 0;
1991 
1992  /* in any case do the unlink */
1993  if (unlink(vfdP->fileName))
1994  ereport(LOG,
1996  errmsg("could not delete file \"%s\": %m", vfdP->fileName)));
1997 
1998  /* and last report the stat results */
1999  if (stat_errno == 0)
2000  ReportTemporaryFileUsage(vfdP->fileName, filestats.st_size);
2001  else
2002  {
2003  errno = stat_errno;
2004  ereport(LOG,
2006  errmsg("could not stat file \"%s\": %m", vfdP->fileName)));
2007  }
2008  }
2009 
2010  /* Unregister it from the resource owner */
2011  if (vfdP->resowner)
2012  ResourceOwnerForgetFile(vfdP->resowner, file);
2013 
2014  /*
2015  * Return the Vfd slot to the free list
2016  */
2017  FreeVfd(file);
2018 }
#define FileIsValid(file)
Definition: fd.c:186
static int nfile
Definition: fd.c:222
static void FreeVfd(File file)
Definition: fd.c:1424
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:194
int data_sync_elevel(int elevel)
Definition: fd.c:3881
static void ReportTemporaryFileUsage(const char *path, off_t size)
Definition: fd.c:1480
static uint64 temporary_files_size
Definition: fd.c:236
void ResourceOwnerForgetFile(ResourceOwner owner, File file)
Definition: resowner.c:1370
char * fileName
Definition: fd.c:205
ResourceOwner resowner
Definition: fd.c:200
off_t fileSize
Definition: fd.c:204
#define stat
Definition: win32_port.h:284

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

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

◆ FileFallocate()

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

Definition at line 2314 of file fd.c.

2315 {
2316 #ifdef HAVE_POSIX_FALLOCATE
2317  int returnCode;
2318 
2319  Assert(FileIsValid(file));
2320 
2321  DO_DB(elog(LOG, "FileFallocate: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
2322  file, VfdCache[file].fileName,
2323  (int64) offset, (int64) amount));
2324 
2325  returnCode = FileAccess(file);
2326  if (returnCode < 0)
2327  return -1;
2328 
2329 retry:
2330  pgstat_report_wait_start(wait_event_info);
2331  returnCode = posix_fallocate(VfdCache[file].fd, offset, amount);
2333 
2334  if (returnCode == 0)
2335  return 0;
2336  else if (returnCode == EINTR)
2337  goto retry;
2338 
2339  /* for compatibility with %m printing etc */
2340  errno = returnCode;
2341 
2342  /*
2343  * Return in cases of a "real" failure, if fallocate is not supported,
2344  * fall through to the FileZero() backed implementation.
2345  */
2346  if (returnCode != EINVAL && returnCode != EOPNOTSUPP)
2347  return -1;
2348 #endif
2349 
2350  return FileZero(file, offset, amount, wait_event_info);
2351 }
#define INT64_FORMAT
Definition: c.h:537
static int FileAccess(File file)
Definition: fd.c:1444
int FileZero(File file, off_t offset, off_t amount, uint32 wait_event_info)
Definition: fd.c:2269
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:88
static void pgstat_report_wait_end(void)
Definition: wait_event.h:104
#define EINTR
Definition: win32_port.h:374
#define EOPNOTSUPP
Definition: win32_port.h:398

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

Referenced by mdzeroextend().

◆ FileGetRawDesc()

int FileGetRawDesc ( File  file)

Definition at line 2422 of file fd.c.

2423 {
2424  Assert(FileIsValid(file));
2425  return VfdCache[file].fd;
2426 }

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

◆ FileGetRawFlags()

int FileGetRawFlags ( File  file)

Definition at line 2432 of file fd.c.

2433 {
2434  Assert(FileIsValid(file));
2435  return VfdCache[file].fileFlags;
2436 }
int fileFlags
Definition: fd.c:207

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

◆ FileGetRawMode()

mode_t FileGetRawMode ( File  file)

Definition at line 2442 of file fd.c.

2443 {
2444  Assert(FileIsValid(file));
2445  return VfdCache[file].fileMode;
2446 }
mode_t fileMode
Definition: fd.c:208

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

◆ FilePathName()

◆ FilePrefetch()

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

Definition at line 2030 of file fd.c.

2031 {
2032 #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
2033  int returnCode;
2034 
2035  Assert(FileIsValid(file));
2036 
2037  DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
2038  file, VfdCache[file].fileName,
2039  (int64) offset, (int64) amount));
2040 
2041  returnCode = FileAccess(file);
2042  if (returnCode < 0)
2043  return returnCode;
2044 
2045 retry:
2046  pgstat_report_wait_start(wait_event_info);
2047  returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
2048  POSIX_FADV_WILLNEED);
2050 
2051  if (returnCode == EINTR)
2052  goto retry;
2053 
2054  return returnCode;
2055 #else
2056  Assert(FileIsValid(file));
2057  return 0;
2058 #endif
2059 }

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

Referenced by mdprefetch().

◆ FileRead()

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

Definition at line 2088 of file fd.c.

2090 {
2091  int returnCode;
2092  Vfd *vfdP;
2093 
2094  Assert(FileIsValid(file));
2095 
2096  DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %zu %p",
2097  file, VfdCache[file].fileName,
2098  (int64) offset,
2099  amount, buffer));
2100 
2101  returnCode = FileAccess(file);
2102  if (returnCode < 0)
2103  return returnCode;
2104 
2105  vfdP = &VfdCache[file];
2106 
2107 retry:
2108  pgstat_report_wait_start(wait_event_info);
2109  returnCode = pg_pread(vfdP->fd, buffer, amount, offset);
2111 
2112  if (returnCode < 0)
2113  {
2114  /*
2115  * Windows may run out of kernel buffers and return "Insufficient
2116  * system resources" error. Wait a bit and retry to solve it.
2117  *
2118  * It is rumored that EINTR is also possible on some Unix filesystems,
2119  * in which case immediate retry is indicated.
2120  */
2121 #ifdef WIN32
2122  DWORD error = GetLastError();
2123 
2124  switch (error)
2125  {
2126  case ERROR_NO_SYSTEM_RESOURCES:
2127  pg_usleep(1000L);
2128  errno = EINTR;
2129  break;
2130  default:
2131  _dosmaperr(error);
2132  break;
2133  }
2134 #endif
2135  /* OK to retry if interrupted */
2136  if (errno == EINTR)
2137  goto retry;
2138  }
2139 
2140  return returnCode;
2141 }
#define pg_pread
Definition: port.h:225
void pg_usleep(long microsec)
Definition: signal.c:53
static void error(void)
Definition: sql-dyntest.c:147
void _dosmaperr(unsigned long)
Definition: win32error.c:177

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

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

◆ FileSize()

off_t FileSize ( File  file)

Definition at line 2354 of file fd.c.

2355 {
2356  Assert(FileIsValid(file));
2357 
2358  DO_DB(elog(LOG, "FileSize %d (%s)",
2359  file, VfdCache[file].fileName));
2360 
2361  if (FileIsNotOpen(file))
2362  {
2363  if (FileAccess(file) < 0)
2364  return (off_t) -1;
2365  }
2366 
2367  return lseek(VfdCache[file].fd, 0, SEEK_END);
2368 }

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

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

◆ FileSync()

int FileSync ( File  file,
uint32  wait_event_info 
)

Definition at line 2242 of file fd.c.

2243 {
2244  int returnCode;
2245 
2246  Assert(FileIsValid(file));
2247 
2248  DO_DB(elog(LOG, "FileSync: %d (%s)",
2249  file, VfdCache[file].fileName));
2250 
2251  returnCode = FileAccess(file);
2252  if (returnCode < 0)
2253  return returnCode;
2254 
2255  pgstat_report_wait_start(wait_event_info);
2256  returnCode = pg_fsync(VfdCache[file].fd);
2258 
2259  return returnCode;
2260 }

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

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

◆ FileTruncate()

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

Definition at line 2371 of file fd.c.

2372 {
2373  int returnCode;
2374 
2375  Assert(FileIsValid(file));
2376 
2377  DO_DB(elog(LOG, "FileTruncate %d (%s)",
2378  file, VfdCache[file].fileName));
2379 
2380  returnCode = FileAccess(file);
2381  if (returnCode < 0)
2382  return returnCode;
2383 
2384  pgstat_report_wait_start(wait_event_info);
2385  returnCode = pg_ftruncate(VfdCache[file].fd, offset);
2387 
2388  if (returnCode == 0 && VfdCache[file].fileSize > offset)
2389  {
2390  /* adjust our state for truncation of a temp file */
2391  Assert(VfdCache[file].fdstate & FD_TEMP_FILE_LIMIT);
2392  temporary_files_size -= VfdCache[file].fileSize - offset;
2393  VfdCache[file].fileSize = offset;
2394  }
2395 
2396  return returnCode;
2397 }
static int pg_ftruncate(int fd, off_t length)
Definition: fd.c:655

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

Referenced by BufFileTruncateFileSet(), and mdtruncate().

◆ FileWrite()

int FileWrite ( File  file,
const void *  buffer,
size_t  amount,
off_t  offset,
uint32  wait_event_info 
)

Definition at line 2144 of file fd.c.

2146 {
2147  int returnCode;
2148  Vfd *vfdP;
2149 
2150  Assert(FileIsValid(file));
2151 
2152  DO_DB(elog(LOG, "FileWrite: %d (%s) " INT64_FORMAT " %zu %p",
2153  file, VfdCache[file].fileName,
2154  (int64) offset,
2155  amount, buffer));
2156 
2157  returnCode = FileAccess(file);
2158  if (returnCode < 0)
2159  return returnCode;
2160 
2161  vfdP = &VfdCache[file];
2162 
2163  /*
2164  * If enforcing temp_file_limit and it's a temp file, check to see if the
2165  * write would overrun temp_file_limit, and throw error if so. Note: it's
2166  * really a modularity violation to throw error here; we should set errno
2167  * and return -1. However, there's no way to report a suitable error
2168  * message if we do that. All current callers would just throw error
2169  * immediately anyway, so this is safe at present.
2170  */
2171  if (temp_file_limit >= 0 && (vfdP->fdstate & FD_TEMP_FILE_LIMIT))
2172  {
2173  off_t past_write = offset + amount;
2174 
2175  if (past_write > vfdP->fileSize)
2176  {
2177  uint64 newTotal = temporary_files_size;
2178 
2179  newTotal += past_write - vfdP->fileSize;
2180  if (newTotal > (uint64) temp_file_limit * (uint64) 1024)
2181  ereport(ERROR,
2182  (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
2183  errmsg("temporary file size exceeds temp_file_limit (%dkB)",
2184  temp_file_limit)));
2185  }
2186  }
2187 
2188 retry:
2189  errno = 0;
2190  pgstat_report_wait_start(wait_event_info);
2191  returnCode = pg_pwrite(VfdCache[file].fd, buffer, amount, offset);
2193 
2194  /* if write didn't set errno, assume problem is no disk space */
2195  if (returnCode != amount && errno == 0)
2196  errno = ENOSPC;
2197 
2198  if (returnCode >= 0)
2199  {
2200  /*
2201  * Maintain fileSize and temporary_files_size if it's a temp file.
2202  */
2203  if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
2204  {
2205  off_t past_write = offset + amount;
2206 
2207  if (past_write > vfdP->fileSize)
2208  {
2209  temporary_files_size += past_write - vfdP->fileSize;
2210  vfdP->fileSize = past_write;
2211  }
2212  }
2213  }
2214  else
2215  {
2216  /*
2217  * See comments in FileRead()
2218  */
2219 #ifdef WIN32
2220  DWORD error = GetLastError();
2221 
2222  switch (error)
2223  {
2224  case ERROR_NO_SYSTEM_RESOURCES:
2225  pg_usleep(1000L);
2226  errno = EINTR;
2227  break;
2228  default:
2229  _dosmaperr(error);
2230  break;
2231  }
2232 #endif
2233  /* OK to retry if interrupted */
2234  if (errno == EINTR)
2235  goto retry;
2236  }
2237 
2238  return returnCode;
2239 }
int temp_file_limit
Definition: guc_tables.c:531
#define pg_pwrite
Definition: port.h:226

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

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

◆ FileWriteback()

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

Definition at line 2062 of file fd.c.

2063 {
2064  int returnCode;
2065 
2066  Assert(FileIsValid(file));
2067 
2068  DO_DB(elog(LOG, "FileWriteback: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
2069  file, VfdCache[file].fileName,
2070  (int64) offset, (int64) nbytes));
2071 
2072  if (nbytes <= 0)
2073  return;
2074 
2075  if (VfdCache[file].fileFlags & PG_O_DIRECT)
2076  return;
2077 
2078  returnCode = FileAccess(file);
2079  if (returnCode < 0)
2080  return;
2081 
2082  pgstat_report_wait_start(wait_event_info);
2083  pg_flush_data(VfdCache[file].fd, offset, nbytes);
2085 }
void pg_flush_data(int fd, off_t offset, off_t nbytes)
Definition: fd.c:477

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

Referenced by mdwriteback().

◆ FileZero()

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

Definition at line 2269 of file fd.c.

2270 {
2271  int returnCode;
2272  ssize_t written;
2273 
2274  Assert(FileIsValid(file));
2275 
2276  DO_DB(elog(LOG, "FileZero: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
2277  file, VfdCache[file].fileName,
2278  (int64) offset, (int64) amount));
2279 
2280  returnCode = FileAccess(file);
2281  if (returnCode < 0)
2282  return returnCode;
2283 
2284  pgstat_report_wait_start(wait_event_info);
2285  written = pg_pwrite_zeros(VfdCache[file].fd, amount, offset);
2287 
2288  if (written < 0)
2289  return -1;
2290  else if (written != amount)
2291  {
2292  /* if errno is unset, assume problem is no disk space */
2293  if (errno == 0)
2294  errno = ENOSPC;
2295  return -1;
2296  }
2297 
2298  return 0;
2299 }
ssize_t pg_pwrite_zeros(int fd, size_t size, off_t offset)
Definition: file_utils.c:660

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

Referenced by FileFallocate(), and mdzeroextend().

◆ FreeDesc()

static int FreeDesc ( AllocateDesc desc)
static

Definition at line 2687 of file fd.c.

2688 {
2689  int result;
2690 
2691  /* Close the underlying object */
2692  switch (desc->kind)
2693  {
2694  case AllocateDescFile:
2695  result = fclose(desc->desc.file);
2696  break;
2697  case AllocateDescPipe:
2698  result = pclose(desc->desc.file);
2699  break;
2700  case AllocateDescDir:
2701  result = closedir(desc->desc.dir);
2702  break;
2703  case AllocateDescRawFD:
2704  result = close(desc->desc.fd);
2705  break;
2706  default:
2707  elog(ERROR, "AllocateDesc kind not recognized");
2708  result = 0; /* keep compiler quiet */
2709  break;
2710  }
2711 
2712  /* Compact storage in the allocatedDescs array */
2715 
2716  return result;
2717 }
int closedir(DIR *)
Definition: dirent.c:127

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

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

◆ FreeDir()

int FreeDir ( DIR dir)

Definition at line 2906 of file fd.c.

2907 {
2908  int i;
2909 
2910  /* Nothing to do if AllocateDir failed */
2911  if (dir == NULL)
2912  return 0;
2913 
2914  DO_DB(elog(LOG, "FreeDir: Allocated %d", numAllocatedDescs));
2915 
2916  /* Remove dir from list of allocated dirs, if it's present */
2917  for (i = numAllocatedDescs; --i >= 0;)
2918  {
2919  AllocateDesc *desc = &allocatedDescs[i];
2920 
2921  if (desc->kind == AllocateDescDir && desc->desc.dir == dir)
2922  return FreeDesc(desc);
2923  }
2924 
2925  /* Only get here if someone passes us a dir not in allocatedDescs */
2926  elog(WARNING, "dir passed to FreeDir was not obtained from AllocateDir");
2927 
2928  return closedir(dir);
2929 }

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

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

◆ FreeFile()

int FreeFile ( FILE *  file)

Definition at line 2726 of file fd.c.

2727 {
2728  int i;
2729 
2730  DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedDescs));
2731 
2732  /* Remove file from list of allocated files, if it's present */
2733  for (i = numAllocatedDescs; --i >= 0;)
2734  {
2735  AllocateDesc *desc = &allocatedDescs[i];
2736 
2737  if (desc->kind == AllocateDescFile && desc->desc.file == file)
2738  return FreeDesc(desc);
2739  }
2740 
2741  /* Only get here if someone passes us a file not in allocatedDescs */
2742  elog(WARNING, "file passed to FreeFile was not obtained from AllocateFile");
2743 
2744  return fclose(file);
2745 }

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

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

◆ FreeVfd()

static void FreeVfd ( File  file)
static

Definition at line 1424 of file fd.c.

1425 {
1426  Vfd *vfdP = &VfdCache[file];
1427 
1428  DO_DB(elog(LOG, "FreeVfd: %d (%s)",
1429  file, vfdP->fileName ? vfdP->fileName : ""));
1430 
1431  if (vfdP->fileName != NULL)
1432  {
1433  free(vfdP->fileName);
1434  vfdP->fileName = NULL;
1435  }
1436  vfdP->fdstate = 0x0;
1437 
1438  vfdP->nextFree = VfdCache[0].nextFree;
1439  VfdCache[0].nextFree = file;
1440 }
#define free(a)
Definition: header.h:65

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

Referenced by FileClose(), and PathNameOpenFilePerm().

◆ fsync_fname()

◆ fsync_fname_ext()

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

Definition at line 3742 of file fd.c.

3743 {
3744  int fd;
3745  int flags;
3746  int returncode;
3747 
3748  /*
3749  * Some OSs require directories to be opened read-only whereas other
3750  * systems don't allow us to fsync files opened read-only; so we need both
3751  * cases here. Using O_RDWR will cause us to fail to fsync files that are
3752  * not writable by our userid, but we assume that's OK.
3753  */
3754  flags = PG_BINARY;
3755  if (!isdir)
3756  flags |= O_RDWR;
3757  else
3758  flags |= O_RDONLY;
3759 
3760  fd = OpenTransientFile(fname, flags);
3761 
3762  /*
3763  * Some OSs don't allow us to open directories at all (Windows returns
3764  * EACCES), just ignore the error in that case. If desired also silently
3765  * ignoring errors about unreadable files. Log others.
3766  */
3767  if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
3768  return 0;
3769  else if (fd < 0 && ignore_perm && errno == EACCES)
3770  return 0;
3771  else if (fd < 0)
3772  {
3773  ereport(elevel,
3775  errmsg("could not open file \"%s\": %m", fname)));
3776  return -1;
3777  }
3778 
3779  returncode = pg_fsync(fd);
3780 
3781  /*
3782  * Some OSes don't allow us to fsync directories at all, so we can ignore
3783  * those errors. Anything else needs to be logged.
3784  */
3785  if (returncode != 0 && !(isdir && (errno == EBADF || errno == EINVAL)))
3786  {
3787  int save_errno;
3788 
3789  /* close file upon error, might not be in transaction context */
3790  save_errno = errno;
3791  (void) CloseTransientFile(fd);
3792  errno = save_errno;
3793 
3794  ereport(elevel,
3796  errmsg("could not fsync file \"%s\": %m", fname)));
3797  return -1;
3798  }
3799 
3800  if (CloseTransientFile(fd) != 0)
3801  {
3802  ereport(elevel,
3804  errmsg("could not close file \"%s\": %m", fname)));
3805  return -1;
3806  }
3807 
3808  return 0;
3809 }

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

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

◆ fsync_parent_path()

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

Definition at line 3818 of file fd.c.

3819 {
3820  char parentpath[MAXPGPATH];
3821 
3822  strlcpy(parentpath, fname, MAXPGPATH);
3823  get_parent_directory(parentpath);
3824 
3825  /*
3826  * get_parent_directory() returns an empty string if the input argument is
3827  * just a file name (see comments in path.c), so handle that as being the
3828  * current directory.
3829  */
3830  if (strlen(parentpath) == 0)
3831  strlcpy(parentpath, ".", MAXPGPATH);
3832 
3833  if (fsync_fname_ext(parentpath, true, false, elevel) != 0)
3834  return -1;
3835 
3836  return 0;
3837 }
#define MAXPGPATH
void get_parent_directory(char *path)
Definition: path.c:977
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45

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

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

◆ GetNextTempTableSpace()

Oid GetNextTempTableSpace ( void  )

Definition at line 3056 of file fd.c.

3057 {
3058  if (numTempTableSpaces > 0)
3059  {
3060  /* Advance nextTempTableSpace counter with wraparound */
3062  nextTempTableSpace = 0;
3064  }
3065  return InvalidOid;
3066 }
static int nextTempTableSpace
Definition: fd.c:290
#define InvalidOid
Definition: postgres_ext.h:36

References InvalidOid, nextTempTableSpace, numTempTableSpaces, and tempTableSpaces.

Referenced by GetDefaultTablespace(), and OpenTemporaryFile().

◆ GetTempTablespaces()

int GetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 3038 of file fd.c.

3039 {
3040  int i;
3041 
3043  for (i = 0; i < numTempTableSpaces && i < numSpaces; ++i)
3044  tableSpaces[i] = tempTableSpaces[i];
3045 
3046  return i;
3047 }
bool TempTablespacesAreSet(void)
Definition: fd.c:3023

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

Referenced by FileSetInit().

◆ InitFileAccess()

void InitFileAccess ( void  )

Definition at line 855 of file fd.c.

856 {
857  Assert(SizeVfdCache == 0); /* call me only once */
858 
859  /* initialize cache header entry */
860  VfdCache = (Vfd *) malloc(sizeof(Vfd));
861  if (VfdCache == NULL)
862  ereport(FATAL,
863  (errcode(ERRCODE_OUT_OF_MEMORY),
864  errmsg("out of memory")));
865 
866  MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
868 
869  SizeVfdCache = 1;
870 }
#define FATAL
Definition: elog.h:41
#define malloc(a)
Definition: header.h:50

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

Referenced by BaseInit().

◆ InitTemporaryFileAccess()

void InitTemporaryFileAccess ( void  )

Definition at line 885 of file fd.c.

886 {
887  Assert(SizeVfdCache != 0); /* InitFileAccess() needs to have run */
888  Assert(!temporary_files_allowed); /* call me only once */
889 
890  /*
891  * Register before-shmem-exit hook to ensure temp files are dropped while
892  * we can still report stats.
893  */
895 
896 #ifdef USE_ASSERT_CHECKING
897  temporary_files_allowed = true;
898 #endif
899 }
static void BeforeShmemExit_Files(int code, Datum arg)
Definition: fd.c:3124
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:333

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

Referenced by BaseInit().

◆ Insert()

static void Insert ( File  file)
static

Definition at line 1265 of file fd.c.

1266 {
1267  Vfd *vfdP;
1268 
1269  Assert(file != 0);
1270 
1271  DO_DB(elog(LOG, "Insert %d (%s)",
1272  file, VfdCache[file].fileName));
1273  DO_DB(_dump_lru());
1274 
1275  vfdP = &VfdCache[file];
1276 
1277  vfdP->lruMoreRecently = 0;
1279  VfdCache[0].lruLessRecently = file;
1281 
1282  DO_DB(_dump_lru());
1283 }

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

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

◆ looks_like_temp_rel_name()

bool looks_like_temp_rel_name ( const char *  name)

Definition at line 3394 of file fd.c.

3395 {
3396  int pos;
3397  int savepos;
3398 
3399  /* Must start with "t". */
3400  if (name[0] != 't')
3401  return false;
3402 
3403  /* Followed by a non-empty string of digits and then an underscore. */
3404  for (pos = 1; isdigit((unsigned char) name[pos]); ++pos)
3405  ;
3406  if (pos == 1 || name[pos] != '_')
3407  return false;
3408 
3409  /* Followed by another nonempty string of digits. */
3410  for (savepos = ++pos; isdigit((unsigned char) name[pos]); ++pos)
3411  ;
3412  if (savepos == pos)
3413  return false;
3414 
3415  /* We might have _forkname or .segment or both. */
3416  if (name[pos] == '_')
3417  {
3418  int forkchar = forkname_chars(&name[pos + 1], NULL);
3419 
3420  if (forkchar <= 0)
3421  return false;
3422  pos += forkchar + 1;
3423  }
3424  if (name[pos] == '.')
3425  {
3426  int segchar;
3427 
3428  for (segchar = 1; isdigit((unsigned char) name[pos + segchar]); ++segchar)
3429  ;
3430  if (segchar <= 1)
3431  return false;
3432  pos += segchar;
3433  }
3434 
3435  /* Now we should be at the end. */
3436  if (name[pos] != '\0')
3437  return false;
3438  return true;
3439 }
int forkname_chars(const char *str, ForkNumber *fork)
Definition: relpath.c:81

References forkname_chars(), and name.

Referenced by RemovePgTempRelationFilesInDbspace(), and sendDir().

◆ LruDelete()

static void LruDelete ( File  file)
static

Definition at line 1239 of file fd.c.

1240 {
1241  Vfd *vfdP;
1242 
1243  Assert(file != 0);
1244 
1245  DO_DB(elog(LOG, "LruDelete %d (%s)",
1246  file, VfdCache[file].fileName));
1247 
1248  vfdP = &VfdCache[file];
1249 
1250  /*
1251  * Close the file. We aren't expecting this to fail; if it does, better
1252  * to leak the FD than to mess up our internal state.
1253  */
1254  if (close(vfdP->fd) != 0)
1256  "could not close file \"%s\": %m", vfdP->fileName);
1257  vfdP->fd = VFD_CLOSED;
1258  --nfile;
1259 
1260  /* delete the vfd record from the LRU ring */
1261  Delete(file);
1262 }

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

Referenced by closeAllVfds(), and ReleaseLruFile().

◆ LruInsert()

static int LruInsert ( File  file)
static

Definition at line 1287 of file fd.c.

1288 {
1289  Vfd *vfdP;
1290 
1291  Assert(file != 0);
1292 
1293  DO_DB(elog(LOG, "LruInsert %d (%s)",
1294  file, VfdCache[file].fileName));
1295 
1296  vfdP = &VfdCache[file];
1297 
1298  if (FileIsNotOpen(file))
1299  {
1300  /* Close excess kernel FDs. */
1301  ReleaseLruFiles();
1302 
1303  /*
1304  * The open could still fail for lack of file descriptors, eg due to
1305  * overall system file table being full. So, be prepared to release
1306  * another FD if necessary...
1307  */
1308  vfdP->fd = BasicOpenFilePerm(vfdP->fileName, vfdP->fileFlags,
1309  vfdP->fileMode);
1310  if (vfdP->fd < 0)
1311  {
1312  DO_DB(elog(LOG, "re-open failed: %m"));
1313  return -1;
1314  }
1315  else
1316  {
1317  ++nfile;
1318  }
1319  }
1320 
1321  /*
1322  * put it at the head of the Lru ring
1323  */
1324 
1325  Insert(file);
1326 
1327  return 0;
1328 }

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

Referenced by FileAccess().

◆ MakePGDirectory()

int MakePGDirectory ( const char *  directoryName)

◆ OpenPipeStream()

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

Definition at line 2631 of file fd.c.

2632 {
2633  FILE *file;
2634  int save_errno;
2635 
2636  DO_DB(elog(LOG, "OpenPipeStream: Allocated %d (%s)",
2637  numAllocatedDescs, command));
2638 
2639  /* Can we allocate another non-virtual FD? */
2640  if (!reserveAllocatedDesc())
2641  ereport(ERROR,
2642  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2643  errmsg("exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"",
2644  maxAllocatedDescs, command)));
2645 
2646  /* Close excess kernel FDs. */
2647  ReleaseLruFiles();
2648 
2649 TryAgain:
2650  fflush(NULL);
2652  errno = 0;
2653  file = popen(command, mode);
2654  save_errno = errno;
2656  errno = save_errno;
2657  if (file != NULL)
2658  {
2660 
2661  desc->kind = AllocateDescPipe;
2662  desc->desc.file = file;
2665  return desc->desc.file;
2666  }
2667 
2668  if (errno == EMFILE || errno == ENFILE)
2669  {
2670  ereport(LOG,
2671  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2672  errmsg("out of file descriptors: %m; release and retry")));
2673  if (ReleaseLruFile())
2674  goto TryAgain;
2675  errno = save_errno;
2676  }
2677 
2678  return NULL;
2679 }
static void const char fflush(stdout)
pqsigfunc pqsignal(int signo, pqsigfunc func)
#define SIG_DFL
Definition: win32_port.h:163
#define SIGPIPE
Definition: win32_port.h:173
#define SIG_IGN
Definition: win32_port.h:165

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

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

◆ OpenTemporaryFile()

File OpenTemporaryFile ( bool  interXact)

Definition at line 1676 of file fd.c.

1677 {
1678  File file = 0;
1679 
1680  Assert(temporary_files_allowed); /* check temp file access is up */
1681 
1682  /*
1683  * Make sure the current resource owner has space for this File before we
1684  * open it, if we'll be registering it below.
1685  */
1686  if (!interXact)
1688 
1689  /*
1690  * If some temp tablespace(s) have been given to us, try to use the next
1691  * one. If a given tablespace can't be found, we silently fall back to
1692  * the database's default tablespace.
1693  *
1694  * BUT: if the temp file is slated to outlive the current transaction,
1695  * force it into the database's default tablespace, so that it will not
1696  * pose a threat to possible tablespace drop attempts.
1697  */
1698  if (numTempTableSpaces > 0 && !interXact)
1699  {
1700  Oid tblspcOid = GetNextTempTableSpace();
1701 
1702  if (OidIsValid(tblspcOid))
1703  file = OpenTemporaryFileInTablespace(tblspcOid, false);
1704  }
1705 
1706  /*
1707  * If not, or if tablespace is bad, create in database's default
1708  * tablespace. MyDatabaseTableSpace should normally be set before we get
1709  * here, but just in case it isn't, fall back to pg_default tablespace.
1710  */
1711  if (file <= 0)
1714  DEFAULTTABLESPACE_OID,
1715  true);
1716 
1717  /* Mark it for deletion at close and temporary file size limit */
1719 
1720  /* Register it with the current resource owner */
1721  if (!interXact)
1722  RegisterTemporaryFile(file);
1723 
1724  return file;
1725 }
#define OidIsValid(objectId)
Definition: c.h:764
Oid GetNextTempTableSpace(void)
Definition: fd.c:3056
static File OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
Definition: fd.c:1756
static void RegisterTemporaryFile(File file)
Definition: fd.c:1499
Oid MyDatabaseTableSpace
Definition: globals.c:91
unsigned int Oid
Definition: postgres_ext.h:31
void ResourceOwnerEnlargeFiles(ResourceOwner owner)
Definition: resowner.c:1350
ResourceOwner CurrentResourceOwner
Definition: resowner.c:147

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

Referenced by BufFileCreateTemp(), and extendBufFile().

◆ OpenTemporaryFileInTablespace()

static File OpenTemporaryFileInTablespace ( Oid  tblspcOid,
bool  rejectError 
)
static

Definition at line 1756 of file fd.c.

1757 {
1758  char tempdirpath[MAXPGPATH];
1759  char tempfilepath[MAXPGPATH];
1760  File file;
1761 
1762  TempTablespacePath(tempdirpath, tblspcOid);
1763 
1764  /*
1765  * Generate a tempfile name that should be unique within the current
1766  * database instance.
1767  */
1768  snprintf(tempfilepath, sizeof(tempfilepath), "%s/%s%d.%ld",
1769  tempdirpath, PG_TEMP_FILE_PREFIX, MyProcPid, tempFileCounter++);
1770 
1771  /*
1772  * Open the file. Note: we don't use O_EXCL, in case there is an orphaned
1773  * temp file that can be reused.
1774  */
1775  file = PathNameOpenFile(tempfilepath,
1776  O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1777  if (file <= 0)
1778  {
1779  /*
1780  * We might need to create the tablespace's tempfile directory, if no
1781  * one has yet done so.
1782  *
1783  * Don't check for an error from MakePGDirectory; it could fail if
1784  * someone else just did the same thing. If it doesn't work then
1785  * we'll bomb out on the second create attempt, instead.
1786  */
1787  (void) MakePGDirectory(tempdirpath);
1788 
1789  file = PathNameOpenFile(tempfilepath,
1790  O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1791  if (file <= 0 && rejectError)
1792  elog(ERROR, "could not create temporary file \"%s\": %m",
1793  tempfilepath);
1794  }
1795 
1796  return file;
1797 }
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3858
static long tempFileCounter
Definition: fd.c:280
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition: fd.c:1527
void TempTablespacePath(char *path, Oid tablespace)
Definition: fd.c:1731
#define PG_TEMP_FILE_PREFIX
Definition: file_utils.h:58
int MyProcPid
Definition: globals.c:44
#define snprintf
Definition: port.h:238

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

Referenced by OpenTemporaryFile().

◆ OpenTransientFile()

◆ OpenTransientFilePerm()

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

Definition at line 2587 of file fd.c.

2588 {
2589  int fd;
2590 
2591  DO_DB(elog(LOG, "OpenTransientFile: Allocated %d (%s)",
2592  numAllocatedDescs, fileName));
2593 
2594  /* Can we allocate another non-virtual FD? */
2595  if (!reserveAllocatedDesc())
2596  ereport(ERROR,
2597  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2598  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2599  maxAllocatedDescs, fileName)));
2600 
2601  /* Close excess kernel FDs. */
2602  ReleaseLruFiles();
2603 
2604  fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
2605 
2606  if (fd >= 0)
2607  {
2609 
2610  desc->kind = AllocateDescRawFD;
2611  desc->desc.fd = fd;
2614 
2615  return fd;
2616  }
2617 
2618  return -1; /* failure */
2619 }

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

Referenced by be_lo_export(), and OpenTransientFile().

◆ PathNameCreateTemporaryDir()

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

Definition at line 1612 of file fd.c.

1613 {
1614  if (MakePGDirectory(directory) < 0)
1615  {
1616  if (errno == EEXIST)
1617  return;
1618 
1619  /*
1620  * Failed. Try to create basedir first in case it's missing. Tolerate
1621  * EEXIST to close a race against another process following the same
1622  * algorithm.
1623  */
1624  if (MakePGDirectory(basedir) < 0 && errno != EEXIST)
1625  ereport(ERROR,
1627  errmsg("cannot create temporary directory \"%s\": %m",
1628  basedir)));
1629 
1630  /* Try again. */
1631  if (MakePGDirectory(directory) < 0 && errno != EEXIST)
1632  ereport(ERROR,
1634  errmsg("cannot create temporary subdirectory \"%s\": %m",
1635  directory)));
1636  }
1637 }
static char * basedir
static const char * directory
Definition: zic.c:634

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

Referenced by FileSetCreate().

◆ PathNameCreateTemporaryFile()

File PathNameCreateTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1813 of file fd.c.

1814 {
1815  File file;
1816 
1817  Assert(temporary_files_allowed); /* check temp file access is up */
1818 
1820 
1821  /*
1822  * Open the file. Note: we don't use O_EXCL, in case there is an orphaned
1823  * temp file that can be reused.
1824  */
1825  file = PathNameOpenFile(path, O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
1826  if (file <= 0)
1827  {
1828  if (error_on_failure)
1829  ereport(ERROR,
1831  errmsg("could not create temporary file \"%s\": %m",
1832  path)));
1833  else
1834  return file;
1835  }
1836 
1837  /* Mark it for temp_file_limit accounting. */
1839 
1840  /* Register it for automatic close. */
1841  RegisterTemporaryFile(file);
1842 
1843  return file;
1844 }

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

Referenced by FileSetCreate().

◆ PathNameDeleteTemporaryDir()

void PathNameDeleteTemporaryDir ( const char *  dirname)

Definition at line 1643 of file fd.c.

1644 {
1645  struct stat statbuf;
1646 
1647  /* Silently ignore missing directory. */
1648  if (stat(dirname, &statbuf) != 0 && errno == ENOENT)
1649  return;
1650 
1651  /*
1652  * Currently, walkdir doesn't offer a way for our passed in function to
1653  * maintain state. Perhaps it should, so that we could tell the caller
1654  * whether this operation succeeded or failed. Since this operation is
1655  * used in a cleanup path, we wouldn't actually behave differently: we'll
1656  * just log failures.
1657  */
1658  walkdir(dirname, unlink_if_exists_fname, false, LOG);
1659 }
static void unlink_if_exists_fname(const char *fname, bool isdir, int elevel)
Definition: fd.c:3717
static void walkdir(const char *path, void(*action)(const char *fname, bool isdir, int elevel), bool process_symlinks, int elevel)
Definition: fd.c:3603

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

Referenced by FileSetDeleteAll().

◆ PathNameDeleteTemporaryFile()

bool PathNameDeleteTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1884 of file fd.c.

1885 {
1886  struct stat filestats;
1887  int stat_errno;
1888 
1889  /* Get the final size for pgstat reporting. */
1890  if (stat(path, &filestats) != 0)
1891  stat_errno = errno;
1892  else
1893  stat_errno = 0;
1894 
1895  /*
1896  * Unlike FileClose's automatic file deletion code, we tolerate
1897  * non-existence to support BufFileDeleteFileSet which doesn't know how
1898  * many segments it has to delete until it runs out.
1899  */
1900  if (stat_errno == ENOENT)
1901  return false;
1902 
1903  if (unlink(path) < 0)
1904  {
1905  if (errno != ENOENT)
1906  ereport(error_on_failure ? ERROR : LOG,
1908  errmsg("could not unlink temporary file \"%s\": %m",
1909  path)));
1910  return false;
1911  }
1912 
1913  if (stat_errno == 0)
1914  ReportTemporaryFileUsage(path, filestats.st_size);
1915  else
1916  {
1917  errno = stat_errno;
1918  ereport(LOG,
1920  errmsg("could not stat file \"%s\": %m", path)));
1921  }
1922 
1923  return true;
1924 }

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

Referenced by FileSetDelete(), and unlink_if_exists_fname().

◆ PathNameOpenFile()

File PathNameOpenFile ( const char *  fileName,
int  fileFlags 
)

◆ PathNameOpenFilePerm()

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

Definition at line 1540 of file fd.c.

1541 {
1542  char *fnamecopy;
1543  File file;
1544  Vfd *vfdP;
1545 
1546  DO_DB(elog(LOG, "PathNameOpenFilePerm: %s %x %o",
1547  fileName, fileFlags, fileMode));
1548 
1549  /*
1550  * We need a malloc'd copy of the file name; fail cleanly if no room.
1551  */
1552  fnamecopy = strdup(fileName);
1553  if (fnamecopy == NULL)
1554  ereport(ERROR,
1555  (errcode(ERRCODE_OUT_OF_MEMORY),
1556  errmsg("out of memory")));
1557 
1558  file = AllocateVfd();
1559  vfdP = &VfdCache[file];
1560 
1561  /* Close excess kernel FDs. */
1562  ReleaseLruFiles();
1563 
1564  /*
1565  * Descriptors managed by VFDs are implicitly marked O_CLOEXEC. The
1566  * client shouldn't be expected to know which kernel descriptors are
1567  * currently open, so it wouldn't make sense for them to be inherited by
1568  * executed subprograms.
1569  */
1570  fileFlags |= O_CLOEXEC;
1571 
1572  vfdP->fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
1573 
1574  if (vfdP->fd < 0)
1575  {
1576  int save_errno = errno;
1577 
1578  FreeVfd(file);
1579  free(fnamecopy);
1580  errno = save_errno;
1581  return -1;
1582  }
1583  ++nfile;
1584  DO_DB(elog(LOG, "PathNameOpenFile: success %d",
1585  vfdP->fd));
1586 
1587  vfdP->fileName = fnamecopy;
1588  /* Saved flags are adjusted to be OK for re-opening file */
1589  vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
1590  vfdP->fileMode = fileMode;
1591  vfdP->fileSize = 0;
1592  vfdP->fdstate = 0x0;
1593  vfdP->resowner = NULL;
1594 
1595  Insert(file);
1596 
1597  return file;
1598 }
static File AllocateVfd(void)
Definition: fd.c:1366

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, O_CLOEXEC, ReleaseLruFiles(), vfd::resowner, and VfdCache.

Referenced by PathNameOpenFile().

◆ PathNameOpenTemporaryFile()

File PathNameOpenTemporaryFile ( const char *  path,
int  mode 
)

Definition at line 1853 of file fd.c.

1854 {
1855  File file;
1856 
1857  Assert(temporary_files_allowed); /* check temp file access is up */
1858 
1860 
1861  file = PathNameOpenFile(path, mode | PG_BINARY);
1862 
1863  /* If no such file, then we don't raise an error. */
1864  if (file <= 0 && errno != ENOENT)
1865  ereport(ERROR,
1867  errmsg("could not open temporary file \"%s\": %m",
1868  path)));
1869 
1870  if (file > 0)
1871  {
1872  /* Register it for automatic close. */
1873  RegisterTemporaryFile(file);
1874  }
1875 
1876  return file;
1877 }

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

Referenced by FileSetOpen().

◆ pg_fdatasync()

int pg_fdatasync ( int  fd)

Definition at line 455 of file fd.c.

456 {
457  int rc;
458 
459  if (!enableFsync)
460  return 0;
461 
462 retry:
463  rc = fdatasync(fd);
464 
465  if (rc == -1 && errno == EINTR)
466  goto retry;
467 
468  return rc;
469 }
int fdatasync(int fildes)
bool enableFsync
Definition: globals.c:123

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

Referenced by issue_xlog_fsync().

◆ pg_flush_data()

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

Definition at line 477 of file fd.c.

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

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

Referenced by copy_file(), and FileWriteback().

◆ pg_fsync()

int pg_fsync ( int  fd)

Definition at line 361 of file fd.c.

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

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

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

◆ pg_fsync_no_writethrough()

int pg_fsync_no_writethrough ( int  fd)

Definition at line 416 of file fd.c.

417 {
418  int rc;
419 
420  if (!enableFsync)
421  return 0;
422 
423 retry:
424  rc = fsync(fd);
425 
426  if (rc == -1 && errno == EINTR)
427  goto retry;
428 
429  return rc;
430 }
#define fsync(fd)
Definition: win32_port.h:85

References EINTR, enableFsync, fd(), and fsync.

Referenced by issue_xlog_fsync(), and pg_fsync().

◆ pg_fsync_writethrough()

int pg_fsync_writethrough ( int  fd)

Definition at line 436 of file fd.c.

437 {
438  if (enableFsync)
439  {
440 #if defined(F_FULLFSYNC)
441  return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
442 #else
443  errno = ENOSYS;
444  return -1;
445 #endif
446  }
447  else
448  return 0;
449 }

References enableFsync, and fd().

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

◆ pg_ftruncate()

static int pg_ftruncate ( int  fd,
off_t  length 
)
static

Definition at line 655 of file fd.c.

656 {
657  int ret;
658 
659 retry:
660  ret = ftruncate(fd, length);
661 
662  if (ret == -1 && errno == EINTR)
663  goto retry;
664 
665  return ret;
666 }
#define ftruncate(a, b)
Definition: win32_port.h:82

References EINTR, fd(), and ftruncate.

Referenced by FileTruncate(), and pg_truncate().

◆ pg_truncate()

int pg_truncate ( const char *  path,
off_t  length 
)

Definition at line 672 of file fd.c.

673 {
674  int ret;
675 #ifdef WIN32
676  int save_errno;
677  int fd;
678 
679  fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
680  if (fd >= 0)
681  {
682  ret = pg_ftruncate(fd, length);
683  save_errno = errno;
685  errno = save_errno;
686  }
687  else
688  ret = -1;
689 #else
690 
691 retry:
692  ret = truncate(path, length);
693 
694  if (ret == -1 && errno == EINTR)
695  goto retry;
696 #endif
697 
698  return ret;
699 }

References CloseTransientFile(), EINTR, fd(), OpenTransientFile(), PG_BINARY, and pg_ftruncate().

Referenced by do_truncate().

◆ ReadDir()

◆ ReadDirExtended()

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

Definition at line 2869 of file fd.c.

2870 {
2871  struct dirent *dent;
2872 
2873  /* Give a generic message for AllocateDir failure, if caller didn't */
2874  if (dir == NULL)
2875  {
2876  ereport(elevel,
2878  errmsg("could not open directory \"%s\": %m",
2879  dirname)));
2880  return NULL;
2881  }
2882 
2883  errno = 0;
2884  if ((dent = readdir(dir)) != NULL)
2885  return dent;
2886 
2887  if (errno)
2888  ereport(elevel,
2890  errmsg("could not read directory \"%s\": %m",
2891  dirname)));
2892  return NULL;
2893 }
struct dirent * readdir(DIR *)
Definition: dirent.c:78
Definition: dirent.h:10

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

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

◆ RegisterTemporaryFile()

static void RegisterTemporaryFile ( File  file)
static

Definition at line 1499 of file fd.c.

1500 {
1503 
1504  /* Backup mechanism for closing at end of xact. */
1507 }
void ResourceOwnerRememberFile(ResourceOwner owner, File file)
Definition: resowner.c:1361

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

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

◆ ReleaseExternalFD()

◆ ReleaseLruFile()

static bool ReleaseLruFile ( void  )
static

Definition at line 1334 of file fd.c.

1335 {
1336  DO_DB(elog(LOG, "ReleaseLruFile. Opened %d", nfile));
1337 
1338  if (nfile > 0)
1339  {
1340  /*
1341  * There are opened files and so there should be at least one used vfd
1342  * in the ring.
1343  */
1344  Assert(VfdCache[0].lruMoreRecently != 0);
1345  LruDelete(VfdCache[0].lruMoreRecently);
1346  return true; /* freed a file */
1347  }
1348  return false; /* no files available to free */
1349 }

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

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

◆ ReleaseLruFiles()

static void ReleaseLruFiles ( void  )
static

Definition at line 1356 of file fd.c.

1357 {
1359  {
1360  if (!ReleaseLruFile())
1361  break;
1362  }
1363 }

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

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

◆ RemovePgTempFiles()

void RemovePgTempFiles ( void  )

Definition at line 3219 of file fd.c.

3220 {
3221  char temp_path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY) + sizeof(PG_TEMP_FILES_DIR)];
3222  DIR *spc_dir;
3223  struct dirent *spc_de;
3224 
3225  /*
3226  * First process temp files in pg_default ($PGDATA/base)
3227  */
3228  snprintf(temp_path, sizeof(temp_path), "base/%s", PG_TEMP_FILES_DIR);
3229  RemovePgTempFilesInDir(temp_path, true, false);
3230  RemovePgTempRelationFiles("base");
3231 
3232  /*
3233  * Cycle through temp directories for all non-default tablespaces.
3234  */
3235  spc_dir = AllocateDir("pg_tblspc");
3236 
3237  while ((spc_de = ReadDirExtended(spc_dir, "pg_tblspc", LOG)) != NULL)
3238  {
3239  if (strcmp(spc_de->d_name, ".") == 0 ||
3240  strcmp(spc_de->d_name, "..") == 0)
3241  continue;
3242 
3243  snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s/%s",
3245  RemovePgTempFilesInDir(temp_path, true, false);
3246 
3247  snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s",
3249  RemovePgTempRelationFiles(temp_path);
3250  }
3251 
3252  FreeDir(spc_dir);
3253 
3254  /*
3255  * In EXEC_BACKEND case there is a pgsql_tmp directory at the top level of
3256  * DataDir as well. However, that is *not* cleaned here because doing so
3257  * would create a race condition. It's done separately, earlier in
3258  * postmaster startup.
3259  */
3260 }
int FreeDir(DIR *dir)
Definition: fd.c:2906
static void RemovePgTempRelationFiles(const char *tsdirname)
Definition: fd.c:3338
void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok, bool unlink_all)
Definition: fd.c:3278
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2788
#define PG_TEMP_FILES_DIR
Definition: file_utils.h:57
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:33
char d_name[MAX_PATH]
Definition: dirent.h:15

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

Referenced by PostmasterMain(), and PostmasterStateMachine().

◆ RemovePgTempFilesInDir()

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

Definition at line 3278 of file fd.c.

3279 {
3280  DIR *temp_dir;
3281  struct dirent *temp_de;
3282  char rm_path[MAXPGPATH * 2];
3283 
3284  temp_dir = AllocateDir(tmpdirname);
3285 
3286  if (temp_dir == NULL && errno == ENOENT && missing_ok)
3287  return;
3288 
3289  while ((temp_de = ReadDirExtended(temp_dir, tmpdirname, LOG)) != NULL)
3290  {
3291  if (strcmp(temp_de->d_name, ".") == 0 ||
3292  strcmp(temp_de->d_name, "..") == 0)
3293  continue;
3294 
3295  snprintf(rm_path, sizeof(rm_path), "%s/%s",
3296  tmpdirname, temp_de->d_name);
3297 
3298  if (unlink_all ||
3299  strncmp(temp_de->d_name,
3301  strlen(PG_TEMP_FILE_PREFIX)) == 0)
3302  {
3303  PGFileType type = get_dirent_type(rm_path, temp_de, false, LOG);
3304 
3305  if (type == PGFILETYPE_ERROR)
3306  continue;
3307  else if (type == PGFILETYPE_DIR)
3308  {
3309  /* recursively remove contents, then directory itself */
3310  RemovePgTempFilesInDir(rm_path, false, true);
3311 
3312  if (rmdir(rm_path) < 0)
3313  ereport(LOG,
3315  errmsg("could not remove directory \"%s\": %m",
3316  rm_path)));
3317  }
3318  else
3319  {
3320  if (unlink(rm_path) < 0)
3321  ereport(LOG,
3323  errmsg("could not remove file \"%s\": %m",
3324  rm_path)));
3325  }
3326  }
3327  else
3328  ereport(LOG,
3329  (errmsg("unexpected file found in temporary-files directory: \"%s\"",
3330  rm_path)));
3331  }
3332 
3333  FreeDir(temp_dir);
3334 }
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:525
PGFileType
Definition: file_utils.h:19
@ PGFILETYPE_DIR
Definition: file_utils.h:23
@ PGFILETYPE_ERROR
Definition: file_utils.h:20
const char * type

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

Referenced by PostmasterMain(), and RemovePgTempFiles().

◆ RemovePgTempRelationFiles()

static void RemovePgTempRelationFiles ( const char *  tsdirname)
static

Definition at line 3338 of file fd.c.

3339 {
3340  DIR *ts_dir;
3341  struct dirent *de;
3342  char dbspace_path[MAXPGPATH * 2];
3343 
3344  ts_dir = AllocateDir(tsdirname);
3345 
3346  while ((de = ReadDirExtended(ts_dir, tsdirname, LOG)) != NULL)
3347  {
3348  /*
3349  * We're only interested in the per-database directories, which have
3350  * numeric names. Note that this code will also (properly) ignore "."
3351  * and "..".
3352  */
3353  if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
3354  continue;
3355 
3356  snprintf(dbspace_path, sizeof(dbspace_path), "%s/%s",
3357  tsdirname, de->d_name);
3358  RemovePgTempRelationFilesInDbspace(dbspace_path);
3359  }
3360 
3361  FreeDir(ts_dir);
3362 }
static void RemovePgTempRelationFilesInDbspace(const char *dbspacedirname)
Definition: fd.c:3366

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

Referenced by RemovePgTempFiles().

◆ RemovePgTempRelationFilesInDbspace()

static void RemovePgTempRelationFilesInDbspace ( const char *  dbspacedirname)
static

Definition at line 3366 of file fd.c.

3367 {
3368  DIR *dbspace_dir;
3369  struct dirent *de;
3370  char rm_path[MAXPGPATH * 2];
3371 
3372  dbspace_dir = AllocateDir(dbspacedirname);
3373 
3374  while ((de = ReadDirExtended(dbspace_dir, dbspacedirname, LOG)) != NULL)
3375  {
3376  if (!looks_like_temp_rel_name(de->d_name))
3377  continue;
3378 
3379  snprintf(rm_path, sizeof(rm_path), "%s/%s",
3380  dbspacedirname, de->d_name);
3381 
3382  if (unlink(rm_path) < 0)
3383  ereport(LOG,
3385  errmsg("could not remove file \"%s\": %m",
3386  rm_path)));
3387  }
3388 
3389  FreeDir(dbspace_dir);
3390 }
bool looks_like_temp_rel_name(const char *name)
Definition: fd.c:3394

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

Referenced by RemovePgTempRelationFiles().

◆ ReportTemporaryFileUsage()

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

Definition at line 1480 of file fd.c.

1481 {
1482  pgstat_report_tempfile(size);
1483 
1484  if (log_temp_files >= 0)
1485  {
1486  if ((size / 1024) >= log_temp_files)
1487  ereport(LOG,
1488  (errmsg("temporary file: path \"%s\", size %lu",
1489  path, (unsigned long) size)));
1490  }
1491 }
int log_temp_files
Definition: guc_tables.c:525
void pgstat_report_tempfile(size_t filesize)

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

Referenced by FileClose(), and PathNameDeleteTemporaryFile().

◆ reserveAllocatedDesc()

static bool reserveAllocatedDesc ( void  )
static

Definition at line 2453 of file fd.c.

2454 {
2455  AllocateDesc *newDescs;
2456  int newMax;
2457 
2458  /* Quick out if array already has a free slot. */
2460  return true;
2461 
2462  /*
2463  * If the array hasn't yet been created in the current process, initialize
2464  * it with FD_MINFREE / 3 elements. In many scenarios this is as many as
2465  * we will ever need, anyway. We don't want to look at max_safe_fds
2466  * immediately because set_max_safe_fds() may not have run yet.
2467  */
2468  if (allocatedDescs == NULL)
2469  {
2470  newMax = FD_MINFREE / 3;
2471  newDescs = (AllocateDesc *) malloc(newMax * sizeof(AllocateDesc));
2472  /* Out of memory already? Treat as fatal error. */
2473  if (newDescs == NULL)
2474  ereport(ERROR,
2475  (errcode(ERRCODE_OUT_OF_MEMORY),
2476  errmsg("out of memory")));
2477  allocatedDescs = newDescs;
2478  maxAllocatedDescs = newMax;
2479  return true;
2480  }
2481 
2482  /*
2483  * Consider enlarging the array beyond the initial allocation used above.
2484  * By the time this happens, max_safe_fds should be known accurately.
2485  *
2486  * We mustn't let allocated descriptors hog all the available FDs, and in
2487  * practice we'd better leave a reasonable number of FDs for VFD use. So
2488  * set the maximum to max_safe_fds / 3. (This should certainly be at
2489  * least as large as the initial size, FD_MINFREE / 3, so we aren't
2490  * tightening the restriction here.) Recall that "external" FDs are
2491  * allowed to consume another third of max_safe_fds.
2492  */
2493  newMax = max_safe_fds / 3;
2494  if (newMax > maxAllocatedDescs)
2495  {
2496  newDescs = (AllocateDesc *) realloc(allocatedDescs,
2497  newMax * sizeof(AllocateDesc));
2498  /* Treat out-of-memory as a non-fatal error. */
2499  if (newDescs == NULL)
2500  return false;
2501  allocatedDescs = newDescs;
2502  maxAllocatedDescs = newMax;
2503  return true;
2504  }
2505 
2506  /* Can't enlarge allocatedDescs[] any more. */
2507  return false;
2508 }
#define FD_MINFREE
Definition: fd.c:138

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

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

◆ ReserveExternalFD()

void ReserveExternalFD ( void  )

Definition at line 1173 of file fd.c.

1174 {
1175  /*
1176  * Release VFDs if needed to stay safe. Because we do this before
1177  * incrementing numExternalFDs, the final state will be as desired, i.e.,
1178  * nfile + numAllocatedDescs + numExternalFDs <= max_safe_fds.
1179  */
1180  ReleaseLruFiles();
1181 
1182  numExternalFDs++;
1183 }

References numExternalFDs, and ReleaseLruFiles().

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

◆ set_max_safe_fds()

void set_max_safe_fds ( void  )

Definition at line 996 of file fd.c.

997 {
998  int usable_fds;
999  int already_open;
1000 
1001  /*----------
1002  * We want to set max_safe_fds to
1003  * MIN(usable_fds, max_files_per_process - already_open)
1004  * less the slop factor for files that are opened without consulting
1005  * fd.c. This ensures that we won't exceed either max_files_per_process
1006  * or the experimentally-determined EMFILE limit.
1007  *----------
1008  */
1010  &usable_fds, &already_open);
1011 
1012  max_safe_fds = Min(usable_fds, max_files_per_process - already_open);
1013 
1014  /*
1015  * Take off the FDs reserved for system() etc.
1016  */
1018 
1019  /*
1020  * Make sure we still have enough to get by.
1021  */
1022  if (max_safe_fds < FD_MINFREE)
1023  ereport(FATAL,
1024  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
1025  errmsg("insufficient file descriptors available to start server process"),
1026  errdetail("System allows %d, server needs at least %d.",
1029 
1030  elog(DEBUG2, "max_safe_fds = %d, usable_fds = %d, already_open = %d",
1031  max_safe_fds, usable_fds, already_open);
1032 }
#define Min(x, y)
Definition: c.h:993
int errdetail(const char *fmt,...)
Definition: elog.c:1202
#define DEBUG2
Definition: elog.h:29
int max_files_per_process
Definition: fd.c:146
static void count_usable_fds(int max_to_probe, int *usable_fds, int *already_open)
Definition: fd.c:916
#define NUM_RESERVED_FDS
Definition: fd.c:129

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

Referenced by PostmasterMain().

◆ SetTempTablespaces()

void SetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2994 of file fd.c.

2995 {
2996  Assert(numSpaces >= 0);
2997  tempTableSpaces = tableSpaces;
2998  numTempTableSpaces = numSpaces;
2999 
3000  /*
3001  * Select a random starting point in the list. This is to minimize
3002  * conflicts between backends that are most likely sharing the same list
3003  * of temp tablespaces. Note that if we create multiple temp files in the
3004  * same transaction, we'll advance circularly through the list --- this
3005  * ensures that large temporary sort files are nicely spread across all
3006  * available tablespaces.
3007  */
3008  if (numSpaces > 1)
3010  0, numSpaces - 1);
3011  else
3012  nextTempTableSpace = 0;
3013 }
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition: pg_prng.c:144
pg_prng_state pg_global_prng_state
Definition: pg_prng.c:34

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

Referenced by assign_temp_tablespaces(), and PrepareTempTablespaces().

◆ SyncDataDirectory()

void SyncDataDirectory ( void  )

Definition at line 3489 of file fd.c.

3490 {
3491  bool xlog_is_symlink;
3492 
3493  /* We can skip this whole thing if fsync is disabled. */
3494  if (!enableFsync)
3495  return;
3496 
3497  /*
3498  * If pg_wal is a symlink, we'll need to recurse into it separately,
3499  * because the first walkdir below will ignore it.
3500  */
3501  xlog_is_symlink = false;
3502 
3503  {
3504  struct stat st;
3505 
3506  if (lstat("pg_wal", &st) < 0)
3507  ereport(LOG,
3509  errmsg("could not stat file \"%s\": %m",
3510  "pg_wal")));
3511  else if (S_ISLNK(st.st_mode))
3512  xlog_is_symlink = true;
3513  }
3514 
3515 #ifdef HAVE_SYNCFS
3517  {
3518  DIR *dir;
3519  struct dirent *de;
3520 
3521  /*
3522  * On Linux, we don't have to open every single file one by one. We
3523  * can use syncfs() to sync whole filesystems. We only expect
3524  * filesystem boundaries to exist where we tolerate symlinks, namely
3525  * pg_wal and the tablespaces, so we call syncfs() for each of those
3526  * directories.
3527  */
3528 
3529  /* Prepare to report progress syncing the data directory via syncfs. */
3531 
3532  /* Sync the top level pgdata directory. */
3533  do_syncfs(".");
3534  /* If any tablespaces are configured, sync each of those. */
3535  dir = AllocateDir("pg_tblspc");
3536  while ((de = ReadDirExtended(dir, "pg_tblspc", LOG)))
3537  {
3538  char path[MAXPGPATH];
3539 
3540  if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
3541  continue;
3542 
3543  snprintf(path, MAXPGPATH, "pg_tblspc/%s", de->d_name);
3544  do_syncfs(path);
3545  }
3546  FreeDir(dir);
3547  /* If pg_wal is a symlink, process that too. */
3548  if (xlog_is_symlink)
3549  do_syncfs("pg_wal");
3550  return;
3551  }
3552 #endif /* !HAVE_SYNCFS */
3553 
3554 #ifdef PG_FLUSH_DATA_WORKS
3555  /* Prepare to report progress of the pre-fsync phase. */
3557 
3558  /*
3559  * If possible, hint to the kernel that we're soon going to fsync the data
3560  * directory and its contents. Errors in this step are even less
3561  * interesting than normal, so log them only at DEBUG1.
3562  */
3563  walkdir(".", pre_sync_fname, false, DEBUG1);
3564  if (xlog_is_symlink)
3565  walkdir("pg_wal", pre_sync_fname, false, DEBUG1);
3566  walkdir("pg_tblspc", pre_sync_fname, true, DEBUG1);
3567 #endif
3568 
3569  /* Prepare to report progress syncing the data directory via fsync. */
3571 
3572  /*
3573  * Now we do the fsync()s in the same order.
3574  *
3575  * The main call ignores symlinks, so in addition to specially processing
3576  * pg_wal if it's a symlink, pg_tblspc has to be visited separately with
3577  * process_symlinks = true. Note that if there are any plain directories
3578  * in pg_tblspc, they'll get fsync'd twice. That's not an expected case
3579  * so we don't worry about optimizing it.
3580  */
3581  walkdir(".", datadir_fsync_fname, false, LOG);
3582  if (xlog_is_symlink)
3583  walkdir("pg_wal", datadir_fsync_fname, false, LOG);
3584  walkdir("pg_tblspc", datadir_fsync_fname, true, LOG);
3585 }
void begin_startup_progress_phase(void)
Definition: startup.c:352
#define DEBUG1
Definition: elog.h:30
int recovery_init_sync_method
Definition: fd.c:165
static void datadir_fsync_fname(const char *fname, bool isdir, int elevel)
Definition: fd.c:3704
@ DATA_DIR_SYNC_METHOD_SYNCFS
Definition: file_utils.h:30
#define lstat(path, sb)
Definition: win32_port.h:285
#define S_ISLNK(m)
Definition: win32_port.h:344

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

Referenced by StartupXLOG().

◆ TempTablespacePath()

void TempTablespacePath ( char *  path,
Oid  tablespace 
)

Definition at line 1731 of file fd.c.

1732 {
1733  /*
1734  * Identify the tempfile directory for this tablespace.
1735  *
1736  * If someone tries to specify pg_global, use pg_default instead.
1737  */
1738  if (tablespace == InvalidOid ||
1739  tablespace == DEFAULTTABLESPACE_OID ||
1740  tablespace == GLOBALTABLESPACE_OID)
1741  snprintf(path, MAXPGPATH, "base/%s", PG_TEMP_FILES_DIR);
1742  else
1743  {
1744  /* All other tablespaces are accessed via symlinks */
1745  snprintf(path, MAXPGPATH, "pg_tblspc/%u/%s/%s",
1748  }
1749 }
char * tablespace
Definition: pgbench.c:216

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

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

◆ TempTablespacesAreSet()

bool TempTablespacesAreSet ( void  )

Definition at line 3023 of file fd.c.

3024 {
3025  return (numTempTableSpaces >= 0);
3026 }

References numTempTableSpaces.

Referenced by GetTempTablespaces(), and PrepareTempTablespaces().

◆ unlink_if_exists_fname()

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

Definition at line 3717 of file fd.c.

3718 {
3719  if (isdir)
3720  {
3721  if (rmdir(fname) != 0 && errno != ENOENT)
3722  ereport(elevel,
3724  errmsg("could not remove directory \"%s\": %m", fname)));
3725  }
3726  else
3727  {
3728  /* Use PathNameDeleteTemporaryFile to report filesize */
3729  PathNameDeleteTemporaryFile(fname, false);
3730  }
3731 }
bool PathNameDeleteTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1884

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

Referenced by PathNameDeleteTemporaryDir().

◆ walkdir()

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

Definition at line 3603 of file fd.c.

3607 {
3608  DIR *dir;
3609  struct dirent *de;
3610 
3611  dir = AllocateDir(path);
3612 
3613  while ((de = ReadDirExtended(dir, path, elevel)) != NULL)
3614  {
3615  char subpath[MAXPGPATH * 2];
3616 
3618 
3619  if (strcmp(de->d_name, ".") == 0 ||
3620  strcmp(de->d_name, "..") == 0)
3621  continue;
3622 
3623  snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name);
3624 
3625  switch (get_dirent_type(subpath, de, process_symlinks, elevel))
3626  {
3627  case PGFILETYPE_REG:
3628  (*action) (subpath, false, elevel);
3629  break;
3630  case PGFILETYPE_DIR:
3631  walkdir(subpath, action, false, elevel);
3632  break;
3633  default:
3634 
3635  /*
3636  * Errors are already reported directly by get_dirent_type(),
3637  * and any remaining symlinks and unknown file types are
3638  * ignored.
3639  */
3640  break;
3641  }
3642  }
3643 
3644  FreeDir(dir); /* we ignore any error here */
3645 
3646  /*
3647  * It's important to fsync the destination directory itself as individual
3648  * file fsyncs don't guarantee that the directory entry for the file is
3649  * synced. However, skip this if AllocateDir failed; the action function
3650  * might not be robust against that.
3651  */
3652  if (dir)
3653  (*action) (path, true, elevel);
3654 }
@ PGFILETYPE_REG
Definition: file_utils.h:22
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:241
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121

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

Referenced by PathNameDeleteTemporaryDir(), and SyncDataDirectory().

Variable Documentation

◆ allocatedDescs

◆ data_sync_retry

bool data_sync_retry = false

Definition at line 162 of file fd.c.

Referenced by data_sync_elevel().

◆ have_xact_temporary_files

bool have_xact_temporary_files = false
static

Definition at line 228 of file fd.c.

Referenced by CleanupTempFiles(), and RegisterTemporaryFile().

◆ io_direct_flags

◆ max_files_per_process

int max_files_per_process = 1000

Definition at line 146 of file fd.c.

Referenced by set_max_safe_fds().

◆ max_safe_fds

int max_safe_fds = FD_MINFREE

Definition at line 159 of file fd.c.

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

◆ maxAllocatedDescs

int maxAllocatedDescs = 0
static

◆ nextTempTableSpace

int nextTempTableSpace = 0
static

Definition at line 290 of file fd.c.

Referenced by GetNextTempTableSpace(), and SetTempTablespaces().

◆ nfile

int nfile = 0
static

◆ numAllocatedDescs

◆ numExternalFDs

int numExternalFDs = 0
static

Definition at line 274 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 = DATA_DIR_SYNC_METHOD_FSYNC

Definition at line 165 of file fd.c.

Referenced by SyncDataDirectory().

◆ SizeVfdCache

Size SizeVfdCache = 0
static

◆ tempFileCounter

long tempFileCounter = 0
static

Definition at line 280 of file fd.c.

Referenced by OpenTemporaryFileInTablespace().

◆ temporary_files_size

uint64 temporary_files_size = 0
static

Definition at line 236 of file fd.c.

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

◆ tempTableSpaces

Oid* tempTableSpaces = NULL
static

◆ VfdCache