Skip to content

Commit 718af10

Browse files
committed
Avoid "you don't own a lock of type ExclusiveLock" in GRANT TABLESPACE.
This WARNING appeared because SearchSysCacheLocked1() read cc_relisshared before catcache initialization, when the field is false unconditionally. On the basis of reading false there, it constructed a locktag as though pg_tablespace weren't relisshared. Only shared catalogs could be affected, and only GRANT TABLESPACE was affected in practice. SearchSysCacheLocked1() callers use one other shared-relation syscache, DATABASEOID. DATABASEOID is initialized by the end of CheckMyDatabase(), making the problem unreachable for pg_database. Back-patch to v13 (all supported versions). This has no known impact before v16, where ExecGrant_common() first appeared. Earlier branches avoid trouble by having a separate ExecGrant_Tablespace() that doesn't use LOCKTAG_TUPLE. However, leaving this unfixed in v15 could ensnare a future back-patch of a SearchSysCacheLocked1() call. Reported by Aya Iwata. Discussion: https://postgr.es/m/OS7PR01MB11964507B5548245A7EE54E70EA212@OS7PR01MB11964.jpnprd01.prod.outlook.com
1 parent aefbd6c commit 718af10

File tree

3 files changed

+21
-5
lines changed

3 files changed

+21
-5
lines changed

src/backend/utils/cache/syscache.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,9 @@ HeapTuple
287287
SearchSysCacheLocked1(int cacheId,
288288
Datum key1)
289289
{
290+
CatCache *cache = SysCache[cacheId];
290291
ItemPointerData tid;
291292
LOCKTAG tag;
292-
Oid dboid =
293-
SysCache[cacheId]->cc_relisshared ? InvalidOid : MyDatabaseId;
294-
Oid reloid = cacheinfo[cacheId].reloid;
295293

296294
/*----------
297295
* Since inplace updates may happen just before our LockTuple(), we must
@@ -343,8 +341,15 @@ SearchSysCacheLocked1(int cacheId,
343341

344342
tid = tuple->t_self;
345343
ReleaseSysCache(tuple);
346-
/* like: LockTuple(rel, &tid, lockmode) */
347-
SET_LOCKTAG_TUPLE(tag, dboid, reloid,
344+
345+
/*
346+
* Do like LockTuple(rel, &tid, lockmode). While cc_relisshared won't
347+
* change from one iteration to another, it may have been a temporary
348+
* "false" until our first SearchSysCache1().
349+
*/
350+
SET_LOCKTAG_TUPLE(tag,
351+
cache->cc_relisshared ? InvalidOid : MyDatabaseId,
352+
cache->cc_reloid,
348353
ItemPointerGetBlockNumber(&tid),
349354
ItemPointerGetOffsetNumber(&tid));
350355
(void) LockAcquire(&tag, lockmode, false, false);

src/test/regress/expected/tablespace.out

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,11 @@ ALTER INDEX testschema.part_a_idx SET TABLESPACE pg_default;
927927
-- Fail, not empty
928928
DROP TABLESPACE regress_tblspace;
929929
ERROR: tablespace "regress_tblspace" is not empty
930+
-- Adequate cache initialization before GRANT
931+
\c -
932+
BEGIN;
933+
GRANT ALL ON TABLESPACE regress_tblspace TO PUBLIC;
934+
ROLLBACK;
930935
CREATE ROLE regress_tablespace_user1 login;
931936
CREATE ROLE regress_tablespace_user2 login;
932937
GRANT USAGE ON SCHEMA testschema TO regress_tablespace_user2;

src/test/regress/sql/tablespace.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,12 @@ ALTER INDEX testschema.part_a_idx SET TABLESPACE pg_default;
396396
-- Fail, not empty
397397
DROP TABLESPACE regress_tblspace;
398398

399+
-- Adequate cache initialization before GRANT
400+
\c -
401+
BEGIN;
402+
GRANT ALL ON TABLESPACE regress_tblspace TO PUBLIC;
403+
ROLLBACK;
404+
399405
CREATE ROLE regress_tablespace_user1 login;
400406
CREATE ROLE regress_tablespace_user2 login;
401407
GRANT USAGE ON SCHEMA testschema TO regress_tablespace_user2;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy