fix-dsa-segment-free-bug.patch
application/octet-stream
Filename: fix-dsa-segment-free-bug.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/utils/mmgr/dsa.c | 24 | 5 |
diff --git a/src/backend/utils/mmgr/dsa.c b/src/backend/utils/mmgr/dsa.c
index 488678191b..f89048c823 100644
--- a/src/backend/utils/mmgr/dsa.c
+++ b/src/backend/utils/mmgr/dsa.c
@@ -405,6 +405,7 @@ static dsa_area *create_internal(void *place, size_t size,
static dsa_area *attach_internal(void *place, dsm_segment *segment,
dsa_handle handle);
static void check_for_freed_segments(dsa_area *area);
+static void check_for_freed_segments_locked(dsa_area *area);
/*
* Create a new shared area in a new DSM segment. Further DSM segments will
@@ -1778,8 +1779,6 @@ destroy_superblock(dsa_area *area, dsa_pointer span_pointer)
int size_class = span->size_class;
dsa_segment_map *segment_map;
- segment_map =
- get_segment_by_index(area, DSA_EXTRACT_SEGMENT_NUMBER(span->start));
/* Remove it from its fullness class list. */
unlink_span(area, span);
@@ -1790,6 +1789,9 @@ destroy_superblock(dsa_area *area, dsa_pointer span_pointer)
* could deadlock.
*/
LWLockAcquire(DSA_AREA_LOCK(area), LW_EXCLUSIVE);
+ check_for_freed_segments_locked(area);
+ segment_map =
+ get_segment_by_index(area, DSA_EXTRACT_SEGMENT_NUMBER(span->start));
FreePageManagerPut(segment_map->fpm,
DSA_EXTRACT_OFFSET(span->start) / FPM_PAGE_SIZE,
span->npages);
@@ -1944,6 +1946,7 @@ get_best_segment(dsa_area *area, Size npages)
Size bin;
Assert(LWLockHeldByMe(DSA_AREA_LOCK(area)));
+ check_for_freed_segments_locked(area);
/*
* Start searching from the first bin that *might* have enough contiguous
@@ -2220,10 +2223,27 @@ check_for_freed_segments(dsa_area *area)
freed_segment_counter = area->control->freed_segment_counter;
if (unlikely(area->freed_segment_counter != freed_segment_counter))
{
- int i;
-
/* Check all currently mapped segments to find what's been freed. */
LWLockAcquire(DSA_AREA_LOCK(area), LW_EXCLUSIVE);
+ check_for_freed_segments_locked(area);
+ LWLockRelease(DSA_AREA_LOCK(area));
+ }
+}
+
+/*
+ * Workhorse for check_for_free_segments_unlocked, when the area lock is already
+ * held.
+ */
+static void
+check_for_freed_segments_locked(dsa_area *area)
+{
+ Size freed_segment_counter;
+ int i;
+
+ Assert(LWLockHeldByMe(DSA_AREA_LOCK(area)));
+ freed_segment_counter = area->control->freed_segment_counter;
+ if (unlikely(area->freed_segment_counter != freed_segment_counter))
+ {
for (i = 0; i <= area->high_segment_index; ++i)
{
if (area->segment_maps[i].header != NULL &&
@@ -2235,7 +2255,6 @@ check_for_freed_segments(dsa_area *area)
area->segment_maps[i].mapped_address = NULL;
}
}
- LWLockRelease(DSA_AREA_LOCK(area));
area->freed_segment_counter = freed_segment_counter;
}
}