Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * bufmask.c
4 : * Routines for buffer masking. Used to mask certain bits
5 : * in a page which can be different when the WAL is generated
6 : * and when the WAL is applied.
7 : *
8 : * Portions Copyright (c) 2016-2023, PostgreSQL Global Development Group
9 : *
10 : * Contains common routines required for masking a page.
11 : *
12 : * IDENTIFICATION
13 : * src/backend/access/common/bufmask.c
14 : *
15 : *-------------------------------------------------------------------------
16 : */
17 :
18 : #include "postgres.h"
19 :
20 : #include "access/bufmask.h"
21 :
22 : /*
23 : * mask_page_lsn_and_checksum
24 : *
25 : * In consistency checks, the LSN of the two pages compared will likely be
26 : * different because of concurrent operations when the WAL is generated and
27 : * the state of the page when WAL is applied. Also, mask out checksum as
28 : * masking anything else on page means checksum is not going to match as well.
29 : */
30 : void
2025 rhaas 31 UBC 0 : mask_page_lsn_and_checksum(Page page)
32 : {
2251 33 0 : PageHeader phdr = (PageHeader) page;
34 :
35 0 : PageXLogRecPtrSet(phdr->pd_lsn, (uint64) MASK_MARKER);
2025 36 0 : phdr->pd_checksum = MASK_MARKER;
2251 37 0 : }
38 :
39 : /*
40 : * mask_page_hint_bits
41 : *
42 : * Mask hint bits in PageHeader. We want to ignore differences in hint bits,
43 : * since they can be set without emitting any WAL.
44 : */
45 : void
46 0 : mask_page_hint_bits(Page page)
47 : {
48 0 : PageHeader phdr = (PageHeader) page;
49 :
50 : /* Ignore prune_xid (it's like a hint-bit) */
51 0 : phdr->pd_prune_xid = MASK_MARKER;
52 :
53 : /* Ignore PD_PAGE_FULL and PD_HAS_FREE_LINES flags, they are just hints. */
54 0 : PageClearFull(page);
55 0 : PageClearHasFreeLinePointers(page);
56 :
57 : /*
58 : * During replay, if the page LSN has advanced past our XLOG record's LSN,
59 : * we don't mark the page all-visible. See heap_xlog_visible() for
60 : * details.
61 : */
62 0 : PageClearAllVisible(page);
63 0 : }
64 :
65 : /*
66 : * mask_unused_space
67 : *
68 : * Mask the unused space of a page between pd_lower and pd_upper.
69 : */
70 : void
71 0 : mask_unused_space(Page page)
72 : {
73 0 : int pd_lower = ((PageHeader) page)->pd_lower;
74 0 : int pd_upper = ((PageHeader) page)->pd_upper;
75 0 : int pd_special = ((PageHeader) page)->pd_special;
76 :
77 : /* Sanity check */
78 0 : if (pd_lower > pd_upper || pd_special < pd_upper ||
79 0 : pd_lower < SizeOfPageHeaderData || pd_special > BLCKSZ)
80 : {
96 michael 81 0 : elog(ERROR, "invalid page pd_lower %u pd_upper %u pd_special %u",
82 : pd_lower, pd_upper, pd_special);
83 : }
84 :
2251 rhaas 85 0 : memset(page + pd_lower, MASK_MARKER, pd_upper - pd_lower);
86 0 : }
87 :
88 : /*
89 : * mask_lp_flags
90 : *
91 : * In some index AMs, line pointer flags can be modified on the primary
92 : * without emitting any WAL record.
93 : */
94 : void
95 0 : mask_lp_flags(Page page)
96 : {
97 : OffsetNumber offnum,
98 : maxoff;
99 :
100 0 : maxoff = PageGetMaxOffsetNumber(page);
101 0 : for (offnum = FirstOffsetNumber;
102 0 : offnum <= maxoff;
103 0 : offnum = OffsetNumberNext(offnum))
104 : {
105 0 : ItemId itemId = PageGetItemId(page, offnum);
106 :
107 0 : if (ItemIdIsUsed(itemId))
108 0 : itemId->lp_flags = LP_UNUSED;
109 : }
110 0 : }
111 :
112 : /*
113 : * mask_page_content
114 : *
115 : * In some index AMs, the contents of deleted pages need to be almost
116 : * completely ignored.
117 : */
118 : void
119 0 : mask_page_content(Page page)
120 : {
121 : /* Mask Page Content */
122 0 : memset(page + SizeOfPageHeaderData, MASK_MARKER,
123 : BLCKSZ - SizeOfPageHeaderData);
124 :
125 : /* Mask pd_lower and pd_upper */
126 0 : memset(&((PageHeader) page)->pd_lower, MASK_MARKER,
127 : sizeof(uint16));
128 0 : memset(&((PageHeader) page)->pd_upper, MASK_MARKER,
129 : sizeof(uint16));
130 0 : }
|