Skip to content

Commit cacb652

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 f34d1fa commit cacb652

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
@@ -1847,10 +1847,7 @@ BufferGetTag(Buffer buffer, RelFileNode *rnode, ForkNumber *forknum,
18471847
* written.)
18481848
*
18491849
* If the caller has an smgr reference for the buffer's relation, pass it
1850-
* as the second parameter. If not, pass NULL. In the latter case, the
1851-
* relation will be marked as "transient" so that the corresponding
1852-
* kernel-level file descriptors are closed when the current transaction ends,
1853-
* if any.
1850+
* as the second parameter. If not, pass NULL.
18541851
*/
18551852
static void
18561853
FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
@@ -1872,12 +1869,9 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
18721869
errcontext.previous = error_context_stack;
18731870
error_context_stack = &errcontext;
18741871

1875-
/* Find smgr relation for buffer, and mark it as transient */
1872+
/* Find smgr relation for buffer */
18761873
if (reln == NULL)
1877-
{
18781874
reln = smgropen(buf->tag.rnode, InvalidBackendId);
1879-
smgrsettransient(reln);
1880-
}
18811875

18821876
TRACE_POSTGRESQL_BUFFER_FLUSH_START(buf->tag.forkNum,
18831877
buf->tag.blockNum,

src/backend/storage/file/fd.c

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

131-
/* Flag to tell whether there are files to close/delete at end of transaction */
132-
static bool have_pending_fd_cleanup = false;
129+
/*
130+
* Flag to tell whether it's worth scanning VfdCache looking for temp files to
131+
* close
132+
*/
133+
static bool have_xact_temporary_files = false;
133134

134135
typedef struct vfd
135136
{
@@ -590,7 +591,6 @@ LruDelete(File file)
590591
Vfd *vfdP;
591592

592593
Assert(file != 0);
593-
Assert(!FileIsNotOpen(file));
594594

595595
DO_DB(elog(LOG, "LruDelete %d (%s)",
596596
file, VfdCache[file].fileName));
@@ -953,7 +953,7 @@ OpenTemporaryFile(bool interXact)
953953
VfdCache[file].resowner = CurrentResourceOwner;
954954

955955
/* ensure cleanup happens at eoxact */
956-
have_pending_fd_cleanup = true;
956+
have_xact_temporary_files = true;
957957
}
958958

959959
return file;
@@ -1026,25 +1026,6 @@ OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
10261026
return file;
10271027
}
10281028

1029-
/*
1030-
* Set the transient flag on a file
1031-
*
1032-
* This flag tells CleanupTempFiles to close the kernel-level file descriptor
1033-
* (but not the VFD itself) at end of transaction.
1034-
*/
1035-
void
1036-
FileSetTransient(File file)
1037-
{
1038-
Vfd *vfdP;
1039-
1040-
Assert(FileIsValid(file));
1041-
1042-
vfdP = &VfdCache[file];
1043-
vfdP->fdstate |= FD_XACT_TRANSIENT;
1044-
1045-
have_pending_fd_cleanup = true;
1046-
}
1047-
10481029
/*
10491030
* close a file when done with it
10501031
*/
@@ -1797,9 +1778,8 @@ AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
17971778
* particularly care which). All still-open per-transaction temporary file
17981779
* VFDs are closed, which also causes the underlying files to be deleted
17991780
* (although they should've been closed already by the ResourceOwner
1800-
* cleanup). Transient files have their kernel file descriptors closed.
1801-
* Furthermore, all "allocated" stdio files are closed. We also forget any
1802-
* transaction-local temp tablespace list.
1781+
* cleanup). Furthermore, all "allocated" stdio files are closed. We also
1782+
* forget any transaction-local temp tablespace list.
18031783
*/
18041784
void
18051785
AtEOXact_Files(void)
@@ -1822,10 +1802,7 @@ AtProcExit_Files(int code, Datum arg)
18221802
}
18231803

18241804
/*
1825-
* General cleanup routine for fd.c.
1826-
*
1827-
* Temporary files are closed, and their underlying files deleted.
1828-
* Transient files are closed.
1805+
* Close temporary files and delete their underlying files.
18291806
*
18301807
* isProcExit: if true, this is being called as the backend process is
18311808
* exiting. If that's the case, we should remove all temporary files; if
@@ -1842,51 +1819,35 @@ CleanupTempFiles(bool isProcExit)
18421819
* Careful here: at proc_exit we need extra cleanup, not just
18431820
* xact_temporary files.
18441821
*/
1845-
if (isProcExit || have_pending_fd_cleanup)
1822+
if (isProcExit || have_xact_temporary_files)
18461823
{
18471824
Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
18481825
for (i = 1; i < SizeVfdCache; i++)
18491826
{
18501827
unsigned short fdstate = VfdCache[i].fdstate;
18511828

1852-
if (VfdCache[i].fileName != NULL)
1829+
if ((fdstate & FD_TEMPORARY) && VfdCache[i].fileName != NULL)
18531830
{
1854-
if (fdstate & FD_TEMPORARY)
1855-
{
1856-
/*
1857-
* If we're in the process of exiting a backend process, close
1858-
* all temporary files. Otherwise, only close temporary files
1859-
* local to the current transaction. They should be closed by
1860-
* the ResourceOwner mechanism already, so this is just a
1861-
* debugging cross-check.
1862-
*/
1863-
if (isProcExit)
1864-
FileClose(i);
1865-
else if (fdstate & FD_XACT_TEMPORARY)
1866-
{
1867-
elog(WARNING,
1868-
"temporary file %s not closed at end-of-transaction",
1869-
VfdCache[i].fileName);
1870-
FileClose(i);
1871-
}
1872-
}
1873-
else if (fdstate & FD_XACT_TRANSIENT)
1831+
/*
1832+
* If we're in the process of exiting a backend process, close
1833+
* all temporary files. Otherwise, only close temporary files
1834+
* local to the current transaction. They should be closed by
1835+
* the ResourceOwner mechanism already, so this is just a
1836+
* debugging cross-check.
1837+
*/
1838+
if (isProcExit)
1839+
FileClose(i);
1840+
else if (fdstate & FD_XACT_TEMPORARY)
18741841
{
1875-
/*
1876-
* Close the FD, and remove the entry from the LRU ring,
1877-
* but also remove the flag from the VFD. This is to
1878-
* ensure that if the VFD is reused in the future for
1879-
* non-transient access, we don't close it inappropriately
1880-
* then.
1881-
*/
1882-
if (!FileIsNotOpen(i))
1883-
LruDelete(i);
1884-
VfdCache[i].fdstate &= ~FD_XACT_TRANSIENT;
1842+
elog(WARNING,
1843+
"temporary file %s not closed at end-of-transaction",
1844+
VfdCache[i].fileName);
1845+
FileClose(i);
18851846
}
18861847
}
18871848
}
18881849

1889-
have_pending_fd_cleanup = false;
1850+
have_xact_temporary_files = false;
18901851
}
18911852

18921853
/* 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
@@ -292,9 +292,6 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
292292

293293
pfree(path);
294294

295-
if (reln->smgr_transient)
296-
FileSetTransient(fd);
297-
298295
reln->md_fd[forkNum] = _fdvec_alloc();
299296

300297
reln->md_fd[forkNum]->mdfd_vfd = fd;
@@ -559,9 +556,6 @@ mdopen(SMgrRelation reln, ForkNumber forknum, ExtensionBehavior behavior)
559556

560557
pfree(path);
561558

562-
if (reln->smgr_transient)
563-
FileSetTransient(fd);
564-
565559
reln->md_fd[forknum] = mdfd = _fdvec_alloc();
566560

567561
mdfd->mdfd_vfd = fd;
@@ -1586,9 +1580,6 @@ _mdfd_openseg(SMgrRelation reln, ForkNumber forknum, BlockNumber segno,
15861580
if (fd < 0)
15871581
return NULL;
15881582

1589-
if (reln->smgr_transient)
1590-
FileSetTransient(fd);
1591-
15921583
/* allocate an mdfdvec entry for it */
15931584
v = _fdvec_alloc();
15941585

src/backend/storage/smgr/smgr.c

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

171170
/* mark it not open */
172171
for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
173172
reln->md_fd[forknum] = NULL;
174173
}
175-
else
176-
/* if it was transient before, it no longer is */
177-
reln->smgr_transient = false;
178174

179175
return reln;
180176
}
181177

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

src/include/storage/fd.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ extern int max_files_per_process;
6161
/* Operations on virtual Files --- equivalent to Unix kernel file ops */
6262
extern File PathNameOpenFile(FileName fileName, int fileFlags, int fileMode);
6363
extern File OpenTemporaryFile(bool interXact);
64-
extern void FileSetTransient(File file);
6564
extern void FileClose(File file);
6665
extern int FilePrefetch(File file, off_t offset, int amount);
6766
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
@@ -62,7 +62,6 @@ typedef struct SMgrRelationData
6262
* submodules. Do not touch them from elsewhere.
6363
*/
6464
int smgr_which; /* storage manager selector */
65-
bool smgr_transient; /* T if files are to be closed at EOXact */
6665

6766
/* for md.c; NULL for forks that are not open */
6867
struct _MdfdVec *md_fd[MAX_FORKNUM + 1];
@@ -75,7 +74,6 @@ typedef SMgrRelationData *SMgrRelation;
7574

7675
extern void smgrinit(void);
7776
extern SMgrRelation smgropen(RelFileNode rnode, BackendId backend);
78-
extern void smgrsettransient(SMgrRelation reln);
7977
extern bool smgrexists(SMgrRelation reln, ForkNumber forknum);
8078
extern void smgrsetowner(SMgrRelation *owner, SMgrRelation reln);
8179
extern void smgrclose(SMgrRelation reln);

0 commit comments

Comments
 (0)