mirror of
https://github.com/postgres/postgres.git
synced 2025-05-03 22:24:49 +03:00
Fix buffile.c error handling.
Convert buffile.c error handling to use ereport. This fixes cases where I/O errors were indistinguishable from EOF or not reported. Also remove "%m" from error messages where errno would be bogus. While we're modifying those strings, add block numbers and short read byte counts where appropriate. Back-patch to all supported releases. Reported-by: Amit Khandekar <amitdkhan.pg@gmail.com> Reviewed-by: Melanie Plageman <melanieplageman@gmail.com> Reviewed-by: Alvaro Herrera <alvherre@2ndquadrant.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Reviewed-by: Ibrar Ahmed <ibrar.ahmad@gmail.com> Reviewed-by: Michael Paquier <michael@paquier.xyz> Discussion: https://postgr.es/m/CA%2BhUKGJE04G%3D8TLK0DLypT_27D9dR8F1RQgNp0jK6qR0tZGWOw%40mail.gmail.com
This commit is contained in:
parent
5c1bfd627f
commit
02b71f06be
@ -757,26 +757,20 @@ gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb, GISTSTATE *giststate,
|
||||
static void
|
||||
ReadTempFileBlock(BufFile *file, long blknum, void *ptr)
|
||||
{
|
||||
size_t nread;
|
||||
|
||||
if (BufFileSeekBlock(file, blknum) != 0)
|
||||
elog(ERROR, "could not seek temporary file: %m");
|
||||
if (BufFileRead(file, ptr, BLCKSZ) != BLCKSZ)
|
||||
elog(ERROR, "could not read temporary file: %m");
|
||||
elog(ERROR, "could not seek to block %ld in temporary file", blknum);
|
||||
nread = BufFileRead(file, ptr, BLCKSZ);
|
||||
if (nread != BLCKSZ)
|
||||
elog(ERROR, "could not read temporary file: read only %zu of %zu bytes",
|
||||
nread, (size_t) BLCKSZ);
|
||||
}
|
||||
|
||||
static void
|
||||
WriteTempFileBlock(BufFile *file, long blknum, void *ptr)
|
||||
{
|
||||
if (BufFileSeekBlock(file, blknum) != 0)
|
||||
elog(ERROR, "could not seek temporary file: %m");
|
||||
if (BufFileWrite(file, ptr, BLCKSZ) != BLCKSZ)
|
||||
{
|
||||
/*
|
||||
* the other errors in Read/WriteTempFileBlock shouldn't happen, but
|
||||
* an error at write can easily happen if you run out of disk space.
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not write block %ld of temporary file: %m",
|
||||
blknum)));
|
||||
}
|
||||
elog(ERROR, "could not seek to block %ld in temporary file", blknum);
|
||||
BufFileWrite(file, ptr, BLCKSZ);
|
||||
}
|
||||
|
@ -820,7 +820,7 @@ ExecHashJoinNewBatch(HashJoinState *hjstate)
|
||||
if (BufFileSeek(innerFile, 0, 0L, SEEK_SET))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not rewind hash-join temporary file: %m")));
|
||||
errmsg("could not rewind hash-join temporary file")));
|
||||
|
||||
while ((slot = ExecHashJoinGetSavedTuple(hjstate,
|
||||
innerFile,
|
||||
@ -850,7 +850,7 @@ ExecHashJoinNewBatch(HashJoinState *hjstate)
|
||||
if (BufFileSeek(hashtable->outerBatchFile[curbatch], 0, 0L, SEEK_SET))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not rewind hash-join temporary file: %m")));
|
||||
errmsg("could not rewind hash-join temporary file")));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -872,7 +872,6 @@ ExecHashJoinSaveTuple(MinimalTuple tuple, uint32 hashvalue,
|
||||
BufFile **fileptr)
|
||||
{
|
||||
BufFile *file = *fileptr;
|
||||
size_t written;
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
@ -881,17 +880,8 @@ ExecHashJoinSaveTuple(MinimalTuple tuple, uint32 hashvalue,
|
||||
*fileptr = file;
|
||||
}
|
||||
|
||||
written = BufFileWrite(file, (void *) &hashvalue, sizeof(uint32));
|
||||
if (written != sizeof(uint32))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not write to hash-join temporary file: %m")));
|
||||
|
||||
written = BufFileWrite(file, (void *) tuple, tuple->t_len);
|
||||
if (written != tuple->t_len)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not write to hash-join temporary file: %m")));
|
||||
BufFileWrite(file, (void *) &hashvalue, sizeof(uint32));
|
||||
BufFileWrite(file, (void *) tuple, tuple->t_len);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -932,7 +922,8 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
|
||||
if (nread != sizeof(header))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read from hash-join temporary file: %m")));
|
||||
errmsg("could not read from hash-join temporary file: read only %zu of %zu bytes",
|
||||
nread, sizeof(header))));
|
||||
*hashvalue = header[0];
|
||||
tuple = (MinimalTuple) palloc(header[1]);
|
||||
tuple->t_len = header[1];
|
||||
@ -942,7 +933,8 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
|
||||
if (nread != header[1] - sizeof(uint32))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read from hash-join temporary file: %m")));
|
||||
errmsg("could not read from hash-join temporary file: read only %zu of %zu bytes",
|
||||
nread, header[1] - sizeof(uint32))));
|
||||
return ExecStoreMinimalTuple(tuple, tupleSlot, true);
|
||||
}
|
||||
|
||||
|
@ -93,8 +93,7 @@ static BufFile *makeBufFile(File firstfile);
|
||||
static void extendBufFile(BufFile *file);
|
||||
static void BufFileLoadBuffer(BufFile *file);
|
||||
static void BufFileDumpBuffer(BufFile *file);
|
||||
static int BufFileFlush(BufFile *file);
|
||||
|
||||
static void BufFileFlush(BufFile *file);
|
||||
|
||||
/*
|
||||
* Create a BufFile given the first underlying physical file.
|
||||
@ -247,7 +246,10 @@ BufFileLoadBuffer(BufFile *file)
|
||||
if (file->curOffset != file->offsets[file->curFile])
|
||||
{
|
||||
if (FileSeek(thisfile, file->curOffset, SEEK_SET) != file->curOffset)
|
||||
return; /* seek failed, read nothing */
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in file \"%s\": %m",
|
||||
FilePathName(thisfile))));
|
||||
file->offsets[file->curFile] = file->curOffset;
|
||||
}
|
||||
|
||||
@ -256,7 +258,14 @@ BufFileLoadBuffer(BufFile *file)
|
||||
*/
|
||||
file->nbytes = FileRead(thisfile, file->buffer.data, sizeof(file->buffer));
|
||||
if (file->nbytes < 0)
|
||||
{
|
||||
file->nbytes = 0;
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read file \"%s\": %m",
|
||||
FilePathName(thisfile))));
|
||||
}
|
||||
|
||||
file->offsets[file->curFile] += file->nbytes;
|
||||
/* we choose not to advance curOffset here */
|
||||
|
||||
@ -314,12 +323,19 @@ BufFileDumpBuffer(BufFile *file)
|
||||
if (file->curOffset != file->offsets[file->curFile])
|
||||
{
|
||||
if (FileSeek(thisfile, file->curOffset, SEEK_SET) != file->curOffset)
|
||||
return; /* seek failed, give up */
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in file \"%s\": %m",
|
||||
FilePathName(thisfile))));
|
||||
file->offsets[file->curFile] = file->curOffset;
|
||||
}
|
||||
bytestowrite = FileWrite(thisfile, file->buffer.data + wpos, bytestowrite);
|
||||
if (bytestowrite <= 0)
|
||||
return; /* failed to write */
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not write to file \"%s\" : %m",
|
||||
FilePathName(thisfile))));
|
||||
|
||||
file->offsets[file->curFile] += bytestowrite;
|
||||
file->curOffset += bytestowrite;
|
||||
wpos += bytestowrite;
|
||||
@ -352,7 +368,8 @@ BufFileDumpBuffer(BufFile *file)
|
||||
/*
|
||||
* BufFileRead
|
||||
*
|
||||
* Like fread() except we assume 1-byte element size.
|
||||
* Like fread() except we assume 1-byte element size and report I/O errors via
|
||||
* ereport().
|
||||
*/
|
||||
size_t
|
||||
BufFileRead(BufFile *file, void *ptr, size_t size)
|
||||
@ -360,12 +377,7 @@ BufFileRead(BufFile *file, void *ptr, size_t size)
|
||||
size_t nread = 0;
|
||||
size_t nthistime;
|
||||
|
||||
if (file->dirty)
|
||||
{
|
||||
if (BufFileFlush(file) != 0)
|
||||
return 0; /* could not flush... */
|
||||
Assert(!file->dirty);
|
||||
}
|
||||
BufFileFlush(file);
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
@ -399,7 +411,8 @@ BufFileRead(BufFile *file, void *ptr, size_t size)
|
||||
/*
|
||||
* BufFileWrite
|
||||
*
|
||||
* Like fwrite() except we assume 1-byte element size.
|
||||
* Like fwrite() except we assume 1-byte element size and report errors via
|
||||
* ereport().
|
||||
*/
|
||||
size_t
|
||||
BufFileWrite(BufFile *file, void *ptr, size_t size)
|
||||
@ -413,11 +426,7 @@ BufFileWrite(BufFile *file, void *ptr, size_t size)
|
||||
{
|
||||
/* Buffer full, dump it out */
|
||||
if (file->dirty)
|
||||
{
|
||||
BufFileDumpBuffer(file);
|
||||
if (file->dirty)
|
||||
break; /* I/O error */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Hmm, went directly from reading to writing? */
|
||||
@ -449,19 +458,15 @@ BufFileWrite(BufFile *file, void *ptr, size_t size)
|
||||
/*
|
||||
* BufFileFlush
|
||||
*
|
||||
* Like fflush()
|
||||
* Like fflush(), except that I/O errors are reported with ereport().
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
BufFileFlush(BufFile *file)
|
||||
{
|
||||
if (file->dirty)
|
||||
{
|
||||
BufFileDumpBuffer(file);
|
||||
if (file->dirty)
|
||||
return EOF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
Assert(!file->dirty);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -470,6 +475,7 @@ BufFileFlush(BufFile *file)
|
||||
* Like fseek(), except that target position needs two values in order to
|
||||
* work when logical filesize exceeds maximum value representable by long.
|
||||
* We do not support relative seeks across more than LONG_MAX, however.
|
||||
* I/O errors are reported by ereport().
|
||||
*
|
||||
* Result is 0 if OK, EOF if not. Logical position is not moved if an
|
||||
* impossible seek is attempted.
|
||||
@ -527,8 +533,7 @@ BufFileSeek(BufFile *file, int fileno, off_t offset, int whence)
|
||||
return 0;
|
||||
}
|
||||
/* Otherwise, must reposition buffer, so flush any dirty data */
|
||||
if (BufFileFlush(file) != 0)
|
||||
return EOF;
|
||||
BufFileFlush(file);
|
||||
|
||||
/*
|
||||
* At this point and no sooner, check for seek past last segment. The
|
||||
|
@ -202,12 +202,12 @@ static void ltsDumpBuffer(LogicalTapeSet *lts, LogicalTape *lt);
|
||||
static void
|
||||
ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
|
||||
{
|
||||
if (BufFileSeekBlock(lts->pfile, blocknum) != 0 ||
|
||||
BufFileWrite(lts->pfile, buffer, BLCKSZ) != BLCKSZ)
|
||||
if (BufFileSeekBlock(lts->pfile, blocknum) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not write block %ld of temporary file: %m",
|
||||
errmsg("could not seek to block %ld of temporary file",
|
||||
blocknum)));
|
||||
BufFileWrite(lts->pfile, buffer, BLCKSZ);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -219,12 +219,19 @@ ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
|
||||
static void
|
||||
ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
|
||||
{
|
||||
if (BufFileSeekBlock(lts->pfile, blocknum) != 0 ||
|
||||
BufFileRead(lts->pfile, buffer, BLCKSZ) != BLCKSZ)
|
||||
size_t nread;
|
||||
|
||||
if (BufFileSeekBlock(lts->pfile, blocknum) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read block %ld of temporary file: %m",
|
||||
errmsg("could not seek to block %ld of temporary file",
|
||||
blocknum)));
|
||||
nread = BufFileRead(lts->pfile, buffer, BLCKSZ);
|
||||
if (nread != BLCKSZ)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read block %ld of temporary file: read only %zu of %zu bytes",
|
||||
blocknum, nread, (size_t) BLCKSZ)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -512,7 +512,7 @@ tuplestore_select_read_pointer(Tuplestorestate *state, int ptr)
|
||||
SEEK_SET) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in tuplestore temporary file: %m")));
|
||||
errmsg("could not seek in tuplestore temporary file")));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -522,7 +522,7 @@ tuplestore_select_read_pointer(Tuplestorestate *state, int ptr)
|
||||
SEEK_SET) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in tuplestore temporary file: %m")));
|
||||
errmsg("could not seek in tuplestore temporary file")));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -849,7 +849,7 @@ tuplestore_puttuple_common(Tuplestorestate *state, void *tuple)
|
||||
SEEK_SET) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in tuplestore temporary file: %m")));
|
||||
errmsg("could not seek in tuplestore temporary file")));
|
||||
state->status = TSS_WRITEFILE;
|
||||
|
||||
/*
|
||||
@ -953,7 +953,7 @@ tuplestore_gettuple(Tuplestorestate *state, bool forward,
|
||||
SEEK_SET) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in tuplestore temporary file: %m")));
|
||||
errmsg("could not seek in tuplestore temporary file")));
|
||||
state->status = TSS_READFILE;
|
||||
/* FALL THRU into READFILE case */
|
||||
|
||||
@ -1017,7 +1017,7 @@ tuplestore_gettuple(Tuplestorestate *state, bool forward,
|
||||
SEEK_CUR) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in tuplestore temporary file: %m")));
|
||||
errmsg("could not seek in tuplestore temporary file")));
|
||||
Assert(!state->truncated);
|
||||
return NULL;
|
||||
}
|
||||
@ -1034,7 +1034,7 @@ tuplestore_gettuple(Tuplestorestate *state, bool forward,
|
||||
SEEK_CUR) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in tuplestore temporary file: %m")));
|
||||
errmsg("could not seek in tuplestore temporary file")));
|
||||
tup = READTUP(state, tuplen);
|
||||
return tup;
|
||||
|
||||
@ -1236,7 +1236,7 @@ tuplestore_rescan(Tuplestorestate *state)
|
||||
if (BufFileSeek(state->myfile, 0, 0L, SEEK_SET) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in tuplestore temporary file: %m")));
|
||||
errmsg("could not seek in tuplestore temporary file")));
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "invalid tuplestore state");
|
||||
@ -1301,7 +1301,7 @@ tuplestore_copy_read_pointer(Tuplestorestate *state,
|
||||
SEEK_SET) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in tuplestore temporary file: %m")));
|
||||
errmsg("could not seek in tuplestore temporary file")));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1310,7 +1310,7 @@ tuplestore_copy_read_pointer(Tuplestorestate *state,
|
||||
SEEK_SET) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not seek in tuplestore temporary file: %m")));
|
||||
errmsg("could not seek in tuplestore temporary file")));
|
||||
}
|
||||
}
|
||||
else if (srcptr == state->activeptr)
|
||||
@ -1457,7 +1457,8 @@ getlen(Tuplestorestate *state, bool eofOK)
|
||||
if (nbytes != 0 || !eofOK)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read from tuplestore temporary file: %m")));
|
||||
errmsg("could not read from tuplestore temporary file: read only %zu of %zu bytes",
|
||||
nbytes, sizeof(len))));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1494,22 +1495,10 @@ writetup_heap(Tuplestorestate *state, void *tup)
|
||||
/* total on-disk footprint: */
|
||||
unsigned int tuplen = tupbodylen + sizeof(int);
|
||||
|
||||
if (BufFileWrite(state->myfile, (void *) &tuplen,
|
||||
sizeof(tuplen)) != sizeof(tuplen))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not write to tuplestore temporary file: %m")));
|
||||
if (BufFileWrite(state->myfile, (void *) tupbody,
|
||||
tupbodylen) != (size_t) tupbodylen)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not write to tuplestore temporary file: %m")));
|
||||
BufFileWrite(state->myfile, (void *) &tuplen, sizeof(tuplen));
|
||||
BufFileWrite(state->myfile, (void *) tupbody, tupbodylen);
|
||||
if (state->backward) /* need trailing length word? */
|
||||
if (BufFileWrite(state->myfile, (void *) &tuplen,
|
||||
sizeof(tuplen)) != sizeof(tuplen))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not write to tuplestore temporary file: %m")));
|
||||
BufFileWrite(state->myfile, (void *) &tuplen, sizeof(tuplen));
|
||||
|
||||
FREEMEM(state, GetMemoryChunkSpace(tuple));
|
||||
heap_free_minimal_tuple(tuple);
|
||||
@ -1522,20 +1511,25 @@ readtup_heap(Tuplestorestate *state, unsigned int len)
|
||||
unsigned int tuplen = tupbodylen + MINIMAL_TUPLE_DATA_OFFSET;
|
||||
MinimalTuple tuple = (MinimalTuple) palloc(tuplen);
|
||||
char *tupbody = (char *) tuple + MINIMAL_TUPLE_DATA_OFFSET;
|
||||
size_t nread;
|
||||
|
||||
USEMEM(state, GetMemoryChunkSpace(tuple));
|
||||
/* read in the tuple proper */
|
||||
tuple->t_len = tuplen;
|
||||
if (BufFileRead(state->myfile, (void *) tupbody,
|
||||
tupbodylen) != (size_t) tupbodylen)
|
||||
nread = BufFileRead(state->myfile, (void *) tupbody, tupbodylen);
|
||||
if (nread != (size_t) tupbodylen)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read from tuplestore temporary file: %m")));
|
||||
errmsg("could not read from tuplestore temporary file: read only %zu of %zu bytes",
|
||||
nread, (size_t) tupbodylen)));
|
||||
if (state->backward) /* need trailing length word? */
|
||||
if (BufFileRead(state->myfile, (void *) &tuplen,
|
||||
sizeof(tuplen)) != sizeof(tuplen))
|
||||
{
|
||||
nread = BufFileRead(state->myfile, (void *) &tuplen, sizeof(tuplen));
|
||||
if (nread != sizeof(tuplen))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read from tuplestore temporary file: %m")));
|
||||
errmsg("could not read from tuplestore temporary file: read only %zu of %zu bytes",
|
||||
nread, sizeof(tuplen))));
|
||||
}
|
||||
return (void *) tuple;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user