From 1331cc6c1ad2beba7985523508d6722dc865c337 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Fri, 11 May 2012 09:46:42 -0400 Subject: [PATCH] Prevent loss of init fork when truncating an unlogged table. Fixes bug #6635, reported by Akira Kurosawa. --- src/backend/catalog/heap.c | 32 +++++++++++++++++--------------- src/backend/commands/tablecmds.c | 4 ++++ src/include/catalog/heap.h | 2 ++ 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index d029a25c11..2734ec8658 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -1306,24 +1306,10 @@ heap_create_with_catalog(const char *relname, if (oncommit != ONCOMMIT_NOOP) register_on_commit_action(relid, oncommit); - /* - * If this is an unlogged relation, it needs an init fork so that it can - * be correctly reinitialized on restart. Since we're going to do an - * immediate sync, we only need to xlog this if archiving or streaming is - * enabled. And the immediate sync is required, because otherwise there's - * no guarantee that this will hit the disk before the next checkpoint - * moves the redo pointer. - */ if (relpersistence == RELPERSISTENCE_UNLOGGED) { Assert(relkind == RELKIND_RELATION || relkind == RELKIND_TOASTVALUE); - - RelationOpenSmgr(new_rel_desc); - smgrcreate(new_rel_desc->rd_smgr, INIT_FORKNUM, false); - if (XLogIsNeeded()) - log_smgrcreate(&new_rel_desc->rd_smgr->smgr_rnode.node, - INIT_FORKNUM); - smgrimmedsync(new_rel_desc->rd_smgr, INIT_FORKNUM); + heap_create_init_fork(new_rel_desc); } /* @@ -1336,6 +1322,22 @@ heap_create_with_catalog(const char *relname, return relid; } +/* + * Set up an init fork for an unlogged table so that it can be correctly + * reinitialized on restart. Since we're going to do an immediate sync, we + * only need to xlog this if archiving or streaming is enabled. And the + * immediate sync is required, because otherwise there's no guarantee that + * this will hit the disk before the next checkpoint moves the redo pointer. + */ +void +heap_create_init_fork(Relation rel) +{ + RelationOpenSmgr(rel); + smgrcreate(rel->rd_smgr, INIT_FORKNUM, false); + if (XLogIsNeeded()) + log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM); + smgrimmedsync(rel->rd_smgr, INIT_FORKNUM); +} /* * RelationRemoveInheritance diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index c94d945722..e23a3dab3c 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1155,6 +1155,8 @@ ExecuteTruncate(TruncateStmt *stmt) * deletion at commit. */ RelationSetNewRelfilenode(rel, RecentXmin); + if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED) + heap_create_init_fork(rel); heap_relid = RelationGetRelid(rel); toast_relid = rel->rd_rel->reltoastrelid; @@ -1166,6 +1168,8 @@ ExecuteTruncate(TruncateStmt *stmt) { rel = relation_open(toast_relid, AccessExclusiveLock); RelationSetNewRelfilenode(rel, RecentXmin); + if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED) + heap_create_init_fork(rel); heap_close(rel, NoLock); } diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index c0deab73ae..bc98d5d6fc 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -69,6 +69,8 @@ extern Oid heap_create_with_catalog(const char *relname, bool use_user_acl, bool allow_system_table_mods); +extern void heap_create_init_fork(Relation rel); + extern void heap_drop_with_catalog(Oid relid); extern void heap_truncate(List *relids);