Add defenses against pre-crash files to BufFileOpenShared().
Crash restarts currently don't clean up temporary files, as a debugging aid. If a left-over file happens to have the same name as a segment file we're trying to create, we'll just truncate and reuse it, but there is a problem: BufFileOpenShared() determines how many segment files exist by trying to open .0, .1, .2, ... until it finds no more files. It might be confused by a junk file that has the next segment number. To defend against that, make sure we always create a gap after the end file by unlinking the following name if it exists. Also make it an error to try to open a BufFile that doesn't exist (has no segment 0), so as not to encourage the development of client code that depends on an interface that we can't reliably provide. Author: Thomas Munro Reviewed-By: Andres Freund Discussion: https://postgr.es/m/CAEepm%3D2jhCbC_GFQJaaDhWxLB4EXtT3vVd5czuRNaqF5CWSTog%40mail.gmail.com
This commit is contained in:
parent
884a60840c
commit
923e8dee88
@ -211,6 +211,16 @@ MakeNewSharedSegment(BufFile *buffile, int segment)
|
|||||||
char name[MAXPGPATH];
|
char name[MAXPGPATH];
|
||||||
File file;
|
File file;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is possible that there are files left over from before a crash
|
||||||
|
* restart with the same name. In order for BufFileOpenShared()
|
||||||
|
* not to get confused about how many segments there are, we'll unlink
|
||||||
|
* the next segment number if it already exists.
|
||||||
|
*/
|
||||||
|
SharedSegmentName(name, buffile->name, segment + 1);
|
||||||
|
SharedFileSetDelete(buffile->fileset, name, true);
|
||||||
|
|
||||||
|
/* Create the new segment. */
|
||||||
SharedSegmentName(name, buffile->name, segment);
|
SharedSegmentName(name, buffile->name, segment);
|
||||||
file = SharedFileSetCreate(buffile->fileset, name);
|
file = SharedFileSetCreate(buffile->fileset, name);
|
||||||
|
|
||||||
@ -303,7 +313,9 @@ BufFileOpenShared(SharedFileSet *fileset, const char *name)
|
|||||||
* name.
|
* name.
|
||||||
*/
|
*/
|
||||||
if (nfiles == 0)
|
if (nfiles == 0)
|
||||||
return NULL;
|
ereport(ERROR,
|
||||||
|
(errcode_for_file_access(),
|
||||||
|
errmsg("could not open BufFile \"%s\"", name)));
|
||||||
|
|
||||||
file->numFiles = nfiles;
|
file->numFiles = nfiles;
|
||||||
file->files = files;
|
file->files = files;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user