aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTeodor Sigaev <teodor@sigaev.ru>2018-04-05 17:56:00 +0300
committerTeodor Sigaev <teodor@sigaev.ru>2018-04-05 17:56:00 +0300
commit0a64b45152b593c5eb95f2e88fbce7fbfe84ae7b (patch)
treef28cd056f3df8f09549dedb400eb890d333f8100 /src
parent01b88b4df5e2df0365cceaf79a039214d9f05273 (diff)
downloadpostgresql-0a64b45152b593c5eb95f2e88fbce7fbfe84ae7b.tar.gz
postgresql-0a64b45152b593c5eb95f2e88fbce7fbfe84ae7b.zip
Fix handling of non-upgraded B-tree metapages
857f9c36 bumps B-tree metapage version while upgrade is performed "on the fly" when needed. However, some asserts fired when old version metapage was cached to rel->rd_amcache. Despite new metadata fields are never used from rel->rd_amcache, that needs to be fixed. This patch introduces metadata upgrade during its caching, which fills unavailable fields with their default values. contrib/pageinspect is also patched to handle non-upgraded metapages in the same way. Author: Alexander Korotkov
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/nbtree/nbtpage.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index c98603bbf8f..019fe48cb6e 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -33,6 +33,7 @@
#include "storage/predicate.h"
#include "utils/snapmgr.h"
+static void _bt_cachemetadata(Relation rel, BTMetaPageData *metad);
static bool _bt_mark_page_halfdead(Relation rel, Buffer buf, BTStack stack);
static bool _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf,
bool *rightsib_empty);
@@ -106,6 +107,44 @@ _bt_upgrademetapage(Page page)
}
/*
+ * Cache metadata from meta page to rel->rd_amcache.
+ */
+static void
+_bt_cachemetadata(Relation rel, BTMetaPageData *metad)
+{
+ /* We assume rel->rd_amcache was already freed by caller */
+ Assert(rel->rd_amcache == NULL);
+ rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
+ sizeof(BTMetaPageData));
+
+ /*
+ * Meta page should be of supported version (should be already checked by
+ * caller).
+ */
+ Assert(metad->btm_version >= BTREE_MIN_VERSION &&
+ metad->btm_version <= BTREE_VERSION);
+
+ if (metad->btm_version == BTREE_VERSION)
+ {
+ /* Last version of meta-data, no need to upgrade */
+ memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
+ }
+ else
+ {
+ BTMetaPageData *cached_metad = (BTMetaPageData *) rel->rd_amcache;
+
+ /*
+ * Upgrade meta-data: copy available information from meta-page and
+ * fill new fields with default values.
+ */
+ memcpy(rel->rd_amcache, metad, offsetof(BTMetaPageData, btm_oldest_btpo_xact));
+ cached_metad->btm_version = BTREE_VERSION;
+ cached_metad->btm_oldest_btpo_xact = InvalidTransactionId;
+ cached_metad->btm_last_cleanup_num_heap_tuples = -1.0;
+ }
+}
+
+/*
* _bt_update_meta_cleanup_info() -- Update cleanup-related information in
* the metapage.
*
@@ -403,9 +442,7 @@ _bt_getroot(Relation rel, int access)
/*
* Cache the metapage data for next time
*/
- rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
- sizeof(BTMetaPageData));
- memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
+ _bt_cachemetadata(rel, metad);
/*
* We are done with the metapage; arrange to release it via first
@@ -604,9 +641,7 @@ _bt_getrootheight(Relation rel)
/*
* Cache the metapage data for next time
*/
- rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
- sizeof(BTMetaPageData));
- memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
+ _bt_cachemetadata(rel, metad);
_bt_relbuf(rel, metabuf);
}