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-2024, 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 31 8889084 : mask_page_lsn_and_checksum(Page page) 32 : { 33 8889084 : PageHeader phdr = (PageHeader) page; 34 : 35 8889084 : PageXLogRecPtrSet(phdr->pd_lsn, (uint64) MASK_MARKER); 36 8889084 : phdr->pd_checksum = MASK_MARKER; 37 8889084 : } 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 8886792 : mask_page_hint_bits(Page page) 47 : { 48 8886792 : PageHeader phdr = (PageHeader) page; 49 : 50 : /* Ignore prune_xid (it's like a hint-bit) */ 51 8886792 : phdr->pd_prune_xid = MASK_MARKER; 52 : 53 : /* Ignore PD_PAGE_FULL and PD_HAS_FREE_LINES flags, they are just hints. */ 54 8886792 : PageClearFull(page); 55 8886792 : 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 8886792 : PageClearAllVisible(page); 63 8886792 : } 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 8886484 : mask_unused_space(Page page) 72 : { 73 8886484 : int pd_lower = ((PageHeader) page)->pd_lower; 74 8886484 : int pd_upper = ((PageHeader) page)->pd_upper; 75 8886484 : int pd_special = ((PageHeader) page)->pd_special; 76 : 77 : /* Sanity check */ 78 8886484 : if (pd_lower > pd_upper || pd_special < pd_upper || 79 8886484 : pd_lower < SizeOfPageHeaderData || pd_special > BLCKSZ) 80 : { 81 0 : elog(ERROR, "invalid page pd_lower %u pd_upper %u pd_special %u", 82 : pd_lower, pd_upper, pd_special); 83 : } 84 : 85 8886484 : memset(page + pd_lower, MASK_MARKER, pd_upper - pd_lower); 86 8886484 : } 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 2252316 : mask_lp_flags(Page page) 96 : { 97 : OffsetNumber offnum, 98 : maxoff; 99 : 100 2252316 : maxoff = PageGetMaxOffsetNumber(page); 101 396274468 : for (offnum = FirstOffsetNumber; 102 : offnum <= maxoff; 103 394022152 : offnum = OffsetNumberNext(offnum)) 104 : { 105 394022152 : ItemId itemId = PageGetItemId(page, offnum); 106 : 107 394022152 : if (ItemIdIsUsed(itemId)) 108 394017392 : itemId->lp_flags = LP_UNUSED; 109 : } 110 2252316 : } 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 712 : mask_page_content(Page page) 120 : { 121 : /* Mask Page Content */ 122 712 : memset(page + SizeOfPageHeaderData, MASK_MARKER, 123 : BLCKSZ - SizeOfPageHeaderData); 124 : 125 : /* Mask pd_lower and pd_upper */ 126 712 : memset(&((PageHeader) page)->pd_lower, MASK_MARKER, 127 : sizeof(uint16)); 128 712 : memset(&((PageHeader) page)->pd_upper, MASK_MARKER, 129 : sizeof(uint16)); 130 712 : }