From 8e21bf52504616024618f3386dc68e8936405dc2 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 29 Jul 2010 19:24:05 +0000 Subject: 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(-) (limited to 'src/backend/commands/tablecmds.c') diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f82109bab35..bce8750d293 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.142.4.13 2010/07/29 16:15:47 rhaas Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.142.4.14 2010/07/29 19:24:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -5729,11 +5729,11 @@ static void copy_relation_data(Relation rel, SMgrRelation dst) { SMgrRelation src; + char *buf; + Page page; bool use_wal; BlockNumber nblocks; BlockNumber blkno; - char buf[BLCKSZ]; - Page page = (Page) buf; /* * Since we copy the data directly without looking at the shared @@ -5744,6 +5744,15 @@ copy_relation_data(Relation rel, SMgrRelation dst) */ FlushRelationBuffers(rel, 0); + /* + * 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 PageSetLSN fail. + */ + buf = (char *) palloc(BLCKSZ); + page = (Page) buf; + /* * We need to log the copied data in WAL iff WAL archiving is enabled * AND it's not a temp rel. @@ -5807,6 +5816,8 @@ copy_relation_data(Relation rel, SMgrRelation dst) smgrwrite(dst, 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 -- cgit v1.2.3