From 965dd860d807c606d2fdf8ee002618de0f6ff464 Mon Sep 17 00:00:00 2001 From: David Christensen Date: Sun, 26 Nov 2023 16:24:09 -0500 Subject: [PATCH v3 01/28] refactor: Create PageUsableSpace to represent space post-smgr Work to abstract out the direct usage of SizeOfPageHeaderData and BLCKSZ from access methods; they should only need to operate from a sense of what space is available to them and not be party to the details. This is in preparation for allowing space to be reserved at the end of the page for, e.g., authenticated encryption tags and/or evs which will prevent future churn when we redefine this value in the future. This is largely mechanical, though some spots are trickier in their reworking; basically anything which used BLCKSZ - SizeOfPageHeaderData (in some form). Care was taken to ensure that even with differences in MAXALIGN() that no changes were introduced in the rework here, though if there is an area to look at more closely, this is it. --- contrib/bloom/bloom.h | 4 ++-- contrib/pageinspect/btreefuncs.c | 2 +- contrib/pgstattuple/pgstatapprox.c | 2 +- contrib/pgstattuple/pgstatindex.c | 2 +- src/backend/access/common/bufmask.c | 2 +- src/backend/access/gin/ginfast.c | 2 +- src/backend/access/gist/gistbuild.c | 4 ++-- src/backend/access/heap/heapam.c | 4 ++-- src/backend/access/heap/heapam_handler.c | 2 +- src/backend/access/heap/vacuumlazy.c | 2 +- src/backend/access/heap/visibilitymap.c | 2 +- src/backend/optimizer/util/plancat.c | 2 +- src/bin/pg_upgrade/file.c | 2 +- src/include/access/brin_page.h | 2 +- src/include/access/ginblock.h | 4 ++-- src/include/access/gist.h | 2 +- src/include/access/gist_private.h | 2 +- src/include/access/htup_details.h | 4 ++-- src/include/access/itup.h | 2 +- src/include/access/nbtree.h | 2 +- src/include/storage/bufpage.h | 7 +++++++ src/include/storage/fsm_internals.h | 2 +- 22 files changed, 33 insertions(+), 26 deletions(-) diff --git a/contrib/bloom/bloom.h b/contrib/bloom/bloom.h index fba3ba7771..5a2002dd37 100644 --- a/contrib/bloom/bloom.h +++ b/contrib/bloom/bloom.h @@ -112,7 +112,7 @@ typedef struct BloomOptions */ typedef BlockNumber FreeBlockNumberArray[ MAXALIGN_DOWN( - BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(BloomPageOpaqueData)) + PageUsableSpace - MAXALIGN(sizeof(BloomPageOpaqueData)) - MAXALIGN(sizeof(uint16) * 2 + sizeof(uint32) + sizeof(BloomOptions)) ) / sizeof(BlockNumber) ]; @@ -150,7 +150,7 @@ typedef struct BloomState } BloomState; #define BloomPageGetFreeSpace(state, page) \ - (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) \ + (PageUsableSpace \ - BloomPageGetMaxOffset(page) * (state)->sizeOfBloomTuple \ - MAXALIGN(sizeof(BloomPageOpaqueData))) diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c index 9cdc8e182b..1e20fecf2f 100644 --- a/contrib/pageinspect/btreefuncs.c +++ b/contrib/pageinspect/btreefuncs.c @@ -116,7 +116,7 @@ GetBTPageStatistics(BlockNumber blkno, Buffer buffer, BTPageStat *stat) stat->blkno = blkno; - stat->max_avail = BLCKSZ - (BLCKSZ - phdr->pd_special + SizeOfPageHeaderData); + stat->max_avail = PageUsableSpace - (BLCKSZ - phdr->pd_special); stat->dead_items = stat->live_items = 0; diff --git a/contrib/pgstattuple/pgstatapprox.c b/contrib/pgstattuple/pgstatapprox.c index c84c642355..b344dc6385 100644 --- a/contrib/pgstattuple/pgstatapprox.c +++ b/contrib/pgstattuple/pgstatapprox.c @@ -113,7 +113,7 @@ statapprox_heap(Relation rel, output_type *stat) if (!PageIsNew(page)) stat->free_space += PageGetHeapFreeSpace(page); else - stat->free_space += BLCKSZ - SizeOfPageHeaderData; + stat->free_space += PageUsableSpace; /* We may count the page as scanned even if it's new/empty */ scanned++; diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c index 5c06ba6db4..2641df9d61 100644 --- a/contrib/pgstattuple/pgstatindex.c +++ b/contrib/pgstattuple/pgstatindex.c @@ -309,7 +309,7 @@ pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo) { int max_avail; - max_avail = BLCKSZ - (BLCKSZ - ((PageHeader) page)->pd_special + SizeOfPageHeaderData); + max_avail = PageUsableSpace - (BLCKSZ - ((PageHeader) page)->pd_special); indexStat.max_avail += max_avail; indexStat.free_space += PageGetFreeSpace(page); diff --git a/src/backend/access/common/bufmask.c b/src/backend/access/common/bufmask.c index 10a1e4d7c6..92bb06bb50 100644 --- a/src/backend/access/common/bufmask.c +++ b/src/backend/access/common/bufmask.c @@ -120,7 +120,7 @@ mask_page_content(Page page) { /* Mask Page Content */ memset(page + SizeOfPageHeaderData, MASK_MARKER, - BLCKSZ - SizeOfPageHeaderData); + PageUsableSpace); /* Mask pd_lower and pd_upper */ memset(&((PageHeader) page)->pd_lower, MASK_MARKER, diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c index cff6850ef8..dc1687b49b 100644 --- a/src/backend/access/gin/ginfast.c +++ b/src/backend/access/gin/ginfast.c @@ -39,7 +39,7 @@ int gin_pending_list_limit = 0; #define GIN_PAGE_FREESIZE \ - ( BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(GinPageOpaqueData)) ) + ( PageUsableSpace - MAXALIGN(sizeof(GinPageOpaqueData)) ) typedef struct KeyArray { diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c index 08555b97f9..505be8430d 100644 --- a/src/backend/access/gist/gistbuild.c +++ b/src/backend/access/gist/gistbuild.c @@ -702,7 +702,7 @@ gistInitBuffering(GISTBuildState *buildstate) int levelStep; /* Calc space of index page which is available for index tuples */ - pageFreeSpace = BLCKSZ - SizeOfPageHeaderData - sizeof(GISTPageOpaqueData) + pageFreeSpace = PageUsableSpace - sizeof(GISTPageOpaqueData) - sizeof(ItemIdData) - buildstate->freespace; @@ -858,7 +858,7 @@ calculatePagesPerBuffer(GISTBuildState *buildstate, int levelStep) Size pageFreeSpace; /* Calc space of index page which is available for index tuples */ - pageFreeSpace = BLCKSZ - SizeOfPageHeaderData - sizeof(GISTPageOpaqueData) + pageFreeSpace = PageUsableSpace - sizeof(GISTPageOpaqueData) - sizeof(ItemIdData) - buildstate->freespace; diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 707460a536..a46594f009 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -2064,7 +2064,7 @@ heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid, static int heap_multi_insert_pages(HeapTuple *heaptuples, int done, int ntuples, Size saveFreeSpace) { - size_t page_avail = BLCKSZ - SizeOfPageHeaderData - saveFreeSpace; + size_t page_avail = PageUsableSpace - saveFreeSpace; int npages = 1; for (int i = done; i < ntuples; i++) @@ -2074,7 +2074,7 @@ heap_multi_insert_pages(HeapTuple *heaptuples, int done, int ntuples, Size saveF if (page_avail < tup_sz) { npages++; - page_avail = BLCKSZ - SizeOfPageHeaderData - saveFreeSpace; + page_avail = PageUsableSpace - saveFreeSpace; } page_avail -= tup_sz; } diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index d15a02b2be..aa01124483 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -2092,7 +2092,7 @@ heapam_relation_toast_am(Relation rel) #define HEAP_OVERHEAD_BYTES_PER_TUPLE \ (MAXALIGN(SizeofHeapTupleHeader) + sizeof(ItemIdData)) #define HEAP_USABLE_BYTES_PER_PAGE \ - (BLCKSZ - SizeOfPageHeaderData) + (PageUsableSpace) static void heapam_estimate_rel_size(Relation rel, int32 *attr_widths, diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 0fb3953513..e8c1db818a 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1272,7 +1272,7 @@ lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno, if (GetRecordedFreeSpace(vacrel->rel, blkno) == 0) { - freespace = BLCKSZ - SizeOfPageHeaderData; + freespace = PageUsableSpace; RecordPageWithFreeSpace(vacrel->rel, blkno, freespace); } diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c index 19785ff9d3..10a266076d 100644 --- a/src/backend/access/heap/visibilitymap.c +++ b/src/backend/access/heap/visibilitymap.c @@ -105,7 +105,7 @@ * extra headers, so the whole page minus the standard page header is * used for the bitmap. */ -#define MAPSIZE (BLCKSZ - MAXALIGN(SizeOfPageHeaderData)) +#define MAPSIZE (PageUsableSpace) /* Number of heap blocks we can represent in one byte */ #define HEAPBLOCKS_PER_BYTE (BITS_PER_BYTE / BITS_PER_HEAPBLOCK) diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 9fab52c58f..28dfd71fd1 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1089,7 +1089,7 @@ estimate_rel_size(Relation rel, int32 *attr_widths, tuple_width += MAXALIGN(SizeofHeapTupleHeader); tuple_width += sizeof(ItemIdData); /* note: integer division is intentional here */ - density = (BLCKSZ - SizeOfPageHeaderData) / tuple_width; + density = (PageUsableSpace) / tuple_width; } *tuples = rint(density * (double) curpages); diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 4850a682cb..087c0c1bd4 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -187,7 +187,7 @@ rewriteVisibilityMap(const char *fromfile, const char *tofile, struct stat statbuf; /* Compute number of old-format bytes per new page */ - rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2; + rewriteVmBytesPerPage = (PageUsableSpace) / 2; if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0) pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %s", diff --git a/src/include/access/brin_page.h b/src/include/access/brin_page.h index 70b141c25e..28c4dd9f21 100644 --- a/src/include/access/brin_page.h +++ b/src/include/access/brin_page.h @@ -86,7 +86,7 @@ typedef struct RevmapContents } RevmapContents; #define REVMAP_CONTENT_SIZE \ - (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - \ + (PageUsableSpace - \ offsetof(RevmapContents, rm_tids) - \ MAXALIGN(sizeof(BrinSpecialSpace))) /* max num of items in the array */ diff --git a/src/include/access/ginblock.h b/src/include/access/ginblock.h index b3b7daa049..1b0d3ed1ea 100644 --- a/src/include/access/ginblock.h +++ b/src/include/access/ginblock.h @@ -318,7 +318,7 @@ typedef signed char GinNullCategory; GinPageGetOpaque(page)->maxoff * sizeof(PostingItem)) #define GinDataPageMaxDataSize \ - (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) \ + (PageUsableSpace \ - MAXALIGN(sizeof(ItemPointerData)) \ - MAXALIGN(sizeof(GinPageOpaqueData))) @@ -326,7 +326,7 @@ typedef signed char GinNullCategory; * List pages */ #define GinListPageSize \ - ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GinPageOpaqueData)) ) + ( PageUsableSpace - MAXALIGN(sizeof(GinPageOpaqueData)) ) /* * A compressed posting list. diff --git a/src/include/access/gist.h b/src/include/access/gist.h index c6dcd6a90d..3590bba31c 100644 --- a/src/include/access/gist.h +++ b/src/include/access/gist.h @@ -96,7 +96,7 @@ typedef GISTPageOpaqueData *GISTPageOpaque; * key size using opclass parameters. */ #define GISTMaxIndexTupleSize \ - MAXALIGN_DOWN((BLCKSZ - SizeOfPageHeaderData - sizeof(GISTPageOpaqueData)) / \ + MAXALIGN_DOWN((PageUsableSpace - sizeof(GISTPageOpaqueData)) / \ 4 - sizeof(ItemIdData)) #define GISTMaxIndexKeySize \ diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h index 7b8749c8db..b7402450ba 100644 --- a/src/include/access/gist_private.h +++ b/src/include/access/gist_private.h @@ -474,7 +474,7 @@ extern void gistadjustmembers(Oid opfamilyoid, /* gistutil.c */ #define GiSTPageSize \ - ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GISTPageOpaqueData)) ) + ( PageUsableSpace - MAXALIGN(sizeof(GISTPageOpaqueData)) ) #define GIST_MIN_FILLFACTOR 10 #define GIST_DEFAULT_FILLFACTOR 90 diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h index 5e38ef8696..370dbbe540 100644 --- a/src/include/access/htup_details.h +++ b/src/include/access/htup_details.h @@ -560,7 +560,7 @@ StaticAssertDecl(MaxOffsetNumber < SpecTokenOffsetNumber, * ItemIds and tuples have different alignment requirements, don't assume that * you can, say, fit 2 tuples of size MaxHeapTupleSize/2 on the same page. */ -#define MaxHeapTupleSize (BLCKSZ - MAXALIGN(SizeOfPageHeaderData + sizeof(ItemIdData))) +#define MaxHeapTupleSize (PageUsableSpace - MAXALIGN(sizeof(ItemIdData))) #define MinHeapTupleSize MAXALIGN(SizeofHeapTupleHeader) /* @@ -575,7 +575,7 @@ StaticAssertDecl(MaxOffsetNumber < SpecTokenOffsetNumber, * require increases in the size of work arrays. */ #define MaxHeapTuplesPerPage \ - ((int) ((BLCKSZ - SizeOfPageHeaderData) / \ + ((int) ((PageUsableSpace) / \ (MAXALIGN(SizeofHeapTupleHeader) + sizeof(ItemIdData)))) /* diff --git a/src/include/access/itup.h b/src/include/access/itup.h index 94885751e5..4b4209e43e 100644 --- a/src/include/access/itup.h +++ b/src/include/access/itup.h @@ -164,7 +164,7 @@ index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull) * But such a page always has at least MAXALIGN special space, so we're safe. */ #define MaxIndexTuplesPerPage \ - ((int) ((BLCKSZ - SizeOfPageHeaderData) / \ + ((int) ((PageUsableSpace) / \ (MAXALIGN(sizeof(IndexTupleData) + 1) + sizeof(ItemIdData)))) #endif /* ITUP_H */ diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 6eb162052e..915a51bc23 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -183,7 +183,7 @@ typedef struct BTMetaPageData * than necessary as a result, which is considered acceptable. */ #define MaxTIDsPerBTreePage \ - (int) ((BLCKSZ - SizeOfPageHeaderData - sizeof(BTPageOpaqueData)) / \ + (int) ((PageUsableSpace - sizeof(BTPageOpaqueData)) / \ sizeof(ItemPointerData)) /* diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h index d0df02d39c..aff24a5ea2 100644 --- a/src/include/storage/bufpage.h +++ b/src/include/storage/bufpage.h @@ -213,6 +213,13 @@ typedef PageHeaderData *PageHeader; */ #define SizeOfPageHeaderData (offsetof(PageHeaderData, pd_linp)) +/* + * how much space is left after smgr's bookkeeping, etc + */ +#define PageUsableSpace (BLCKSZ - SizeOfPageHeaderData) +StaticAssertDecl(PageUsableSpace == MAXALIGN(PageUsableSpace), + "SizeOfPageHeaderData must be MAXALIGN'd"); + /* * PageIsEmpty * returns true iff no itemid has been allocated on the page diff --git a/src/include/storage/fsm_internals.h b/src/include/storage/fsm_internals.h index a922e691fe..148693d977 100644 --- a/src/include/storage/fsm_internals.h +++ b/src/include/storage/fsm_internals.h @@ -48,7 +48,7 @@ typedef FSMPageData *FSMPage; * Number of non-leaf and leaf nodes, and nodes in total, on an FSM page. * These definitions are internal to fsmpage.c. */ -#define NodesPerPage (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - \ +#define NodesPerPage (PageUsableSpace - \ offsetof(FSMPageData, fp_nodes)) #define NonLeafNodesPerPage (BLCKSZ / 2 - 1) -- 2.40.1