From 786fafb408ba0b9080941170eedcb6a58c2df8d1 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 18 May 2018 12:42:32 -0700
Subject: [PATCH v1 4/7] WIP: Allow to create a transient file for a previously
 openend FD.

It might be better to extend the normal vfd files instead, adding a
flag that prohibits closing the underlying file (and removing them
from the LRU).

Author: Andres Freund
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/storage/file/fd.c | 32 ++++++++++++++++++++++++++++++++
 src/include/storage/fd.h      |  2 ++
 2 files changed, 34 insertions(+)

diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 8ae13a51ec1..e2492ce94d5 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -2430,6 +2430,38 @@ OpenTransientFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
 	return -1;					/* failure */
 }
 
+void
+ReserveTransientFile(void)
+{
+	if (!reserveAllocatedDesc())
+		ereport(PANIC,
+				(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
+				 errmsg("exceeded maxAllocatedDescs (%d) while trying to open file",
+						maxAllocatedDescs)));
+
+	/* Close excess kernel FDs. */
+	ReleaseLruFiles();
+
+	Assert(nfile + numAllocatedDescs <= max_safe_fds);
+}
+
+void
+RegisterTransientFile(int fd)
+{
+	AllocateDesc *desc;
+
+	/* make sure ReserveTransientFile was called sufficiently recently */
+	Assert(fd >= 0);
+	Assert(nfile + numAllocatedDescs <= max_safe_fds);
+	Assert(numAllocatedDescs < maxAllocatedDescs);
+
+	desc = &allocatedDescs[numAllocatedDescs];
+	desc->kind = AllocateDescRawFD;
+	desc->desc.fd = fd;
+	desc->create_subid = GetCurrentSubTransactionId();
+	numAllocatedDescs++;
+}
+
 /*
  * Routines that want to initiate a pipe stream should use OpenPipeStream
  * rather than plain popen().  This lets fd.c deal with freeing FDs if
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index 5e016d69a5a..9bb32771602 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -105,6 +105,8 @@ extern int	FreeDir(DIR *dir);
 /* Operations to allow use of a plain kernel FD, with automatic cleanup */
 extern int	OpenTransientFile(const char *fileName, int fileFlags);
 extern int	OpenTransientFilePerm(const char *fileName, int fileFlags, mode_t fileMode);
+extern void ReserveTransientFile(void);
+extern void RegisterTransientFile(int fd);
 extern int	CloseTransientFile(int fd);
 
 /* If you've really really gotta have a plain kernel FD, use this */
-- 
2.17.0.rc1.dirty

