|
| 1 | +-- Test: VACUUM on a table in a non-default tablespace does not crash on first run. |
| 2 | +-- |
| 3 | +-- Bug: SIGSEGV in fsm_extend() (freespace.c:637) when vacuuming a heap table |
| 4 | +-- (or an AO table's aoseg auxiliary table) that resides in a non-default |
| 5 | +-- tablespace for the very first time. |
| 6 | +-- |
| 7 | +-- Root cause: commit "Prevent CREATE TABLE from using dangling tablespace" |
| 8 | +-- added TablespaceLockTuple() in TablespaceCreateDbspace() for non-default |
| 9 | +-- tablespaces. That call reaches AcceptInvalidationMessages() via |
| 10 | +-- LockSharedObject(), which processes a pending SHAREDINVALSMGR_ID message |
| 11 | +-- that vm_extend() had queued via CacheInvalidateSmgr(), nullifying |
| 12 | +-- rel->rd_smgr before fsm_extend() dereferences it at freespace.c:637. |
| 13 | +-- |
| 14 | +-- Fix: added RelationOpenSmgr(rel) after smgrcreate() in both fsm_extend() |
| 15 | +-- (freespace.c) and vm_extend() (visibilitymap.c) so that rd_smgr is |
| 16 | +-- re-opened if the sinval handler closed it. |
| 17 | + |
| 18 | +CREATE TABLESPACE fsm_ts_test LOCATION '@testtablespace@'; |
| 19 | + |
| 20 | +-- Case 1: plain heap table in non-default tablespace, first VACUUM. |
| 21 | +-- Before the fix this crashed with SIGSEGV at freespace.c:637: |
| 22 | +-- vm_extend() -> CacheInvalidateSmgr (queues SHAREDINVALSMGR_ID) |
| 23 | +-- fsm_extend() -> smgrcreate -> TablespaceCreateDbspace |
| 24 | +-- -> TablespaceLockTuple -> AcceptInvalidationMessages |
| 25 | +-- -> processes SHAREDINVALSMGR_ID -> rel->rd_smgr = NULL |
| 26 | +-- -> rel->rd_smgr->smgr_cached_nblocks[...] = ... SIGSEGV |
| 27 | +CREATE TABLE fsm_ts_heap (id int, val text) |
| 28 | + TABLESPACE fsm_ts_test |
| 29 | + DISTRIBUTED BY (id); |
| 30 | +INSERT INTO fsm_ts_heap SELECT i, repeat('x', 80) FROM generate_series(1, 500) i; |
| 31 | +VACUUM ANALYZE fsm_ts_heap; |
| 32 | +SELECT count(*) FROM fsm_ts_heap; |
| 33 | +-- Second VACUUM must also succeed (FSM/VM now exist, different code path). |
| 34 | +VACUUM ANALYZE fsm_ts_heap; |
| 35 | +SELECT count(*) FROM fsm_ts_heap; |
| 36 | +DROP TABLE fsm_ts_heap; |
| 37 | + |
| 38 | +-- Case 2: AO table in non-default tablespace. |
| 39 | +-- The crash occurs inside the recursive vacuum of the aoseg auxiliary table |
| 40 | +-- (which is also a heap table stored in the same non-default tablespace). |
| 41 | +CREATE TABLE fsm_ts_ao (id int, val text) |
| 42 | + USING ao_row |
| 43 | + TABLESPACE fsm_ts_test |
| 44 | + DISTRIBUTED BY (id); |
| 45 | +INSERT INTO fsm_ts_ao SELECT i, repeat('y', 80) FROM generate_series(1, 500) i; |
| 46 | +VACUUM ANALYZE fsm_ts_ao; |
| 47 | +SELECT count(*) FROM fsm_ts_ao; |
| 48 | +-- Second VACUUM must also succeed. |
| 49 | +VACUUM ANALYZE fsm_ts_ao; |
| 50 | +SELECT count(*) FROM fsm_ts_ao; |
| 51 | +DROP TABLE fsm_ts_ao; |
| 52 | + |
| 53 | +-- Cleanup. |
| 54 | +DROP TABLESPACE fsm_ts_test; |
0 commit comments