Fix relptr's encoding of the base address.
authorThomas Munro <[email protected]>
Sun, 26 Jun 2022 22:30:15 +0000 (10:30 +1200)
committerThomas Munro <[email protected]>
Sun, 26 Jun 2022 23:34:26 +0000 (11:34 +1200)
Previously, we encoded both NULL and the first byte at the base address
as 0.  That confusion led to the assertion in commit e07d4ddc, which
failed when min_dynamic_shared_memory was used.  Give them distinct
encodings, by switching to 1-based offsets for non-NULL pointers.  Also
improve macro hygiene in passing (missing/misplaced parentheses), and
remove open-coded access to the raw offset value from freepage.c/h.

Although e07d4ddc was back-patched to 10, the only code that actually
makes use of relptr at the base address arrived in 84b1c63a, so no need
to back-patch further than 14 for now.

Reported-by: Justin Pryzby <[email protected]>
Reviewed-by: Robert Haas <[email protected]>
Discussion: https://postgr.es/m/20220519193839.GT19626%40telsasoft.com

src/backend/utils/mmgr/freepage.c
src/include/utils/freepage.h
src/include/utils/relptr.h

index b26a295a4ead5e308ea215b9c68635c39a9178fc..dcf246faf111097e3c6054ca8f8e30738e450c80 100644 (file)
@@ -434,7 +434,7 @@ FreePageManagerDump(FreePageManager *fpm)
 
    /* Dump general stuff. */
    appendStringInfo(&buf, "metadata: self %zu max contiguous pages = %zu\n",
-                    fpm->self.relptr_off, fpm->contiguous_pages);
+                    relptr_offset(fpm->self), fpm->contiguous_pages);
 
    /* Dump btree. */
    if (fpm->btree_depth > 0)
@@ -1269,7 +1269,7 @@ FreePageManagerDumpBtree(FreePageManager *fpm, FreePageBtree *btp,
        if (btp->hdr.magic == FREE_PAGE_INTERNAL_MAGIC)
            appendStringInfo(buf, " %zu->%zu",
                             btp->u.internal_key[index].first_page,
-                            btp->u.internal_key[index].child.relptr_off / FPM_PAGE_SIZE);
+                            relptr_offset(btp->u.internal_key[index].child) / FPM_PAGE_SIZE);
        else
            appendStringInfo(buf, " %zu(%zu)",
                             btp->u.leaf_key[index].first_page,
@@ -1859,7 +1859,7 @@ FreePagePopSpanLeader(FreePageManager *fpm, Size pageno)
    {
        Size        f = Min(span->npages, FPM_NUM_FREELISTS) - 1;
 
-       Assert(fpm->freelist[f].relptr_off == pageno * FPM_PAGE_SIZE);
+       Assert(relptr_offset(fpm->freelist[f]) == pageno * FPM_PAGE_SIZE);
        relptr_copy(fpm->freelist[f], span->next);
    }
 }
index 08064b10f9756867f7c4dc22f97f1c69e129b6e7..e69b2804ec146569b553a7be965e9a6d7f3d99db 100644 (file)
@@ -78,11 +78,11 @@ struct FreePageManager
 #define fpm_pointer_is_page_aligned(base, ptr)     \
    (((Size) (((char *) (ptr)) - (base))) % FPM_PAGE_SIZE == 0)
 #define fpm_relptr_is_page_aligned(base, relptr)       \
-   ((relptr).relptr_off % FPM_PAGE_SIZE == 0)
+   (relptr_offset(relptr) % FPM_PAGE_SIZE == 0)
 
 /* Macro to find base address of the segment containing a FreePageManager. */
 #define fpm_segment_base(fpm)  \
-   (((char *) fpm) - fpm->self.relptr_off)
+   (((char *) fpm) - relptr_offset(fpm->self))
 
 /* Macro to access a FreePageManager's largest consecutive run of pages. */
 #define fpm_largest(fpm) \
index cc80a7200de144b544009bb8467b5c1e3a7802d5..9364dd6694838f4e1af5ad74555f90f78d1e9e33 100644 (file)
@@ -42,7 +42,7 @@
 #define relptr_access(base, rp) \
    (AssertVariableIsOfTypeMacro(base, char *), \
     (__typeof__((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
-       (base + (rp).relptr_off)))
+       (base) + (rp).relptr_off - 1))
 #else
 /*
  * If we don't have __builtin_types_compatible_p, assume we might not have
  */
 #define relptr_access(base, rp) \
    (AssertVariableIsOfTypeMacro(base, char *), \
-    (void *) ((rp).relptr_off == 0 ? NULL : (base + (rp).relptr_off)))
+    (void *) ((rp).relptr_off == 0 ? NULL : (base) + (rp).relptr_off - 1))
 #endif
 
 #define relptr_is_null(rp) \
    ((rp).relptr_off == 0)
 
+#define relptr_offset(rp) \
+   ((rp).relptr_off - 1)
+
 /* We use this inline to avoid double eval of "val" in relptr_store */
 static inline Size
 relptr_store_eval(char *base, char *val)
@@ -64,8 +67,8 @@ relptr_store_eval(char *base, char *val)
        return 0;
    else
    {
-       Assert(val > base);
-       return val - base;
+       Assert(val >= base);
+       return val - base + 1;
    }
 }
 
@@ -73,7 +76,7 @@ relptr_store_eval(char *base, char *val)
 #define relptr_store(base, rp, val) \
    (AssertVariableIsOfTypeMacro(base, char *), \
     AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \
-    (rp).relptr_off = relptr_store_eval(base, (char *) (val)))
+    (rp).relptr_off = relptr_store_eval((base), (char *) (val)))
 #else
 /*
  * If we don't have __builtin_types_compatible_p, assume we might not have
@@ -81,7 +84,7 @@ relptr_store_eval(char *base, char *val)
  */
 #define relptr_store(base, rp, val) \
    (AssertVariableIsOfTypeMacro(base, char *), \
-    (rp).relptr_off = relptr_store_eval(base, (char *) (val)))
+    (rp).relptr_off = relptr_store_eval((base), (char *) (val)))
 #endif
 
 #define relptr_copy(rp1, rp2) \