From 4cdfdef2ff441f5db01dc989a90aecce4dc6b272 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Mon, 21 May 2018 15:43:30 -0700 Subject: [PATCH] WIP: Add FileOpenForFd(). Author: Andres Freund Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/backend/storage/file/fd.c | 68 +++++++++++++++++++++++++++++++---- src/include/storage/fd.h | 2 ++ 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 8ae13a51ec..50a1cb930f 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -180,6 +180,7 @@ int max_safe_fds = 32; /* default if not changed */ #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 */ +#define FD_NOT_IN_LRU (1 << 3) /* T = not in LRU */ typedef struct vfd { @@ -304,7 +305,6 @@ 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); @@ -1176,7 +1176,7 @@ ReleaseLruFile(void) * Release kernel FDs as needed to get under the max_safe_fds limit. * After calling this, it's OK to try to open another file. */ -static void +void ReleaseLruFiles(void) { while (nfile + numAllocatedDescs >= max_safe_fds) @@ -1289,9 +1289,11 @@ FileAccess(File file) * We now know that the file is open and that it is not the last one * accessed, so we need to move it to the head of the Lru ring. */ - - Delete(file); - Insert(file); + if (!(VfdCache[file].fdstate & FD_NOT_IN_LRU)) + { + Delete(file); + Insert(file); + } } return 0; @@ -1414,6 +1416,56 @@ PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode) return file; } +/* + * Open a File for a pre-existing file descriptor. + * + * Note that these files will not be closed in an LRU basis, therefore the + * caller is responsible for limiting the number of open file descriptors. + * + * The passed in name is purely for informational purposes. + */ +File +FileOpenForFd(int fd, const char *fileName) +{ + char *fnamecopy; + File file; + Vfd *vfdP; + + /* + * We need a malloc'd copy of the file name; fail cleanly if no room. + */ + fnamecopy = strdup(fileName); + if (fnamecopy == NULL) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + file = AllocateVfd(); + vfdP = &VfdCache[file]; + + /* Close excess kernel FDs. */ + ReleaseLruFiles(); + + vfdP->fd = fd; + ++nfile; + + DO_DB(elog(LOG, "FileOpenForFd: success %d/%d (%s)", + file, fd, fnamecopy)); + + /* NB: Explicitly not inserted into LRU! */ + + vfdP->fileName = fnamecopy; + /* Saved flags are adjusted to be OK for re-opening file */ + vfdP->fileFlags = 0; + vfdP->fileMode = 0; + vfdP->seekPos = 0; + vfdP->fileSize = 0; + vfdP->fdstate = FD_NOT_IN_LRU; + vfdP->resowner = NULL; + + return file; +} + /* * Create directory 'directory'. If necessary, create 'basedir', which must * be the directory above it. This is designed for creating the top-level @@ -1760,7 +1812,11 @@ FileClose(File file) vfdP->fd = VFD_CLOSED; /* remove the file from the lru ring */ - Delete(file); + if (!(vfdP->fdstate & FD_NOT_IN_LRU)) + { + vfdP->fdstate &= ~FD_NOT_IN_LRU; + Delete(file); + } } if (vfdP->fdstate & FD_TEMP_FILE_LIMIT) diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index 5e016d69a5..e96e8b1398 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -65,6 +65,7 @@ extern int max_safe_fds; /* Operations on virtual Files --- equivalent to Unix kernel file ops */ extern File PathNameOpenFile(const char *fileName, int fileFlags); extern File PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode); +extern File FileOpenForFd(int fd, const char *fileName); extern File OpenTemporaryFile(bool interXact); extern void FileClose(File file); extern int FilePrefetch(File file, off_t offset, int amount, uint32 wait_event_info); @@ -127,6 +128,7 @@ extern void AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid); extern void RemovePgTempFiles(void); extern bool looks_like_temp_rel_name(const char *name); +extern void ReleaseLruFiles(void); extern int pg_fsync(int fd); extern int pg_fsync_no_writethrough(int fd); -- 2.39.5