Skip to content

Commit 9bacf0e

Browse files
committed
Revert "Use "transient" files for blind writes, take 2".
This reverts commit fba105b. That approach had problems with the smgr-level state not tracking what we really want to happen, and with the VFD-level state not tracking the smgr-level state very well either. In consequence, it was still possible to hold kernel file descriptors open for long-gone tables (as in recent report from Tore Halset), and yet there were also cases of FDs being closed undesirably soon. A replacement implementation will follow.
1 parent a66ee69 commit 9bacf0e

File tree

6 files changed

+28
-102
lines changed

6 files changed

+28
-102
lines changed

src/backend/storage/buffer/bufmgr.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,10 +1882,7 @@ BufferGetTag(Buffer buffer, RelFileNode *rnode, ForkNumber *forknum,
18821882
* written.)
18831883
*
18841884
* If the caller has an smgr reference for the buffer's relation, pass it
1885-
* as the second parameter. If not, pass NULL. In the latter case, the
1886-
* relation will be marked as "transient" so that the corresponding
1887-
* kernel-level file descriptors are closed when the current transaction ends,
1888-
* if any.
1885+
* as the second parameter. If not, pass NULL.
18891886
*/
18901887
static void
18911888
FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
@@ -1909,12 +1906,9 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
19091906
errcontext.previous = error_context_stack;
19101907
error_context_stack = &errcontext;
19111908

1912-
/* Find smgr relation for buffer, and mark it as transient */
1909+
/* Find smgr relation for buffer */
19131910
if (reln == NULL)
1914-
{
19151911
reln = smgropen(buf->tag.rnode, InvalidBackendId);
1916-
smgrsettransient(reln);
1917-
}
19181912

19191913
TRACE_POSTGRESQL_BUFFER_FLUSH_START(buf->tag.forkNum,
19201914
buf->tag.blockNum,

src/backend/storage/file/fd.c

Lines changed: 26 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,6 @@ int max_safe_fds = 32; /* default if not changed */
126126
/* these are the assigned bits in fdstate below: */
127127
#define FD_TEMPORARY (1 << 0) /* T = delete when closed */
128128
#define FD_XACT_TEMPORARY (1 << 1) /* T = delete at eoXact */
129-
#define FD_XACT_TRANSIENT (1 << 2) /* T = close (not delete) at aoXact,
130-
* but keep VFD */
131129

132130
typedef struct vfd
133131
{
@@ -158,8 +156,11 @@ static Size SizeVfdCache = 0;
158156
*/
159157
static int nfile = 0;
160158

161-
/* True if there are files to close/delete at end of transaction */
162-
static bool have_pending_fd_cleanup = false;
159+
/*
160+
* Flag to tell whether it's worth scanning VfdCache looking for temp files
161+
* to close
162+
*/
163+
static bool have_xact_temporary_files = false;
163164

164165
/*
165166
* Tracks the total size of all temporary files. Note: when temp_file_limit
@@ -607,7 +608,6 @@ LruDelete(File file)
607608
Vfd *vfdP;
608609

609610
Assert(file != 0);
610-
Assert(!FileIsNotOpen(file));
611611

612612
DO_DB(elog(LOG, "LruDelete %d (%s)",
613613
file, VfdCache[file].fileName));
@@ -971,7 +971,7 @@ OpenTemporaryFile(bool interXact)
971971
VfdCache[file].resowner = CurrentResourceOwner;
972972

973973
/* ensure cleanup happens at eoxact */
974-
have_pending_fd_cleanup = true;
974+
have_xact_temporary_files = true;
975975
}
976976

977977
return file;
@@ -1044,25 +1044,6 @@ OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
10441044
return file;
10451045
}
10461046

1047-
/*
1048-
* Set the transient flag on a file
1049-
*
1050-
* This flag tells CleanupTempFiles to close the kernel-level file descriptor
1051-
* (but not the VFD itself) at end of transaction.
1052-
*/
1053-
void
1054-
FileSetTransient(File file)
1055-
{
1056-
Vfd *vfdP;
1057-
1058-
Assert(FileIsValid(file));
1059-
1060-
vfdP = &VfdCache[file];
1061-
vfdP->fdstate |= FD_XACT_TRANSIENT;
1062-
1063-
have_pending_fd_cleanup = true;
1064-
}
1065-
10661047
/*
10671048
* close a file when done with it
10681049
*/
@@ -1863,9 +1844,8 @@ AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
18631844
* particularly care which). All still-open per-transaction temporary file
18641845
* VFDs are closed, which also causes the underlying files to be deleted
18651846
* (although they should've been closed already by the ResourceOwner
1866-
* cleanup). Transient files have their kernel file descriptors closed.
1867-
* Furthermore, all "allocated" stdio files are closed. We also forget any
1868-
* transaction-local temp tablespace list.
1847+
* cleanup). Furthermore, all "allocated" stdio files are closed. We also
1848+
* forget any transaction-local temp tablespace list.
18691849
*/
18701850
void
18711851
AtEOXact_Files(void)
@@ -1888,10 +1868,7 @@ AtProcExit_Files(int code, Datum arg)
18881868
}
18891869

18901870
/*
1891-
* General cleanup routine for fd.c.
1892-
*
1893-
* Temporary files are closed, and their underlying files deleted.
1894-
* Transient files are closed.
1871+
* Close temporary files and delete their underlying files.
18951872
*
18961873
* isProcExit: if true, this is being called as the backend process is
18971874
* exiting. If that's the case, we should remove all temporary files; if
@@ -1908,51 +1885,35 @@ CleanupTempFiles(bool isProcExit)
19081885
* Careful here: at proc_exit we need extra cleanup, not just
19091886
* xact_temporary files.
19101887
*/
1911-
if (isProcExit || have_pending_fd_cleanup)
1888+
if (isProcExit || have_xact_temporary_files)
19121889
{
19131890
Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
19141891
for (i = 1; i < SizeVfdCache; i++)
19151892
{
19161893
unsigned short fdstate = VfdCache[i].fdstate;
19171894

1918-
if (VfdCache[i].fileName != NULL)
1895+
if ((fdstate & FD_TEMPORARY) && VfdCache[i].fileName != NULL)
19191896
{
1920-
if (fdstate & FD_TEMPORARY)
1921-
{
1922-
/*
1923-
* If we're in the process of exiting a backend process,
1924-
* close all temporary files. Otherwise, only close
1925-
* temporary files local to the current transaction. They
1926-
* should be closed by the ResourceOwner mechanism
1927-
* already, so this is just a debugging cross-check.
1928-
*/
1929-
if (isProcExit)
1930-
FileClose(i);
1931-
else if (fdstate & FD_XACT_TEMPORARY)
1932-
{
1933-
elog(WARNING,
1934-
"temporary file %s not closed at end-of-transaction",
1935-
VfdCache[i].fileName);
1936-
FileClose(i);
1937-
}
1938-
}
1939-
else if (fdstate & FD_XACT_TRANSIENT)
1897+
/*
1898+
* If we're in the process of exiting a backend process, close
1899+
* all temporary files. Otherwise, only close temporary files
1900+
* local to the current transaction. They should be closed by
1901+
* the ResourceOwner mechanism already, so this is just a
1902+
* debugging cross-check.
1903+
*/
1904+
if (isProcExit)
1905+
FileClose(i);
1906+
else if (fdstate & FD_XACT_TEMPORARY)
19401907
{
1941-
/*
1942-
* Close the FD, and remove the entry from the LRU ring,
1943-
* but also remove the flag from the VFD. This is to
1944-
* ensure that if the VFD is reused in the future for
1945-
* non-transient access, we don't close it inappropriately
1946-
* then.
1947-
*/
1948-
if (!FileIsNotOpen(i))
1949-
LruDelete(i);
1950-
VfdCache[i].fdstate &= ~FD_XACT_TRANSIENT;
1908+
elog(WARNING,
1909+
"temporary file %s not closed at end-of-transaction",
1910+
VfdCache[i].fileName);
1911+
FileClose(i);
19511912
}
19521913
}
19531914
}
19541915

1955-
have_pending_fd_cleanup = false;
1916+
have_xact_temporary_files = false;
19561917
}
19571918

19581919
/* Clean up "allocated" stdio files and dirs. */

src/backend/storage/smgr/md.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,6 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
300300

301301
pfree(path);
302302

303-
if (reln->smgr_transient)
304-
FileSetTransient(fd);
305-
306303
reln->md_fd[forkNum] = _fdvec_alloc();
307304

308305
reln->md_fd[forkNum]->mdfd_vfd = fd;
@@ -585,9 +582,6 @@ mdopen(SMgrRelation reln, ForkNumber forknum, ExtensionBehavior behavior)
585582

586583
pfree(path);
587584

588-
if (reln->smgr_transient)
589-
FileSetTransient(fd);
590-
591585
reln->md_fd[forknum] = mdfd = _fdvec_alloc();
592586

593587
mdfd->mdfd_vfd = fd;
@@ -1680,9 +1674,6 @@ _mdfd_openseg(SMgrRelation reln, ForkNumber forknum, BlockNumber segno,
16801674
if (fd < 0)
16811675
return NULL;
16821676

1683-
if (reln->smgr_transient)
1684-
FileSetTransient(fd);
1685-
16861677
/* allocate an mdfdvec entry for it */
16871678
v = _fdvec_alloc();
16881679

src/backend/storage/smgr/smgr.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -163,33 +163,16 @@ smgropen(RelFileNode rnode, BackendId backend)
163163
reln->smgr_targblock = InvalidBlockNumber;
164164
reln->smgr_fsm_nblocks = InvalidBlockNumber;
165165
reln->smgr_vm_nblocks = InvalidBlockNumber;
166-
reln->smgr_transient = false;
167166
reln->smgr_which = 0; /* we only have md.c at present */
168167

169168
/* mark it not open */
170169
for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
171170
reln->md_fd[forknum] = NULL;
172171
}
173-
else
174-
/* if it was transient before, it no longer is */
175-
reln->smgr_transient = false;
176172

177173
return reln;
178174
}
179175

180-
/*
181-
* smgrsettransient() -- mark an SMgrRelation object as transaction-bound
182-
*
183-
* The main effect of this is that all opened files are marked to be
184-
* kernel-level closed (but not necessarily VFD-closed) when the current
185-
* transaction ends.
186-
*/
187-
void
188-
smgrsettransient(SMgrRelation reln)
189-
{
190-
reln->smgr_transient = true;
191-
}
192-
193176
/*
194177
* smgrsetowner() -- Establish a long-lived reference to an SMgrRelation object
195178
*

src/include/storage/fd.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ extern int max_safe_fds;
6666
/* Operations on virtual Files --- equivalent to Unix kernel file ops */
6767
extern File PathNameOpenFile(FileName fileName, int fileFlags, int fileMode);
6868
extern File OpenTemporaryFile(bool interXact);
69-
extern void FileSetTransient(File file);
7069
extern void FileClose(File file);
7170
extern int FilePrefetch(File file, off_t offset, int amount);
7271
extern int FileRead(File file, char *buffer, int amount);

src/include/storage/smgr.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ typedef struct SMgrRelationData
6060
* submodules. Do not touch them from elsewhere.
6161
*/
6262
int smgr_which; /* storage manager selector */
63-
bool smgr_transient; /* T if files are to be closed at EOXact */
6463

6564
/* for md.c; NULL for forks that are not open */
6665
struct _MdfdVec *md_fd[MAX_FORKNUM + 1];
@@ -73,7 +72,6 @@ typedef SMgrRelationData *SMgrRelation;
7372

7473
extern void smgrinit(void);
7574
extern SMgrRelation smgropen(RelFileNode rnode, BackendId backend);
76-
extern void smgrsettransient(SMgrRelation reln);
7775
extern bool smgrexists(SMgrRelation reln, ForkNumber forknum);
7876
extern void smgrsetowner(SMgrRelation *owner, SMgrRelation reln);
7977
extern void smgrclose(SMgrRelation reln);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy