From 984d56b80f5a945db2bfa80499b5ed913848242b Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 29 Jul 2010 19:23:20 +0000
Subject: [PATCH] Fix another longstanding problem in copy_relation_data: it
 was blithely assuming that a local char[] array would be aligned on at least
 a word boundary.  There are architectures on which that is pretty much
 guaranteed to NOT be the case ... and those arches also don't like
 non-aligned memory accesses, meaning that log_newpage() would crash if it
 ever got invoked. Even on Intel-ish machines there's a potential for a large
 performance penalty from doing I/O to an inadequately aligned buffer.  So
 palloc it instead.

Backpatch to 8.0 --- 7.4 doesn't have this code.
---
 src/backend/commands/tablecmds.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 431b06568bd..b16232a0b52 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.336 2010/07/29 11:06:34 sriggs Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.337 2010/07/29 19:23:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -7230,11 +7230,20 @@ static void
 copy_relation_data(SMgrRelation src, SMgrRelation dst,
 				   ForkNumber forkNum, bool istemp)
 {
+	char	   *buf;
+	Page		page;
 	bool		use_wal;
 	BlockNumber nblocks;
 	BlockNumber blkno;
-	char		buf[BLCKSZ];
-	Page		page = (Page) buf;
+
+	/*
+	 * palloc the buffer so that it's MAXALIGN'd.  If it were just a local
+	 * char[] array, the compiler might align it on any byte boundary, which
+	 * can seriously hurt transfer speed to and from the kernel; not to
+	 * mention possibly making log_newpage's accesses to the page header fail.
+	 */
+	buf = (char *) palloc(BLCKSZ);
+	page = (Page) buf;
 
 	/*
 	 * We need to log the copied data in WAL iff WAL archiving/streaming is
@@ -7263,6 +7272,8 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst,
 		smgrextend(dst, forkNum, blkno, buf, true);
 	}
 
+	pfree(buf);
+
 	/*
 	 * If the rel isn't temp, we must fsync it down to disk before it's safe
 	 * to commit the transaction.  (For a temp rel we don't care since the rel
-- 
GitLab