diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index d34182a7b0..250e55ffe0 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -106,11 +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 = 0;
 
 	/* clamp request size to what we can actually deliver */
-	if (bytes_to_read > (int64) (MaxAllocSize - VARHDRSZ))
+	if (bytes_to_read > ((int64) MaxAllocSize - VARHDRSZ))
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("requested length too large")));
@@ -126,69 +126,60 @@ 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 (bytes_to_read >= 0)
+	if (bytes_to_read > 0)
 	{
 		/* If passed explicit read size just do it */
 		buf = (bytea *) palloc((Size) bytes_to_read + VARHDRSZ);
 
+		/* Bypass fread buffer: less copies. */
+		setvbuf(file, VARDATA(buf), _IOFBF, (size_t) bytes_to_read);
+
 		nbytes = fread(VARDATA(buf), 1, (size_t) bytes_to_read, file);
 	}
 	else
 	{
 		/* Negative read size, read rest of file */
-		StringInfoData sbuf;
+		StringInfoData	sbuf;
+		size_t			rbytes;
+		int				fd;
 
 		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 */
+		/* 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;
-		}
+        fd = fileno(file);
+        nbytes = 0;
+        do {
+            /* 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 read calls than necessary.
+ 			 */
+		    rbytes = read(fd, sbuf.data + sbuf.len, (size_t) (sbuf.maxlen - sbuf.len - 1));
+
+ 			sbuf.len += rbytes;
+ 			nbytes += rbytes;
+		} while(rbytes != 0 && sbuf.len < ((int64) MaxAllocSize - VARHDRSZ));
+
+	    if (sbuf.len > ((int64) MaxAllocSize - VARHDRSZ))
+			ereport(ERROR,
+					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+					 errmsg("file length too large")));
 
 		/* Now we can commandeer the stringinfo's buffer as the result */
 		buf = (bytea *) sbuf.data;
@@ -199,10 +190,10 @@ read_binary_file(const char *filename, int64 seek_offset, int64 bytes_to_read,
 				(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;
 }