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

Go to the source code of this file.

Data Structures

struct  vfd
 
struct  AllocateDesc
 

Macros

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

Typedefs

typedef struct vfd Vfd
 

Enumerations

enum  AllocateDescKind { AllocateDescFile, AllocateDescPipe, AllocateDescDir, AllocateDescRawFD }
 

Functions

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

Variables

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

Macro Definition Documentation

◆ DO_DB

◆ FD_CLOSE_AT_EOXACT

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

Definition at line 187 of file fd.c.

Referenced by CleanupTempFiles(), and RegisterTemporaryFile().

◆ FD_DELETE_AT_CLOSE

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

Definition at line 186 of file fd.c.

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

◆ FD_MINFREE

#define FD_MINFREE   10

Definition at line 125 of file fd.c.

Referenced by reserveAllocatedDesc(), and set_max_safe_fds().

◆ FD_TEMP_FILE_LIMIT

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

◆ FileIsNotOpen

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

◆ FileIsValid

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

◆ FilePosIsUnknown

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

Definition at line 183 of file fd.c.

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

◆ FileUnknownPos

#define FileUnknownPos   ((off_t) -1)

Definition at line 182 of file fd.c.

Referenced by FileRead(), and FileWrite().

◆ NUM_RESERVED_FDS

#define NUM_RESERVED_FDS   10

Definition at line 119 of file fd.c.

Referenced by set_max_safe_fds().

◆ PG_FILE_MODE_DEFAULT

#define PG_FILE_MODE_DEFAULT   (S_IRUSR | S_IWUSR)

Definition at line 131 of file fd.c.

Referenced by BasicOpenFile(), OpenTransientFile(), and PathNameOpenFile().

◆ VFD_CLOSED

#define VFD_CLOSED   (-1)

Definition at line 169 of file fd.c.

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

Typedef Documentation

◆ Vfd

typedef struct vfd Vfd

Enumeration Type Documentation

◆ AllocateDescKind

Enumerator
AllocateDescFile 
AllocateDescPipe 
AllocateDescDir 
AllocateDescRawFD 

Definition at line 237 of file fd.c.

Function Documentation

◆ AllocateDir()

DIR* AllocateDir ( const char *  dirname)

Definition at line 2607 of file fd.c.

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

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

2608 {
2609  DIR *dir;
2610 
2611  DO_DB(elog(LOG, "AllocateDir: Allocated %d (%s)",
2612  numAllocatedDescs, dirname));
2613 
2614  /* Can we allocate another non-virtual FD? */
2615  if (!reserveAllocatedDesc())
2616  ereport(ERROR,
2617  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2618  errmsg("exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"",
2619  maxAllocatedDescs, dirname)));
2620 
2621  /* Close excess kernel FDs. */
2622  ReleaseLruFiles();
2623 
2624 TryAgain:
2625  if ((dir = opendir(dirname)) != NULL)
2626  {
2628 
2629  desc->kind = AllocateDescDir;
2630  desc->desc.dir = dir;
2633  return desc->desc.dir;
2634  }
2635 
2636  if (errno == EMFILE || errno == ENFILE)
2637  {
2638  int save_errno = errno;
2639 
2640  ereport(LOG,
2641  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2642  errmsg("out of file descriptors: %m; release and retry")));
2643  errno = 0;
2644  if (ReleaseLruFile())
2645  goto TryAgain;
2646  errno = save_errno;
2647  }
2648 
2649  return NULL;
2650 }
static AllocateDesc * allocatedDescs
Definition: fd.c:259
DIR * dir
Definition: fd.c:252
#define DO_DB(A)
Definition: fd.c:165
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool reserveAllocatedDesc(void)
Definition: fd.c:2280
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:247
static bool ReleaseLruFile(void)
Definition: fd.c:1165
Definition: dirent.c:25
#define ERROR
Definition: elog.h:43
DIR * opendir(const char *)
Definition: dirent.c:33
#define ereport(elevel, rest)
Definition: elog.h:122
static void ReleaseLruFiles(void)
Definition: fd.c:1187
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:642
SubTransactionId create_subid
Definition: fd.c:248
int errmsg(const char *fmt,...)
Definition: elog.c:797
union AllocateDesc::@27 desc
#define elog
Definition: elog.h:219
static int maxAllocatedDescs
Definition: fd.c:258
static int numAllocatedDescs
Definition: fd.c:257

◆ AllocateFile()

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

Definition at line 2353 of file fd.c.

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

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

2354 {
2355  FILE *file;
2356 
2357  DO_DB(elog(LOG, "AllocateFile: Allocated %d (%s)",
2359 
2360  /* Can we allocate another non-virtual FD? */
2361  if (!reserveAllocatedDesc())
2362  ereport(ERROR,
2363  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2364  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2365  maxAllocatedDescs, name)));
2366 
2367  /* Close excess kernel FDs. */
2368  ReleaseLruFiles();
2369 
2370 TryAgain:
2371  if ((file = fopen(name, mode)) != NULL)
2372  {
2374 
2375  desc->kind = AllocateDescFile;
2376  desc->desc.file = file;
2379  return desc->desc.file;
2380  }
2381 
2382  if (errno == EMFILE || errno == ENFILE)
2383  {
2384  int save_errno = errno;
2385 
2386  ereport(LOG,
2387  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2388  errmsg("out of file descriptors: %m; release and retry")));
2389  errno = 0;
2390  if (ReleaseLruFile())
2391  goto TryAgain;
2392  errno = save_errno;
2393  }
2394 
2395  return NULL;
2396 }
static AllocateDesc * allocatedDescs
Definition: fd.c:259
#define DO_DB(A)
Definition: fd.c:165
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool reserveAllocatedDesc(void)
Definition: fd.c:2280
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:247
static bool ReleaseLruFile(void)
Definition: fd.c:1165
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
static void ReleaseLruFiles(void)
Definition: fd.c:1187
FILE * file
Definition: fd.c:251
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:642
SubTransactionId create_subid
Definition: fd.c:248
const char * name
Definition: encode.c:521
int errmsg(const char *fmt,...)
Definition: elog.c:797
union AllocateDesc::@27 desc
#define elog
Definition: elog.h:219
static int maxAllocatedDescs
Definition: fd.c:258
static int numAllocatedDescs
Definition: fd.c:257

◆ AllocateVfd()

static File AllocateVfd ( void  )
static

Definition at line 1197 of file fd.c.

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

Referenced by PathNameOpenFilePerm().

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

◆ AtEOSubXact_Files()

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

Definition at line 2889 of file fd.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

2891 {
2892  Index i;
2893 
2894  for (i = 0; i < numAllocatedDescs; i++)
2895  {
2896  if (allocatedDescs[i].create_subid == mySubid)
2897  {
2898  if (isCommit)
2899  allocatedDescs[i].create_subid = parentSubid;
2900  else
2901  {
2902  /* have to recheck the item after FreeDesc (ugly) */
2903  FreeDesc(&allocatedDescs[i--]);
2904  }
2905  }
2906  }
2907 }
static AllocateDesc * allocatedDescs
Definition: fd.c:259
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2506
unsigned int Index
Definition: c.h:431
SubTransactionId create_subid
Definition: fd.c:248
int i
static int numAllocatedDescs
Definition: fd.c:257

◆ AtEOXact_Files()

void AtEOXact_Files ( void  )

Definition at line 2920 of file fd.c.

References CleanupTempFiles(), numTempTableSpaces, and tempTableSpaces.

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

2921 {
2922  CleanupTempFiles(false);
2923  tempTableSpaces = NULL;
2924  numTempTableSpaces = -1;
2925 }
static int numTempTableSpaces
Definition: fd.c:272
static void CleanupTempFiles(bool isProcExit)
Definition: fd.c:2949
static Oid * tempTableSpaces
Definition: fd.c:271

◆ AtProcExit_Files()

static void AtProcExit_Files ( int  code,
Datum  arg 
)
static

Definition at line 2934 of file fd.c.

References CleanupTempFiles().

Referenced by InitFileAccess().

2935 {
2936  CleanupTempFiles(true);
2937 }
static void CleanupTempFiles(bool isProcExit)
Definition: fd.c:2949

◆ BasicOpenFile()

int BasicOpenFile ( const char *  fileName,
int  fileFlags 
)

Definition at line 939 of file fd.c.

References BasicOpenFilePerm(), and PG_FILE_MODE_DEFAULT.

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

940 {
941  return BasicOpenFilePerm(fileName, fileFlags, PG_FILE_MODE_DEFAULT);
942 }
#define PG_FILE_MODE_DEFAULT
Definition: fd.c:131
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:961

◆ BasicOpenFilePerm()

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

Definition at line 961 of file fd.c.

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

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

962 {
963  int fd;
964 
965 tryAgain:
966  fd = open(fileName, fileFlags, fileMode);
967 
968  if (fd >= 0)
969  return fd; /* success! */
970 
971  if (errno == EMFILE || errno == ENFILE)
972  {
973  int save_errno = errno;
974 
975  ereport(LOG,
976  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
977  errmsg("out of file descriptors: %m; release and retry")));
978  errno = 0;
979  if (ReleaseLruFile())
980  goto tryAgain;
981  errno = save_errno;
982  }
983 
984  return -1; /* failure */
985 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static bool ReleaseLruFile(void)
Definition: fd.c:1165
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ CleanupTempFiles()

static void CleanupTempFiles ( bool  isProcExit)
static

Definition at line 2949 of file fd.c.

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

Referenced by AtEOXact_Files(), and AtProcExit_Files().

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

◆ closeAllVfds()

void closeAllVfds ( void  )

Definition at line 2784 of file fd.c.

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

Referenced by standard_ProcessUtility().

2785 {
2786  Index i;
2787 
2788  if (SizeVfdCache > 0)
2789  {
2790  Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
2791  for (i = 1; i < SizeVfdCache; i++)
2792  {
2793  if (!FileIsNotOpen(i))
2794  LruDelete(i);
2795  }
2796  }
2797 }
static Size SizeVfdCache
Definition: fd.c:212
static void LruDelete(File file)
Definition: fd.c:1028
#define FileIsNotOpen(file)
Definition: fd.c:174
unsigned int Index
Definition: c.h:431
#define Assert(condition)
Definition: c.h:688
int i

◆ ClosePipeStream()

int ClosePipeStream ( FILE *  file)

Definition at line 2755 of file fd.c.

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

Referenced by ClosePipeToProgram(), and pg_import_system_collations().

2756 {
2757  int i;
2758 
2759  DO_DB(elog(LOG, "ClosePipeStream: Allocated %d", numAllocatedDescs));
2760 
2761  /* Remove file from list of allocated files, if it's present */
2762  for (i = numAllocatedDescs; --i >= 0;)
2763  {
2764  AllocateDesc *desc = &allocatedDescs[i];
2765 
2766  if (desc->kind == AllocateDescPipe && desc->desc.file == file)
2767  return FreeDesc(desc);
2768  }
2769 
2770  /* Only get here if someone passes us a file not in allocatedDescs */
2771  elog(WARNING, "file passed to ClosePipeStream was not obtained from OpenPipeStream");
2772 
2773  return pclose(file);
2774 }
static AllocateDesc * allocatedDescs
Definition: fd.c:259
#define DO_DB(A)
Definition: fd.c:165
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:247
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2506
#define WARNING
Definition: elog.h:40
FILE * file
Definition: fd.c:251
union AllocateDesc::@27 desc
int i
#define elog
Definition: elog.h:219
static int numAllocatedDescs
Definition: fd.c:257

◆ CloseTransientFile()

int CloseTransientFile ( int  fd)

Definition at line 2573 of file fd.c.

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

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

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

◆ count_usable_fds()

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

Definition at line 812 of file fd.c.

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

Referenced by set_max_safe_fds().

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

◆ datadir_fsync_fname()

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

Definition at line 3433 of file fd.c.

References fsync_fname_ext().

Referenced by SyncDataDirectory().

3434 {
3435  /*
3436  * We want to silently ignoring errors about unreadable files. Pass that
3437  * desire on to fsync_fname_ext().
3438  */
3439  fsync_fname_ext(fname, isdir, true, elevel);
3440 }
static int elevel
Definition: vacuumlazy.c:136
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3468

◆ Delete()

static void Delete ( File  file)
static

Definition at line 1009 of file fd.c.

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

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

1010 {
1011  Vfd *vfdP;
1012 
1013  Assert(file != 0);
1014 
1015  DO_DB(elog(LOG, "Delete %d (%s)",
1016  file, VfdCache[file].fileName));
1017  DO_DB(_dump_lru());
1018 
1019  vfdP = &VfdCache[file];
1020 
1023 
1024  DO_DB(_dump_lru());
1025 }
File lruLessRecently
Definition: fd.c:197
#define DO_DB(A)
Definition: fd.c:165
static Vfd * VfdCache
Definition: fd.c:211
#define LOG
Definition: elog.h:26
Definition: fd.c:190
#define Assert(condition)
Definition: c.h:688
File lruMoreRecently
Definition: fd.c:196
#define elog
Definition: elog.h:219

◆ durable_link_or_rename()

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

Definition at line 727 of file fd.c.

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

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

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

◆ durable_rename()

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

Definition at line 608 of file fd.c.

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

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

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

◆ durable_unlink()

int durable_unlink ( const char *  fname,
int  elevel 
)

Definition at line 691 of file fd.c.

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

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

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

◆ FileAccess()

static int FileAccess ( File  file)
static

Definition at line 1275 of file fd.c.

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

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

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

◆ FileClose()

void FileClose ( File  file)

Definition at line 1749 of file fd.c.

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

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

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

◆ FileGetRawDesc()

int FileGetRawDesc ( File  file)

Definition at line 2239 of file fd.c.

References Assert, vfd::fd, and FileIsValid.

2240 {
2241  Assert(FileIsValid(file));
2242  return VfdCache[file].fd;
2243 }
static Vfd * VfdCache
Definition: fd.c:211
int fd
Definition: fd.c:192
#define FileIsValid(file)
Definition: fd.c:171
#define Assert(condition)
Definition: c.h:688

◆ FileGetRawFlags()

int FileGetRawFlags ( File  file)

Definition at line 2249 of file fd.c.

References Assert, vfd::fileFlags, and FileIsValid.

2250 {
2251  Assert(FileIsValid(file));
2252  return VfdCache[file].fileFlags;
2253 }
static Vfd * VfdCache
Definition: fd.c:211
#define FileIsValid(file)
Definition: fd.c:171
#define Assert(condition)
Definition: c.h:688
int fileFlags
Definition: fd.c:202

◆ FileGetRawMode()

mode_t FileGetRawMode ( File  file)

Definition at line 2259 of file fd.c.

References Assert, FileIsValid, and vfd::fileMode.

2260 {
2261  Assert(FileIsValid(file));
2262  return VfdCache[file].fileMode;
2263 }
static Vfd * VfdCache
Definition: fd.c:211
mode_t fileMode
Definition: fd.c:203
#define FileIsValid(file)
Definition: fd.c:171
#define Assert(condition)
Definition: c.h:688

◆ FileGetSize()

off_t FileGetSize ( File  file)

Definition at line 2269 of file fd.c.

References Assert, FileIsValid, and vfd::fileSize.

Referenced by BufFileSize().

2270 {
2271  Assert(FileIsValid(file));
2272  return VfdCache[file].fileSize;
2273 }
static Vfd * VfdCache
Definition: fd.c:211
off_t fileSize
Definition: fd.c:199
#define FileIsValid(file)
Definition: fd.c:171
#define Assert(condition)
Definition: c.h:688

◆ FilePathName()

char* FilePathName ( File  file)

Definition at line 2223 of file fd.c.

References Assert, FileIsValid, and vfd::fileName.

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

2224 {
2225  Assert(FileIsValid(file));
2226 
2227  return VfdCache[file].fileName;
2228 }
static Vfd * VfdCache
Definition: fd.c:211
char * fileName
Definition: fd.c:200
#define FileIsValid(file)
Definition: fd.c:171
#define Assert(condition)
Definition: c.h:688

◆ FilePrefetch()

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

Definition at line 1839 of file fd.c.

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

Referenced by mdprefetch().

1840 {
1841 #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
1842  int returnCode;
1843 
1844  Assert(FileIsValid(file));
1845 
1846  DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " %d",
1847  file, VfdCache[file].fileName,
1848  (int64) offset, amount));
1849 
1850  returnCode = FileAccess(file);
1851  if (returnCode < 0)
1852  return returnCode;
1853 
1854  pgstat_report_wait_start(wait_event_info);
1855  returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
1856  POSIX_FADV_WILLNEED);
1858 
1859  return returnCode;
1860 #else
1861  Assert(FileIsValid(file));
1862  return 0;
1863 #endif
1864 }
#define DO_DB(A)
Definition: fd.c:165
static Vfd * VfdCache
Definition: fd.c:211
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1260
#define FileIsValid(file)
Definition: fd.c:171
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:688
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
#define INT64_FORMAT
Definition: c.h:356
#define elog
Definition: elog.h:219

◆ FileRead()

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

Definition at line 1894 of file fd.c.

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

Referenced by BufFileLoadBuffer(), and mdread().

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

◆ FileSeek()

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

Definition at line 2100 of file fd.c.

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

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

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

◆ FileSync()

int FileSync ( File  file,
uint32  wait_event_info 
)

Definition at line 2079 of file fd.c.

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

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

2080 {
2081  int returnCode;
2082 
2083  Assert(FileIsValid(file));
2084 
2085  DO_DB(elog(LOG, "FileSync: %d (%s)",
2086  file, VfdCache[file].fileName));
2087 
2088  returnCode = FileAccess(file);
2089  if (returnCode < 0)
2090  return returnCode;
2091 
2092  pgstat_report_wait_start(wait_event_info);
2093  returnCode = pg_fsync(VfdCache[file].fd);
2095 
2096  return returnCode;
2097 }
#define DO_DB(A)
Definition: fd.c:165
static Vfd * VfdCache
Definition: fd.c:211
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1260
#define FileIsValid(file)
Definition: fd.c:171
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:688
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
int pg_fsync(int fd)
Definition: fd.c:348
#define elog
Definition: elog.h:219

◆ FileTruncate()

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

Definition at line 2188 of file fd.c.

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

Referenced by mdtruncate().

2189 {
2190  int returnCode;
2191 
2192  Assert(FileIsValid(file));
2193 
2194  DO_DB(elog(LOG, "FileTruncate %d (%s)",
2195  file, VfdCache[file].fileName));
2196 
2197  returnCode = FileAccess(file);
2198  if (returnCode < 0)
2199  return returnCode;
2200 
2201  pgstat_report_wait_start(wait_event_info);
2202  returnCode = ftruncate(VfdCache[file].fd, offset);
2204 
2205  if (returnCode == 0 && VfdCache[file].fileSize > offset)
2206  {
2207  /* adjust our state for truncation of a temp file */
2208  Assert(VfdCache[file].fdstate & FD_TEMP_FILE_LIMIT);
2209  temporary_files_size -= VfdCache[file].fileSize - offset;
2210  VfdCache[file].fileSize = offset;
2211  }
2212 
2213  return returnCode;
2214 }
#define FD_TEMP_FILE_LIMIT
Definition: fd.c:188
#define DO_DB(A)
Definition: fd.c:165
static Vfd * VfdCache
Definition: fd.c:211
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1260
off_t fileSize
Definition: fd.c:199
#define FileIsValid(file)
Definition: fd.c:171
static uint64 temporary_files_size
Definition: fd.c:231
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:688
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
#define elog
Definition: elog.h:219
#define ftruncate(a, b)
Definition: win32_port.h:60

◆ FileWrite()

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

Definition at line 1958 of file fd.c.

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

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

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

◆ FileWriteback()

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

Definition at line 1867 of file fd.c.

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

Referenced by mdwriteback().

1868 {
1869  int returnCode;
1870 
1871  Assert(FileIsValid(file));
1872 
1873  DO_DB(elog(LOG, "FileWriteback: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
1874  file, VfdCache[file].fileName,
1875  (int64) offset, (int64) nbytes));
1876 
1877  /*
1878  * Caution: do not call pg_flush_data with nbytes = 0, it could trash the
1879  * file's seek position. We prefer to define that as a no-op here.
1880  */
1881  if (nbytes <= 0)
1882  return;
1883 
1884  returnCode = FileAccess(file);
1885  if (returnCode < 0)
1886  return;
1887 
1888  pgstat_report_wait_start(wait_event_info);
1889  pg_flush_data(VfdCache[file].fd, offset, nbytes);
1891 }
#define DO_DB(A)
Definition: fd.c:165
static Vfd * VfdCache
Definition: fd.c:211
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1260
void pg_flush_data(int fd, off_t offset, off_t nbytes)
Definition: fd.c:422
#define FileIsValid(file)
Definition: fd.c:171
static int FileAccess(File file)
Definition: fd.c:1275
#define Assert(condition)
Definition: c.h:688
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1236
#define INT64_FORMAT
Definition: c.h:356
#define elog
Definition: elog.h:219

◆ FreeDesc()

static int FreeDesc ( AllocateDesc desc)
static

Definition at line 2506 of file fd.c.

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

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

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

◆ FreeDir()

int FreeDir ( DIR dir)

Definition at line 2725 of file fd.c.

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

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

2726 {
2727  int i;
2728 
2729  /* Nothing to do if AllocateDir failed */
2730  if (dir == NULL)
2731  return 0;
2732 
2733  DO_DB(elog(LOG, "FreeDir: Allocated %d", numAllocatedDescs));
2734 
2735  /* Remove dir from list of allocated dirs, if it's present */
2736  for (i = numAllocatedDescs; --i >= 0;)
2737  {
2738  AllocateDesc *desc = &allocatedDescs[i];
2739 
2740  if (desc->kind == AllocateDescDir && desc->desc.dir == dir)
2741  return FreeDesc(desc);
2742  }
2743 
2744  /* Only get here if someone passes us a dir not in allocatedDescs */
2745  elog(WARNING, "dir passed to FreeDir was not obtained from AllocateDir");
2746 
2747  return closedir(dir);
2748 }
static AllocateDesc * allocatedDescs
Definition: fd.c:259
DIR * dir
Definition: fd.c:252
#define DO_DB(A)
Definition: fd.c:165
int closedir(DIR *)
Definition: dirent.c:111
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:247
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2506
#define WARNING
Definition: elog.h:40
union AllocateDesc::@27 desc
int i
#define elog
Definition: elog.h:219
static int numAllocatedDescs
Definition: fd.c:257

◆ FreeFile()

int FreeFile ( FILE *  file)

Definition at line 2545 of file fd.c.

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

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

2546 {
2547  int i;
2548 
2549  DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedDescs));
2550 
2551  /* Remove file from list of allocated files, if it's present */
2552  for (i = numAllocatedDescs; --i >= 0;)
2553  {
2554  AllocateDesc *desc = &allocatedDescs[i];
2555 
2556  if (desc->kind == AllocateDescFile && desc->desc.file == file)
2557  return FreeDesc(desc);
2558  }
2559 
2560  /* Only get here if someone passes us a file not in allocatedDescs */
2561  elog(WARNING, "file passed to FreeFile was not obtained from AllocateFile");
2562 
2563  return fclose(file);
2564 }
static AllocateDesc * allocatedDescs
Definition: fd.c:259
#define DO_DB(A)
Definition: fd.c:165
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:247
static int FreeDesc(AllocateDesc *desc)
Definition: fd.c:2506
#define WARNING
Definition: elog.h:40
FILE * file
Definition: fd.c:251
union AllocateDesc::@27 desc
int i
#define elog
Definition: elog.h:219
static int numAllocatedDescs
Definition: fd.c:257

◆ FreeVfd()

static void FreeVfd ( File  file)
static

Definition at line 1255 of file fd.c.

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

Referenced by FileClose(), and PathNameOpenFilePerm().

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

◆ fsync_fname()

void fsync_fname ( const char *  fname,
bool  isdir 
)

◆ fsync_fname_ext()

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

Definition at line 3468 of file fd.c.

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

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

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

◆ fsync_parent_path()

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

Definition at line 3538 of file fd.c.

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

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

3539 {
3540  char parentpath[MAXPGPATH];
3541 
3542  strlcpy(parentpath, fname, MAXPGPATH);
3543  get_parent_directory(parentpath);
3544 
3545  /*
3546  * get_parent_directory() returns an empty string if the input argument is
3547  * just a file name (see comments in path.c), so handle that as being the
3548  * current directory.
3549  */
3550  if (strlen(parentpath) == 0)
3551  strlcpy(parentpath, ".", MAXPGPATH);
3552 
3553  if (fsync_fname_ext(parentpath, true, false, elevel) != 0)
3554  return -1;
3555 
3556  return 0;
3557 }
#define MAXPGPATH
void get_parent_directory(char *path)
Definition: path.c:854
static int elevel
Definition: vacuumlazy.c:136
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
Definition: fd.c:3468

◆ GetNextTempTableSpace()

Oid GetNextTempTableSpace ( void  )

Definition at line 2868 of file fd.c.

References InvalidOid, nextTempTableSpace, numTempTableSpaces, and tempTableSpaces.

Referenced by GetDefaultTablespace(), and OpenTemporaryFile().

2869 {
2870  if (numTempTableSpaces > 0)
2871  {
2872  /* Advance nextTempTableSpace counter with wraparound */
2874  nextTempTableSpace = 0;
2876  }
2877  return InvalidOid;
2878 }
static int numTempTableSpaces
Definition: fd.c:272
static int nextTempTableSpace
Definition: fd.c:273
#define InvalidOid
Definition: postgres_ext.h:36
static Oid * tempTableSpaces
Definition: fd.c:271

◆ GetTempTablespaces()

int GetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2850 of file fd.c.

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

Referenced by SharedFileSetInit().

2851 {
2852  int i;
2853 
2855  for (i = 0; i < numTempTableSpaces && i < numSpaces; ++i)
2856  tableSpaces[i] = tempTableSpaces[i];
2857 
2858  return i;
2859 }
static int numTempTableSpaces
Definition: fd.c:272
bool TempTablespacesAreSet(void)
Definition: fd.c:2838
#define Assert(condition)
Definition: c.h:688
static Oid * tempTableSpaces
Definition: fd.c:271
int i

◆ InitFileAccess()

void InitFileAccess ( void  )

Definition at line 779 of file fd.c.

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

Referenced by BaseInit().

780 {
781  Assert(SizeVfdCache == 0); /* call me only once */
782 
783  /* initialize cache header entry */
784  VfdCache = (Vfd *) malloc(sizeof(Vfd));
785  if (VfdCache == NULL)
786  ereport(FATAL,
787  (errcode(ERRCODE_OUT_OF_MEMORY),
788  errmsg("out of memory")));
789 
790  MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
792 
793  SizeVfdCache = 1;
794 
795  /* register proc-exit hook to ensure temp files are dropped at exit */
797 }
static void AtProcExit_Files(int code, Datum arg)
Definition: fd.c:2934
static Size SizeVfdCache
Definition: fd.c:212
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:299
static Vfd * VfdCache
Definition: fd.c:211
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:897
#define malloc(a)
Definition: header.h:50
#define FATAL
Definition: elog.h:52
Definition: fd.c:190
int fd
Definition: fd.c:192
#define ereport(elevel, rest)
Definition: elog.h:122
#define VFD_CLOSED
Definition: fd.c:169
#define Assert(condition)
Definition: c.h:688
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ Insert()

static void Insert ( File  file)
static

Definition at line 1069 of file fd.c.

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

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

1070 {
1071  Vfd *vfdP;
1072 
1073  Assert(file != 0);
1074 
1075  DO_DB(elog(LOG, "Insert %d (%s)",
1076  file, VfdCache[file].fileName));
1077  DO_DB(_dump_lru());
1078 
1079  vfdP = &VfdCache[file];
1080 
1081  vfdP->lruMoreRecently = 0;
1083  VfdCache[0].lruLessRecently = file;
1085 
1086  DO_DB(_dump_lru());
1087 }
File lruLessRecently
Definition: fd.c:197
#define DO_DB(A)
Definition: fd.c:165
static Vfd * VfdCache
Definition: fd.c:211
#define LOG
Definition: elog.h:26
Definition: fd.c:190
#define Assert(condition)
Definition: c.h:688
File lruMoreRecently
Definition: fd.c:196
#define elog
Definition: elog.h:219

◆ looks_like_temp_rel_name()

static bool looks_like_temp_rel_name ( const char *  name)
static

Definition at line 3196 of file fd.c.

References forkname_chars().

Referenced by RemovePgTempRelationFilesInDbspace().

3197 {
3198  int pos;
3199  int savepos;
3200 
3201  /* Must start with "t". */
3202  if (name[0] != 't')
3203  return false;
3204 
3205  /* Followed by a non-empty string of digits and then an underscore. */
3206  for (pos = 1; isdigit((unsigned char) name[pos]); ++pos)
3207  ;
3208  if (pos == 1 || name[pos] != '_')
3209  return false;
3210 
3211  /* Followed by another nonempty string of digits. */
3212  for (savepos = ++pos; isdigit((unsigned char) name[pos]); ++pos)
3213  ;
3214  if (savepos == pos)
3215  return false;
3216 
3217  /* We might have _forkname or .segment or both. */
3218  if (name[pos] == '_')
3219  {
3220  int forkchar = forkname_chars(&name[pos + 1], NULL);
3221 
3222  if (forkchar <= 0)
3223  return false;
3224  pos += forkchar + 1;
3225  }
3226  if (name[pos] == '.')
3227  {
3228  int segchar;
3229 
3230  for (segchar = 1; isdigit((unsigned char) name[pos + segchar]); ++segchar)
3231  ;
3232  if (segchar <= 1)
3233  return false;
3234  pos += segchar;
3235  }
3236 
3237  /* Now we should be at the end. */
3238  if (name[pos] != '\0')
3239  return false;
3240  return true;
3241 }
int forkname_chars(const char *str, ForkNumber *fork)
Definition: relpath.c:79
const char * name
Definition: encode.c:521

◆ LruDelete()

static void LruDelete ( File  file)
static

Definition at line 1028 of file fd.c.

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

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

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

◆ LruInsert()

static int LruInsert ( File  file)
static

Definition at line 1091 of file fd.c.

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

Referenced by FileAccess().

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

◆ OpenPipeStream()

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

Definition at line 2452 of file fd.c.

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

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

2453 {
2454  FILE *file;
2455 
2456  DO_DB(elog(LOG, "OpenPipeStream: Allocated %d (%s)",
2457  numAllocatedDescs, command));
2458 
2459  /* Can we allocate another non-virtual FD? */
2460  if (!reserveAllocatedDesc())
2461  ereport(ERROR,
2462  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2463  errmsg("exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"",
2464  maxAllocatedDescs, command)));
2465 
2466  /* Close excess kernel FDs. */
2467  ReleaseLruFiles();
2468 
2469 TryAgain:
2470  fflush(stdout);
2471  fflush(stderr);
2472  errno = 0;
2473  if ((file = popen(command, mode)) != NULL)
2474  {
2476 
2477  desc->kind = AllocateDescPipe;
2478  desc->desc.file = file;
2481  return desc->desc.file;
2482  }
2483 
2484  if (errno == EMFILE || errno == ENFILE)
2485  {
2486  int save_errno = errno;
2487 
2488  ereport(LOG,
2489  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2490  errmsg("out of file descriptors: %m; release and retry")));
2491  errno = 0;
2492  if (ReleaseLruFile())
2493  goto TryAgain;
2494  errno = save_errno;
2495  }
2496 
2497  return NULL;
2498 }
static AllocateDesc * allocatedDescs
Definition: fd.c:259
#define DO_DB(A)
Definition: fd.c:165
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool reserveAllocatedDesc(void)
Definition: fd.c:2280
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:247
static bool ReleaseLruFile(void)
Definition: fd.c:1165
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
static void ReleaseLruFiles(void)
Definition: fd.c:1187
FILE * file
Definition: fd.c:251
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:642
SubTransactionId create_subid
Definition: fd.c:248
int errmsg(const char *fmt,...)
Definition: elog.c:797
union AllocateDesc::@27 desc
#define elog
Definition: elog.h:219
static int maxAllocatedDescs
Definition: fd.c:258
static int numAllocatedDescs
Definition: fd.c:257

◆ OpenTemporaryFile()

File OpenTemporaryFile ( bool  interXact)

Definition at line 1500 of file fd.c.

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

Referenced by BufFileCreateTemp(), and extendBufFile().

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

◆ OpenTemporaryFileInTablespace()

static File OpenTemporaryFileInTablespace ( Oid  tblspcOid,
bool  rejectError 
)
static

Definition at line 1578 of file fd.c.

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

Referenced by OpenTemporaryFile().

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

◆ OpenTransientFile()

◆ OpenTransientFilePerm()

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

Definition at line 2412 of file fd.c.

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

Referenced by be_lo_export(), and OpenTransientFile().

2413 {
2414  int fd;
2415 
2416  DO_DB(elog(LOG, "OpenTransientFile: Allocated %d (%s)",
2417  numAllocatedDescs, fileName));
2418 
2419  /* Can we allocate another non-virtual FD? */
2420  if (!reserveAllocatedDesc())
2421  ereport(ERROR,
2422  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
2423  errmsg("exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"",
2424  maxAllocatedDescs, fileName)));
2425 
2426  /* Close excess kernel FDs. */
2427  ReleaseLruFiles();
2428 
2429  fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
2430 
2431  if (fd >= 0)
2432  {
2434 
2435  desc->kind = AllocateDescRawFD;
2436  desc->desc.fd = fd;
2439 
2440  return fd;
2441  }
2442 
2443  return -1; /* failure */
2444 }
static AllocateDesc * allocatedDescs
Definition: fd.c:259
#define DO_DB(A)
Definition: fd.c:165
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool reserveAllocatedDesc(void)
Definition: fd.c:2280
#define LOG
Definition: elog.h:26
AllocateDescKind kind
Definition: fd.c:247
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
static void ReleaseLruFiles(void)
Definition: fd.c:1187
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:642
SubTransactionId create_subid
Definition: fd.c:248
int fd
Definition: fd.c:253
int errmsg(const char *fmt,...)
Definition: elog.c:797
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:961
union AllocateDesc::@27 desc
#define elog
Definition: elog.h:219
static int maxAllocatedDescs
Definition: fd.c:258
static int numAllocatedDescs
Definition: fd.c:257

◆ PathNameCreateTemporaryDir()

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

Definition at line 1436 of file fd.c.

References ereport, errcode_for_file_access(), errmsg(), ERROR, mkdir, and S_IRWXU.

Referenced by SharedFileSetCreate().

1437 {
1438  if (mkdir(directory, S_IRWXU) < 0)
1439  {
1440  if (errno == EEXIST)
1441  return;
1442 
1443  /*
1444  * Failed. Try to create basedir first in case it's missing. Tolerate
1445  * EEXIST to close a race against another process following the same
1446  * algorithm.
1447  */
1448  if (mkdir(basedir, S_IRWXU) < 0 && errno != EEXIST)
1449  ereport(ERROR,
1451  errmsg("cannot create temporary directory \"%s\": %m",
1452  basedir)));
1453 
1454  /* Try again. */
1455  if (mkdir(directory, S_IRWXU) < 0 && errno != EEXIST)
1456  ereport(ERROR,
1458  errmsg("cannot create temporary subdirectory \"%s\": %m",
1459  directory)));
1460  }
1461 }
static char * basedir
Definition: pg_basebackup.c:78
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
static const char * directory
Definition: zic.c:567
#define S_IRWXU
Definition: win32_port.h:280
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define mkdir(a, b)
Definition: win32_port.h:58

◆ PathNameCreateTemporaryFile()

File PathNameCreateTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1635 of file fd.c.

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

Referenced by SharedFileSetCreate().

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

◆ PathNameDeleteTemporaryDir()

void PathNameDeleteTemporaryDir ( const char *  dirname)

Definition at line 1467 of file fd.c.

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

Referenced by SharedFileSetDeleteAll().

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

◆ PathNameDeleteTemporaryFile()

bool PathNameDeleteTemporaryFile ( const char *  path,
bool  error_on_failure 
)

Definition at line 1703 of file fd.c.

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

Referenced by SharedFileSetDelete(), and unlink_if_exists_fname().

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

◆ PathNameOpenFile()

File PathNameOpenFile ( const char *  fileName,
int  fileFlags 
)

Definition at line 1358 of file fd.c.

References PathNameOpenFilePerm(), and PG_FILE_MODE_DEFAULT.

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

1359 {
1360  return PathNameOpenFilePerm(fileName, fileFlags, PG_FILE_MODE_DEFAULT);
1361 }
File PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
Definition: fd.c:1371
#define PG_FILE_MODE_DEFAULT
Definition: fd.c:131

◆ PathNameOpenFilePerm()

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

Definition at line 1371 of file fd.c.

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

Referenced by PathNameOpenFile().

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

◆ PathNameOpenTemporaryFile()

File PathNameOpenTemporaryFile ( const char *  path)

Definition at line 1673 of file fd.c.

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

Referenced by SharedFileSetOpen().

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

◆ pg_fdatasync()

int pg_fdatasync ( int  fd)

Definition at line 400 of file fd.c.

References enableFsync, and fsync.

Referenced by issue_xlog_fsync().

401 {
402  if (enableFsync)
403  {
404 #ifdef HAVE_FDATASYNC
405  return fdatasync(fd);
406 #else
407  return fsync(fd);
408 #endif
409  }
410  else
411  return 0;
412 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define fsync(fd)
Definition: win32_port.h:63
bool enableFsync
Definition: globals.c:111

◆ pg_flush_data()

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

Definition at line 422 of file fd.c.

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

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

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

◆ pg_fsync()

int pg_fsync ( int  fd)

Definition at line 348 of file fd.c.

References pg_fsync_no_writethrough(), pg_fsync_writethrough(), sync_method, and SYNC_METHOD_FSYNC_WRITETHROUGH.

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

349 {
350  /* #if is to skip the sync_method test if there's no need for it */
351 #if defined(HAVE_FSYNC_WRITETHROUGH) && !defined(FSYNC_WRITETHROUGH_IS_FSYNC)
353  return pg_fsync_writethrough(fd);
354  else
355 #endif
357 }
#define SYNC_METHOD_FSYNC_WRITETHROUGH
Definition: xlog.h:28
int pg_fsync_writethrough(int fd)
Definition: fd.c:377
int pg_fsync_no_writethrough(int fd)
Definition: fd.c:365
static int fd(const char *x, int i)
Definition: preproc-init.c:105
int sync_method
Definition: xlog.c:103

◆ pg_fsync_no_writethrough()

int pg_fsync_no_writethrough ( int  fd)

Definition at line 365 of file fd.c.

References enableFsync, and fsync.

Referenced by issue_xlog_fsync(), and pg_fsync().

366 {
367  if (enableFsync)
368  return fsync(fd);
369  else
370  return 0;
371 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define fsync(fd)
Definition: win32_port.h:63
bool enableFsync
Definition: globals.c:111

◆ pg_fsync_writethrough()

int pg_fsync_writethrough ( int  fd)

Definition at line 377 of file fd.c.

References enableFsync.

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

378 {
379  if (enableFsync)
380  {
381 #ifdef WIN32
382  return _commit(fd);
383 #elif defined(F_FULLFSYNC)
384  return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
385 #else
386  errno = ENOSYS;
387  return -1;
388 #endif
389  }
390  else
391  return 0;
392 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
bool enableFsync
Definition: globals.c:111

◆ ReadDir()

◆ ReadDirExtended()

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

Definition at line 2688 of file fd.c.

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

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

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

◆ RegisterTemporaryFile()

static void RegisterTemporaryFile ( File  file)
static

Definition at line 1330 of file fd.c.

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

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

1331 {
1334 
1335  /* Backup mechanism for closing at end of xact. */
1338 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static Vfd * VfdCache
Definition: fd.c:211
static bool have_xact_temporary_files
Definition: fd.c:223
void ResourceOwnerRememberFile(ResourceOwner owner, File file)
Definition: resowner.c:1186
unsigned short fdstate
Definition: fd.c:193
ResourceOwner resowner
Definition: fd.c:194
#define FD_CLOSE_AT_EOXACT
Definition: fd.c:187

◆ ReleaseLruFile()

static bool ReleaseLruFile ( void  )
static

Definition at line 1165 of file fd.c.

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

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

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

◆ ReleaseLruFiles()

static void ReleaseLruFiles ( void  )
static

Definition at line 1187 of file fd.c.

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

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

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

◆ RemovePgTempFiles()

void RemovePgTempFiles ( void  )

Definition at line 3014 of file fd.c.

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

Referenced by PostmasterMain().

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

◆ RemovePgTempFilesInDir()

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

Definition at line 3074 of file fd.c.

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

Referenced by RemovePgTempFiles().

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

◆ RemovePgTempRelationFiles()

static void RemovePgTempRelationFiles ( const char *  tsdirname)
static

Definition at line 3140 of file fd.c.

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

Referenced by RemovePgTempFiles().

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

◆ RemovePgTempRelationFilesInDbspace()

static void RemovePgTempRelationFilesInDbspace ( const char *  dbspacedirname)
static

Definition at line 3168 of file fd.c.

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

Referenced by RemovePgTempRelationFiles().

3169 {
3170  DIR *dbspace_dir;
3171  struct dirent *de;
3172  char rm_path[MAXPGPATH * 2];
3173 
3174  dbspace_dir = AllocateDir(dbspacedirname);
3175 
3176  while ((de = ReadDirExtended(dbspace_dir, dbspacedirname, LOG)) != NULL)
3177  {
3178  if (!looks_like_temp_rel_name(de->d_name))
3179  continue;
3180 
3181  snprintf(rm_path, sizeof(rm_path), "%s/%s",
3182  dbspacedirname, de->d_name);
3183 
3184  if (unlink(rm_path) < 0)
3185  ereport(LOG,
3187  errmsg("could not remove file \"%s\": %m",
3188  rm_path)));
3189  }
3190 
3191  FreeDir(dbspace_dir);
3192 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2688
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2607
#define ereport(elevel, rest)
Definition: elog.h:122
static bool looks_like_temp_rel_name(const char *name)
Definition: fd.c:3196
int errmsg(const char *fmt,...)
Definition: elog.c:797
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2725

◆ ReportTemporaryFileUsage()

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

Definition at line 1311 of file fd.c.

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

Referenced by FileClose(), and PathNameDeleteTemporaryFile().

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

◆ reserveAllocatedDesc()

static bool reserveAllocatedDesc ( void  )
static

Definition at line 2280 of file fd.c.

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

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

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

◆ set_max_safe_fds()

void set_max_safe_fds ( void  )

Definition at line 896 of file fd.c.

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

Referenced by PostmasterMain().

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

◆ SetTempTablespaces()

void SetTempTablespaces ( Oid tableSpaces,
int  numSpaces 
)

Definition at line 2810 of file fd.c.

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

Referenced by assign_temp_tablespaces(), and PrepareTempTablespaces().

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

◆ SyncDataDirectory()

void SyncDataDirectory ( void  )

Definition at line 3263 of file fd.c.

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

Referenced by StartupXLOG().

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

◆ TempTablespacePath()

void TempTablespacePath ( char *  path,
Oid  tablespace 
)

Definition at line 1553 of file fd.c.

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

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

1554 {
1555  /*
1556  * Identify the tempfile directory for this tablespace.
1557  *
1558  * If someone tries to specify pg_global, use pg_default instead.
1559  */
1560  if (tablespace == InvalidOid ||
1563  snprintf(path, MAXPGPATH, "base/%s", PG_TEMP_FILES_DIR);
1564  else
1565  {
1566  /* All other tablespaces are accessed via symlinks */
1567  snprintf(path, MAXPGPATH, "pg_tblspc/%u/%s/%s",
1570  }
1571 }
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define MAXPGPATH
#define DEFAULTTABLESPACE_OID
Definition: pg_tablespace.h:63
char * tablespace
Definition: pgbench.c:146
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_TEMP_FILES_DIR
Definition: fd.h:140
#define TABLESPACE_VERSION_DIRECTORY
Definition: catalog.h:26

◆ TempTablespacesAreSet()

bool TempTablespacesAreSet ( void  )

Definition at line 2838 of file fd.c.

References numTempTableSpaces.

Referenced by GetTempTablespaces(), and PrepareTempTablespaces().

2839 {
2840  return (numTempTableSpaces >= 0);
2841 }
static int numTempTableSpaces
Definition: fd.c:272

◆ unlink_if_exists_fname()

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

Definition at line 3443 of file fd.c.

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

Referenced by PathNameDeleteTemporaryDir().

3444 {
3445  if (isdir)
3446  {
3447  if (rmdir(fname) != 0 && errno != ENOENT)
3448  ereport(elevel,
3450  errmsg("could not rmdir directory \"%s\": %m", fname)));
3451  }
3452  else
3453  {
3454  /* Use PathNameDeleteTemporaryFile to report filesize */
3455  PathNameDeleteTemporaryFile(fname, false);
3456  }
3457 }
bool PathNameDeleteTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1703
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
static int elevel
Definition: vacuumlazy.c:136
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ walkdir()

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

Definition at line 3336 of file fd.c.

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

Referenced by PathNameDeleteTemporaryDir(), and SyncDataDirectory().

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

Variable Documentation

◆ allocatedDescs

AllocateDesc* allocatedDescs = NULL
static

Definition at line 259 of file fd.c.

◆ have_xact_temporary_files

bool have_xact_temporary_files = false
static

Definition at line 223 of file fd.c.

Referenced by CleanupTempFiles(), and RegisterTemporaryFile().

◆ max_files_per_process

int max_files_per_process = 1000

Definition at line 139 of file fd.c.

Referenced by set_max_safe_fds().

◆ max_safe_fds

int max_safe_fds = 32

◆ maxAllocatedDescs

int maxAllocatedDescs = 0
static

◆ nextTempTableSpace

int nextTempTableSpace = 0
static

Definition at line 273 of file fd.c.

Referenced by GetNextTempTableSpace(), and SetTempTablespaces().

◆ nfile

int nfile = 0
static

◆ numAllocatedDescs

◆ numTempTableSpaces

int numTempTableSpaces = -1
static

◆ SizeVfdCache

Size SizeVfdCache = 0
static

Definition at line 212 of file fd.c.

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

◆ tempFileCounter

long tempFileCounter = 0
static

Definition at line 265 of file fd.c.

Referenced by OpenTemporaryFileInTablespace().

◆ temporary_files_size

uint64 temporary_files_size = 0
static

Definition at line 231 of file fd.c.

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

◆ tempTableSpaces

Oid* tempTableSpaces = NULL
static

◆ VfdCache

Vfd* VfdCache
static

Definition at line 211 of file fd.c.