Fix relptr's encoding of the base address.
Previously, we encoded both NULL and the first byte at the base address as 0. That confusion led to the assertion in commite07d4ddc
, 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. Althoughe07d4ddc
was back-patched to 10, the only code that actually makes use of relptr at the base address arrived in84b1c63a
, so no need to back-patch further than 14 for now. Reported-by: Justin Pryzby <pryzby@telsasoft.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Discussion: https://postgr.es/m/20220519193839.GT19626%40telsasoft.com
This commit is contained in:
parent
ebc584ed49
commit
7201cd1862
|
@ -434,7 +434,7 @@ FreePageManagerDump(FreePageManager *fpm)
|
||||||
|
|
||||||
/* Dump general stuff. */
|
/* Dump general stuff. */
|
||||||
appendStringInfo(&buf, "metadata: self %zu max contiguous pages = %zu\n",
|
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. */
|
/* Dump btree. */
|
||||||
if (fpm->btree_depth > 0)
|
if (fpm->btree_depth > 0)
|
||||||
|
@ -1269,7 +1269,7 @@ FreePageManagerDumpBtree(FreePageManager *fpm, FreePageBtree *btp,
|
||||||
if (btp->hdr.magic == FREE_PAGE_INTERNAL_MAGIC)
|
if (btp->hdr.magic == FREE_PAGE_INTERNAL_MAGIC)
|
||||||
appendStringInfo(buf, " %zu->%zu",
|
appendStringInfo(buf, " %zu->%zu",
|
||||||
btp->u.internal_key[index].first_page,
|
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
|
else
|
||||||
appendStringInfo(buf, " %zu(%zu)",
|
appendStringInfo(buf, " %zu(%zu)",
|
||||||
btp->u.leaf_key[index].first_page,
|
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;
|
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);
|
relptr_copy(fpm->freelist[f], span->next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,11 +78,11 @@ struct FreePageManager
|
||||||
#define fpm_pointer_is_page_aligned(base, ptr) \
|
#define fpm_pointer_is_page_aligned(base, ptr) \
|
||||||
(((Size) (((char *) (ptr)) - (base))) % FPM_PAGE_SIZE == 0)
|
(((Size) (((char *) (ptr)) - (base))) % FPM_PAGE_SIZE == 0)
|
||||||
#define fpm_relptr_is_page_aligned(base, relptr) \
|
#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. */
|
/* Macro to find base address of the segment containing a FreePageManager. */
|
||||||
#define fpm_segment_base(fpm) \
|
#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. */
|
/* Macro to access a FreePageManager's largest consecutive run of pages. */
|
||||||
#define fpm_largest(fpm) \
|
#define fpm_largest(fpm) \
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
#define relptr_access(base, rp) \
|
#define relptr_access(base, rp) \
|
||||||
(AssertVariableIsOfTypeMacro(base, char *), \
|
(AssertVariableIsOfTypeMacro(base, char *), \
|
||||||
(__typeof__((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
|
(__typeof__((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
|
||||||
(base + (rp).relptr_off)))
|
(base) + (rp).relptr_off - 1))
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
* If we don't have __builtin_types_compatible_p, assume we might not have
|
* If we don't have __builtin_types_compatible_p, assume we might not have
|
||||||
|
@ -50,12 +50,15 @@
|
||||||
*/
|
*/
|
||||||
#define relptr_access(base, rp) \
|
#define relptr_access(base, rp) \
|
||||||
(AssertVariableIsOfTypeMacro(base, char *), \
|
(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
|
#endif
|
||||||
|
|
||||||
#define relptr_is_null(rp) \
|
#define relptr_is_null(rp) \
|
||||||
((rp).relptr_off == 0)
|
((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 */
|
/* We use this inline to avoid double eval of "val" in relptr_store */
|
||||||
static inline Size
|
static inline Size
|
||||||
relptr_store_eval(char *base, char *val)
|
relptr_store_eval(char *base, char *val)
|
||||||
|
@ -64,8 +67,8 @@ relptr_store_eval(char *base, char *val)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Assert(val > base);
|
Assert(val >= base);
|
||||||
return val - base;
|
return val - base + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +76,7 @@ relptr_store_eval(char *base, char *val)
|
||||||
#define relptr_store(base, rp, val) \
|
#define relptr_store(base, rp, val) \
|
||||||
(AssertVariableIsOfTypeMacro(base, char *), \
|
(AssertVariableIsOfTypeMacro(base, char *), \
|
||||||
AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \
|
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
|
#else
|
||||||
/*
|
/*
|
||||||
* If we don't have __builtin_types_compatible_p, assume we might not have
|
* 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) \
|
#define relptr_store(base, rp, val) \
|
||||||
(AssertVariableIsOfTypeMacro(base, char *), \
|
(AssertVariableIsOfTypeMacro(base, char *), \
|
||||||
(rp).relptr_off = relptr_store_eval(base, (char *) (val)))
|
(rp).relptr_off = relptr_store_eval((base), (char *) (val)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define relptr_copy(rp1, rp2) \
|
#define relptr_copy(rp1, rp2) \
|
||||||
|
|
Loading…
Reference in New Issue