From: Andres Freund Date: Wed, 13 Dec 2017 20:51:32 +0000 (-0800) Subject: Add defenses against pre-crash files to BufFileOpenShared(). X-Git-Tag: REL_11_BETA1~1073 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=923e8dee88ada071fe41541e83f121ead4baf7f8;p=postgresql 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 --- diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c index fa9940da9b..c6b210d137 100644 --- a/src/backend/storage/file/buffile.c +++ b/src/backend/storage/file/buffile.c @@ -211,6 +211,16 @@ MakeNewSharedSegment(BufFile *buffile, int segment) char name[MAXPGPATH]; 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); file = SharedFileSetCreate(buffile->fileset, name); @@ -303,7 +313,9 @@ BufFileOpenShared(SharedFileSet *fileset, const char *name) * name. */ if (nfiles == 0) - return NULL; + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open BufFile \"%s\"", name))); file->numFiles = nfiles; file->files = files;