diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index d34182a7b0..9c06aadb38 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -106,14 +106,11 @@ read_binary_file(const char *filename, int64 seek_offset, int64 bytes_to_read,
 				 bool missing_ok)
 {
 	bytea	   *buf;
-	size_t		nbytes = 0;
 	FILE	   *file;
+	size_t		nbytes;
 
-	/* clamp request size to what we can actually deliver */
-	if (bytes_to_read > (int64) (MaxAllocSize - VARHDRSZ))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("requested length too large")));
+    /* Read zero byte? */
+	Assert(bytes_to_read != 0);
 
 	if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
 	{
@@ -126,83 +123,38 @@ read_binary_file(const char *filename, int64 seek_offset, int64 bytes_to_read,
 							filename)));
 	}
 
-	if (fseeko(file, (off_t) seek_offset,
-			   (seek_offset >= 0) ? SEEK_SET : SEEK_END) != 0)
+    /* Avoid syscall fseeko if seek_offset is zero */
+	if (seek_offset != 0 &&
+	    fseeko(file, (off_t) seek_offset,
+			   (seek_offset > 0) ? SEEK_SET : SEEK_END) != 0)
 		ereport(ERROR,
 				(errcode_for_file_access(),
 				 errmsg("could not seek in file \"%s\": %m", filename)));
 
+    /* If passed explicit read size just do it */
 	if (bytes_to_read >= 0)
-	{
-		/* If passed explicit read size just do it */
-		buf = (bytea *) palloc((Size) bytes_to_read + VARHDRSZ);
-
-		nbytes = fread(VARDATA(buf), 1, (size_t) bytes_to_read, file);
-	}
+	    nbytes = bytes_to_read;
 	else
-	{
-		/* Negative read size, read rest of file */
-		StringInfoData sbuf;
+        nbytes = ftello(file);
 
-		initStringInfo(&sbuf);
-		/* Leave room in the buffer for the varlena length word */
-		sbuf.len += VARHDRSZ;
-		Assert(sbuf.len < sbuf.maxlen);
-
-		while (!(feof(file) || ferror(file)))
-		{
-			size_t		rbytes;
-
-			/* Minimum amount to read at a time */
-#define MIN_READ_SIZE 4096
-
-			/*
-			 * If not at end of file, and sbuf.len is equal to
-			 * MaxAllocSize - 1, then either the file is too large, or
-			 * there is nothing left to read. Attempt to read one more
-			 * byte to see if the end of file has been reached. If not,
-			 * the file is too large; we'd rather give the error message
-			 * for that ourselves.
-			 */
-			if (sbuf.len == MaxAllocSize - 1)
-			{
-				char	rbuf[1];
-
-				if (fread(rbuf, 1, 1, file) != 0 || !feof(file))
-					ereport(ERROR,
-							(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
-							 errmsg("file length too large")));
-				else
-					break;
-			}
-
-			/* OK, ensure that we can read at least MIN_READ_SIZE */
-			enlargeStringInfo(&sbuf, MIN_READ_SIZE);
-
-			/*
-			 * stringinfo.c likes to allocate in powers of 2, so it's likely
-			 * that much more space is available than we asked for.  Use all
-			 * of it, rather than making more fread calls than necessary.
-			 */
-			rbytes = fread(sbuf.data + sbuf.len, 1,
-						   (size_t) (sbuf.maxlen - sbuf.len - 1), file);
-			sbuf.len += rbytes;
-			nbytes += rbytes;
-		}
+	/* clamp request size to what we can actually deliver */
+	if (nbytes > ((int64) MaxAllocSize - VARHDRSZ))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("requested length too large")));
 
-		/* Now we can commandeer the stringinfo's buffer as the result */
-		buf = (bytea *) sbuf.data;
-	}
+	buf = (bytea *) palloc((Size) nbytes + VARHDRSZ);
+	nbytes = fread(VARDATA(buf), 1, nbytes, file);
 
 	if (ferror(file))
 		ereport(ERROR,
 				(errcode_for_file_access(),
 				 errmsg("could not read file \"%s\": %m", filename)));
 
-	SET_VARSIZE(buf, nbytes + VARHDRSZ);
-
 	FreeFile(file);
 
+	SET_VARSIZE(buf, nbytes + VARHDRSZ);
+
 	return buf;
 }