On Tue, May 22, 2018 at 04:51:00PM +0900, Kyotaro HORIGUCHI wrote: > I see the same issue in snapbuild.c(4 places). > > | readBytes = read(fd, &ondisk, SnapBuildOnDiskConstantSize); > | pgstat_report_wait_end(); > | if (readBytes != SnapBuildOnDiskConstantSize) > | { > | CloseTransientFile(fd); > | ereport(ERROR, > | (errcode_for_file_access(), > | errmsg("could not read file \"%s\", read %d of %d: %m", > | path, readBytes, (int) SnapBuildOnDiskConstantSize))); > | }
Four times the same pattern, which also bloat errno when closing the file descriptor. I did not catch those. > and walsender.c (2 places) > > | if (nread <= 0) > | ereport(ERROR, > | (errcode_for_file_access(), > | errmsg("could not read file \"%s\": %m", > | path))); Those two ones I saw, but I was not sure if it is worth the complication to error on an empty file. We could do something like the attached which would be an improvement in readability? > and pg_receivewal.c > > | if (read(fd, (char *) buf, sizeof(buf)) != sizeof(buf)) > | { > | fprintf(stderr, _("%s: could not read compressed file \"%s\": %s\n"), > | progname, fullpath, strerror(errno)); Okay. > pg_waldump.c > > | if (readbytes <= 0) > ... > | fatal_error("could not read from log file %s, offset %u, length %d: %s", > | fname, sendOff, segbytes, strerror(err)); > > > A bit different issue, but in pg_waldump.c, search_directory can > check uninitialized errno when read returns a non-zero value. Yeah, the error message could be improved as well if the result is an empty file. Updated patch is attached. Thanks for your review. -- Michael
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 87942b4cca..d487347cc6 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -683,6 +683,11 @@ SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno) pgstat_report_wait_start(WAIT_EVENT_SLRU_READ); if (read(fd, shared->page_buffer[slotno], BLCKSZ) != BLCKSZ) { + /* + * XXX: Note that this may actually report sucess if the number + * of bytes read is positive, but lacking data so that errno is + * not set. + */ pgstat_report_wait_end(); slru_errcause = SLRU_READ_FAILED; slru_errno = errno; diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 65194db70e..52f634e706 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -1219,6 +1219,7 @@ ReadTwoPhaseFile(TransactionId xid, bool give_warnings) uint32 crc_offset; pg_crc32c calc_crc, file_crc; + int r; TwoPhaseFilePath(path, xid); @@ -1272,15 +1273,28 @@ ReadTwoPhaseFile(TransactionId xid, bool give_warnings) buf = (char *) palloc(stat.st_size); pgstat_report_wait_start(WAIT_EVENT_TWOPHASE_FILE_READ); - if (read(fd, buf, stat.st_size) != stat.st_size) + r = read(fd, buf, stat.st_size); + if (r != stat.st_size) { + int save_errno = errno; + pgstat_report_wait_end(); CloseTransientFile(fd); if (give_warnings) - ereport(WARNING, - (errcode_for_file_access(), - errmsg("could not read two-phase state file \"%s\": %m", - path))); + { + if (r < 0) + { + errno = save_errno; + ereport(WARNING, + (errcode_for_file_access(), + errmsg("could not read two-phase state file \"%s\": %m", + path))); + } + else + ereport(WARNING, + (errmsg("could not read two-phase state file \"%s\": %d read, expected %zu", + path, r, stat.st_size))); + } pfree(buf); return NULL; } diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index adbd6a2126..2f2102eb71 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -3395,21 +3395,24 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno, if (nread > 0) { + int r; + if (nread > sizeof(buffer)) nread = sizeof(buffer); errno = 0; pgstat_report_wait_start(WAIT_EVENT_WAL_COPY_READ); - if (read(srcfd, buffer, nread) != nread) + r = read(srcfd, buffer, nread); + if (r != nread) { - if (errno != 0) + if (r < 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not read file \"%s\": %m", path))); else ereport(ERROR, - (errmsg("not enough data in file \"%s\"", - path))); + (errmsg("not enough data in file \"%s\": read %d, expected %d", + path, r, nread))); } pgstat_report_wait_end(); } @@ -11594,6 +11597,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, int emode = private->emode; uint32 targetPageOff; XLogSegNo targetSegNo PG_USED_FOR_ASSERTS_ONLY; + int r; XLByteToSeg(targetPagePtr, targetSegNo, wal_segment_size); targetPageOff = XLogSegmentOffset(targetPagePtr, wal_segment_size); @@ -11675,8 +11679,10 @@ retry: if (lseek(readFile, (off_t) readOff, SEEK_SET) < 0) { char fname[MAXFNAMELEN]; + int save_errno = errno; XLogFileName(fname, curFileTLI, readSegNo, wal_segment_size); + errno = save_errno; ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen), (errcode_for_file_access(), errmsg("could not seek in log segment %s to offset %u: %m", @@ -11685,16 +11691,28 @@ retry: } pgstat_report_wait_start(WAIT_EVENT_WAL_READ); - if (read(readFile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ) + r = read(readFile, readBuf, XLOG_BLCKSZ); + if (r != XLOG_BLCKSZ) { char fname[MAXFNAMELEN]; + int save_errno = errno; pgstat_report_wait_end(); XLogFileName(fname, curFileTLI, readSegNo, wal_segment_size); - ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen), - (errcode_for_file_access(), - errmsg("could not read from log segment %s, offset %u: %m", - fname, readOff))); + + if (r < 0) + { + errno = save_errno; + ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen), + (errcode_for_file_access(), + errmsg("could not read from log segment %s, offset %u: %m", + fname, readOff))); + } + else + ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen), + (errmsg("could not read from log segment %s, offset %u: read %d, expected %d", + fname, readOff, r, XLOG_BLCKSZ))); + goto next_record_is_invalid; } pgstat_report_wait_end(); diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 963878a5d8..c39d023d22 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -697,9 +697,16 @@ StartupReplicationOrigin(void) /* verify magic, that is written even if nothing was active */ readBytes = read(fd, &magic, sizeof(magic)); if (readBytes != sizeof(magic)) - ereport(PANIC, - (errmsg("could not read file \"%s\": %m", - path))); + { + if (readBytes < 0) + ereport(PANIC, + (errmsg("could not read file \"%s\": %m", + path))); + else + ereport(PANIC, + (errmsg("could not read file \"%s\": %d read of %zu", + path, readBytes, sizeof(magic)))); + } COMP_CRC32C(crc, &magic, sizeof(magic)); if (magic != REPLICATION_STATE_MAGIC) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index 4123cdebcf..f99a885c5d 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1708,11 +1708,20 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) pgstat_report_wait_end(); if (readBytes != SnapBuildOnDiskConstantSize) { + int save_errno = errno; CloseTransientFile(fd); - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not read file \"%s\", read %d of %d: %m", - path, readBytes, (int) SnapBuildOnDiskConstantSize))); + + if (readBytes < 0) + { + errno = save_errno; + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", path))); + } + else + ereport(ERROR, + (errmsg("could not read file \"%s\": read %d of %zu", + path, readBytes, SnapBuildOnDiskConstantSize))); } if (ondisk.magic != SNAPBUILD_MAGIC) @@ -1736,11 +1745,20 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) pgstat_report_wait_end(); if (readBytes != sizeof(SnapBuild)) { + int save_errno = errno; CloseTransientFile(fd); - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not read file \"%s\", read %d of %d: %m", - path, readBytes, (int) sizeof(SnapBuild)))); + + if (readBytes < 0) + { + errno = save_errno; + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", path))); + } + else + ereport(ERROR, + (errmsg("could not read file \"%s\": read %d of %zu", + path, readBytes, sizeof(SnapBuild)))); } COMP_CRC32C(checksum, &ondisk.builder, sizeof(SnapBuild)); @@ -1753,11 +1771,20 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) pgstat_report_wait_end(); if (readBytes != sz) { + int save_errno = errno; CloseTransientFile(fd); - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not read file \"%s\", read %d of %d: %m", - path, readBytes, (int) sz))); + + if (readBytes < 0) + { + errno = save_errno; + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", path))); + } + else + ereport(ERROR, + (errmsg("could not read file \"%s\": read %d of %zu", + path, readBytes, sz))); } COMP_CRC32C(checksum, ondisk.builder.was_running.was_xip, sz); @@ -1769,11 +1796,20 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) pgstat_report_wait_end(); if (readBytes != sz) { + int save_errno = errno; CloseTransientFile(fd); - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not read file \"%s\", read %d of %d: %m", - path, readBytes, (int) sz))); + + if (readBytes < 0) + { + errno = save_errno; + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", path))); + } + else + ereport(ERROR, + (errmsg("could not read file \"%s\": read %d of %zu", + path, readBytes, sz))); } COMP_CRC32C(checksum, ondisk.builder.committed.xip, sz); diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 056628fe8e..cc64ff22ac 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -1394,11 +1394,15 @@ RestoreSlotFromDisk(const char *name) CloseTransientFile(fd); errno = saved_errno; - ereport(PANIC, - (errcode_for_file_access(), - errmsg("could not read file \"%s\", read %d of %u: %m", - path, readBytes, - (uint32) ReplicationSlotOnDiskConstantSize))); + if (readBytes < 0) + ereport(PANIC, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", path))); + else + ereport(PANIC, + (errmsg("could not read file \"%s\": read %d of %u", + path, readBytes, + (uint32) ReplicationSlotOnDiskConstantSize))); } /* verify magic */ @@ -1434,10 +1438,14 @@ RestoreSlotFromDisk(const char *name) CloseTransientFile(fd); errno = saved_errno; - ereport(PANIC, - (errcode_for_file_access(), - errmsg("could not read file \"%s\", read %d of %u: %m", - path, readBytes, cp.length))); + if (readBytes < 0) + ereport(PANIC, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", path))); + else + ereport(PANIC, + (errmsg("could not read file \"%s\": read %d of %u", + path, readBytes, cp.length))); } CloseTransientFile(fd); diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index e47ddca6bc..727c3acbcb 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -501,11 +501,16 @@ SendTimeLineHistory(TimeLineHistoryCmd *cmd) pgstat_report_wait_start(WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ); nread = read(fd, rbuf, sizeof(rbuf)); pgstat_report_wait_end(); - if (nread <= 0) + if (nread < 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not read file \"%s\": %m", path))); + else if (nread == 0) + ereport(ERROR, + (errmsg("could not read empty file \"%s\"", + path))); + pq_sendbytes(&buf, rbuf, nread); bytesleft -= nread; } @@ -2425,7 +2430,7 @@ retry: pgstat_report_wait_start(WAIT_EVENT_WAL_READ); readbytes = read(sendFile, p, segbytes); pgstat_report_wait_end(); - if (readbytes <= 0) + if (readbytes < 0) { ereport(ERROR, (errcode_for_file_access(), @@ -2433,6 +2438,13 @@ retry: XLogFileNameP(curFileTimeLine, sendSegNo), sendOff, (unsigned long) segbytes))); } + else if (readbytes == 0) + { + ereport(ERROR, + (errmsg("could not read any data from log segment %s, offset %u, length %lu", + XLogFileNameP(curFileTimeLine, sendSegNo), + sendOff, (unsigned long) segbytes))); + } /* Update state for read */ recptr += readbytes; diff --git a/src/backend/utils/cache/relmapper.c b/src/backend/utils/cache/relmapper.c index 99d095f2df..c4839b11f6 100644 --- a/src/backend/utils/cache/relmapper.c +++ b/src/backend/utils/cache/relmapper.c @@ -629,6 +629,7 @@ load_relmap_file(bool shared) char mapfilename[MAXPGPATH]; pg_crc32c crc; int fd; + int r; if (shared) { @@ -659,11 +660,19 @@ load_relmap_file(bool shared) * are able to access any relation that's affected by the change. */ pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_READ); - if (read(fd, map, sizeof(RelMapFile)) != sizeof(RelMapFile)) - ereport(FATAL, - (errcode_for_file_access(), - errmsg("could not read relation mapping file \"%s\": %m", - mapfilename))); + r = read(fd, map, sizeof(RelMapFile)); + if (r != sizeof(RelMapFile)) + { + if (r < 0) + ereport(FATAL, + (errcode_for_file_access(), + errmsg("could not read relation mapping file \"%s\": %m", + mapfilename))); + else + ereport(FATAL, + (errmsg("could not read relation mapping file \"%s\": %d read, expected %zu", + mapfilename, r, sizeof(RelMapFile)))); + } pgstat_report_wait_end(); CloseTransientFile(fd); diff --git a/src/bin/pg_basebackup/pg_receivewal.c b/src/bin/pg_basebackup/pg_receivewal.c index 071b32d19d..ddc3e90e79 100644 --- a/src/bin/pg_basebackup/pg_receivewal.c +++ b/src/bin/pg_basebackup/pg_receivewal.c @@ -284,6 +284,7 @@ FindStreamingStart(uint32 *tli) char buf[4]; int bytes_out; char fullpath[MAXPGPATH * 2]; + int r; snprintf(fullpath, sizeof(fullpath), "%s/%s", basedir, dirent->d_name); @@ -300,10 +301,16 @@ FindStreamingStart(uint32 *tli) progname, fullpath, strerror(errno)); disconnect_and_exit(1); } - if (read(fd, (char *) buf, sizeof(buf)) != sizeof(buf)) + r = read(fd, (char *) buf, sizeof(buf)); + if (r != sizeof(buf)) { - fprintf(stderr, _("%s: could not read compressed file \"%s\": %s\n"), - progname, fullpath, strerror(errno)); + if (r < 0) + fprintf(stderr, _("%s: could not read compressed file \"%s\": %s\n"), + progname, fullpath, strerror(errno)); + else + fprintf(stderr, + _("%s: could not read compressed file \"%s\": read %d out of %zu\n"), + progname, fullpath, r, sizeof(buf)); disconnect_and_exit(1); } diff --git a/src/bin/pg_rewind/file_ops.c b/src/bin/pg_rewind/file_ops.c index 94bcc13ae8..174ca7216d 100644 --- a/src/bin/pg_rewind/file_ops.c +++ b/src/bin/pg_rewind/file_ops.c @@ -289,6 +289,7 @@ slurpFile(const char *datadir, const char *path, size_t *filesize) struct stat statbuf; char fullpath[MAXPGPATH]; int len; + int r; snprintf(fullpath, sizeof(fullpath), "%s/%s", datadir, path); @@ -304,9 +305,17 @@ slurpFile(const char *datadir, const char *path, size_t *filesize) buffer = pg_malloc(len + 1); - if (read(fd, buffer, len) != len) - pg_fatal("could not read file \"%s\": %s\n", - fullpath, strerror(errno)); + r = read(fd, buffer, len); + if (r != len) + { + if (r < 0) + pg_fatal("could not read file \"%s\": %s\n", + fullpath, strerror(errno)); + else + pg_fatal("could not read file \"%s\": read %d, expected %d\n", + fullpath, r, len); + + } close(fd); /* Zero-terminate the buffer. */ diff --git a/src/bin/pg_rewind/parsexlog.c b/src/bin/pg_rewind/parsexlog.c index b4c1f827a6..4f27cfe42b 100644 --- a/src/bin/pg_rewind/parsexlog.c +++ b/src/bin/pg_rewind/parsexlog.c @@ -246,6 +246,7 @@ SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, uint32 targetPageOff; XLogRecPtr targetSegEnd; XLogSegNo targetSegNo; + int r; XLByteToSeg(targetPagePtr, targetSegNo, WalSegSz); XLogSegNoOffsetToRecPtr(targetSegNo + 1, 0, targetSegEnd, WalSegSz); @@ -309,10 +310,17 @@ SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, return -1; } - if (read(xlogreadfd, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ) + + r = read(xlogreadfd, readBuf, XLOG_BLCKSZ); + if (r != XLOG_BLCKSZ) { - printf(_("could not read from file \"%s\": %s\n"), xlogfpath, - strerror(errno)); + if (r < 0) + printf(_("could not read from file \"%s\": %s\n"), xlogfpath, + strerror(errno)); + else + printf(_("could not read from file \"%s\": read %d, expected %d\n"), + xlogfpath, r, XLOG_BLCKSZ); + return -1; } diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c index 5c4f38e597..61464d44c5 100644 --- a/src/bin/pg_waldump/pg_waldump.c +++ b/src/bin/pg_waldump/pg_waldump.c @@ -210,8 +210,10 @@ search_directory(const char *directory, const char *fname) if (fd >= 0) { char buf[XLOG_BLCKSZ]; + int r; - if (read(fd, buf, XLOG_BLCKSZ) == XLOG_BLCKSZ) + r = read(fd, buf, XLOG_BLCKSZ); + if (r == XLOG_BLCKSZ) { XLogLongPageHeader longhdr = (XLogLongPageHeader) buf; @@ -229,7 +231,8 @@ search_directory(const char *directory, const char *fname) fatal_error("could not read file \"%s\": %s", fname, strerror(errno)); else - fatal_error("not enough data in file \"%s\"", fname); + fatal_error("not enough data in file \"%s\": %d read, %d expected", + fname, r, XLOG_BLCKSZ); } close(fd); return true; @@ -411,11 +414,17 @@ XLogDumpXLogRead(const char *directory, TimeLineID timeline_id, { int err = errno; char fname[MAXPGPATH]; + int save_errno = errno; XLogFileName(fname, timeline_id, sendSegNo, WalSegSz); + errno = save_errno; - fatal_error("could not read from log file %s, offset %u, length %d: %s", - fname, sendOff, segbytes, strerror(err)); + if (readbytes < 0) + fatal_error("could not read from log file %s, offset %u, length %d: %s", + fname, sendOff, segbytes, strerror(err)); + else if (readbytes == 0) + fatal_error("could not read any data from log file %s, offset %u, length %d", + fname, sendOff, segbytes); } /* Update state for read */
signature.asc
Description: PGP signature