Fix another longstanding problem in copy_relation_data: it was blithely
authorTom Lane <[email protected]>
Thu, 29 Jul 2010 19:23:44 +0000 (19:23 +0000)
committerTom Lane <[email protected]>
Thu, 29 Jul 2010 19:23:44 +0000 (19:23 +0000)
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

index 4181c1a1873510d86bda6c2a22c944d5d2d3d08a..14757befdff06a127032a52729e550c3af42694c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.242.2.6 2010/07/01 14:11:42 rhaas Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.242.2.7 2010/07/29 19:23:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -5960,11 +5960,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 file directly without looking at the shared buffers,
@@ -5974,6 +5974,15 @@ copy_relation_data(Relation rel, SMgrRelation dst)
     */
    FlushRelationBuffers(rel);
 
+   /*
+    * 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 is enabled AND
     * it's not a temp rel.
@@ -6003,6 +6012,8 @@ copy_relation_data(Relation rel, SMgrRelation dst)
        smgrextend(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 since the rel