Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ff90ee6

Browse files
committed
In REASSIGN OWNED of a database, lock the tuple as mandated.
Commit aac2c9b mandated such locking and attempted to fulfill that mandate, but it missed REASSIGN OWNED. Hence, it remained possible to lose VACUUM's inplace update of datfrozenxid if a REASSIGN OWNED processed that database at the same time. This didn't affect the other inplace-updated catalog, pg_class. For pg_class, REASSIGN OWNED calls ATExecChangeOwner() instead of the generic AlterObjectOwner_internal(), and ATExecChangeOwner() fulfills the locking mandate. Like in GRANT, implement this by following the locking protocol for any catalog subject to the generic AlterObjectOwner_internal(). It would suffice to do this for IsInplaceUpdateOid() catalogs only. Back-patch to v13 (all supported versions). Kirill Reshke. Reported by Alexander Kukushkin. Discussion: https://postgr.es/m/CAFh8B=mpKjAy4Cuun-HP-f_vRzh2HSvYFG3rhVfYbfEBUhBAGg@mail.gmail.com
1 parent 58a359e commit ff90ee6

File tree

5 files changed

+51
-2
lines changed

5 files changed

+51
-2
lines changed

src/backend/catalog/objectaddress.c

+26-1
Original file line numberDiff line numberDiff line change
@@ -2784,14 +2784,35 @@ get_object_property_data(Oid class_id)
27842784
*/
27852785
HeapTuple
27862786
get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId)
2787+
{
2788+
return
2789+
get_catalog_object_by_oid_extended(catalog, oidcol, objectId, false);
2790+
}
2791+
2792+
/*
2793+
* Same as get_catalog_object_by_oid(), but with an additional "locktup"
2794+
* argument controlling whether to acquire a LOCKTAG_TUPLE at mode
2795+
* InplaceUpdateTupleLock. See README.tuplock section "Locking to write
2796+
* inplace-updated tables".
2797+
*/
2798+
HeapTuple
2799+
get_catalog_object_by_oid_extended(Relation catalog,
2800+
AttrNumber oidcol,
2801+
Oid objectId,
2802+
bool locktup)
27872803
{
27882804
HeapTuple tuple;
27892805
Oid classId = RelationGetRelid(catalog);
27902806
int oidCacheId = get_object_catcache_oid(classId);
27912807

27922808
if (oidCacheId > 0)
27932809
{
2794-
tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId));
2810+
if (locktup)
2811+
tuple = SearchSysCacheLockedCopy1(oidCacheId,
2812+
ObjectIdGetDatum(objectId));
2813+
else
2814+
tuple = SearchSysCacheCopy1(oidCacheId,
2815+
ObjectIdGetDatum(objectId));
27952816
if (!HeapTupleIsValid(tuple)) /* should not happen */
27962817
return NULL;
27972818
}
@@ -2816,6 +2837,10 @@ get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId)
28162837
systable_endscan(scan);
28172838
return NULL;
28182839
}
2840+
2841+
if (locktup)
2842+
LockTuple(catalog, &tuple->t_self, InplaceUpdateTupleLock);
2843+
28192844
tuple = heap_copytuple(tuple);
28202845

28212846
systable_endscan(scan);

src/backend/commands/alter.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#include "miscadmin.h"
6060
#include "replication/logicalworker.h"
6161
#include "rewrite/rewriteDefine.h"
62+
#include "storage/lmgr.h"
6263
#include "utils/acl.h"
6364
#include "utils/builtins.h"
6465
#include "utils/lsyscache.h"
@@ -924,7 +925,9 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
924925

925926
rel = table_open(catalogId, RowExclusiveLock);
926927

927-
oldtup = get_catalog_object_by_oid(rel, Anum_oid, objectId);
928+
/* Search tuple and lock it. */
929+
oldtup =
930+
get_catalog_object_by_oid_extended(rel, Anum_oid, objectId, true);
928931
if (oldtup == NULL)
929932
elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
930933
objectId, RelationGetRelationName(rel));
@@ -1024,6 +1027,8 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
10241027
/* Perform actual update */
10251028
CatalogTupleUpdate(rel, &newtup->t_self, newtup);
10261029

1030+
UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock);
1031+
10271032
/* Update owner dependency reference */
10281033
changeDependencyOnOwner(classId, objectId, new_ownerId);
10291034

@@ -1032,6 +1037,8 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
10321037
pfree(nulls);
10331038
pfree(replaces);
10341039
}
1040+
else
1041+
UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock);
10351042

10361043
/* Note the post-alter hook gets classId not catalogId */
10371044
InvokeObjectPostAlterHook(classId, objectId, 0);

src/include/catalog/objectaddress.h

+4
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ extern bool get_object_namensp_unique(Oid class_id);
6969

7070
extern HeapTuple get_catalog_object_by_oid(Relation catalog,
7171
AttrNumber oidcol, Oid objectId);
72+
extern HeapTuple get_catalog_object_by_oid_extended(Relation catalog,
73+
AttrNumber oidcol,
74+
Oid objectId,
75+
bool locktup);
7276

7377
extern char *getObjectDescription(const ObjectAddress *object,
7478
bool missing_ok);

src/test/regress/expected/database.out

+6
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,10 @@ WHERE datname = 'regression_utf8';
1212
-- load catcache entry, if nothing else does
1313
ALTER DATABASE regression_utf8 RESET TABLESPACE;
1414
ROLLBACK;
15+
CREATE ROLE regress_datdba_before;
16+
CREATE ROLE regress_datdba_after;
17+
ALTER DATABASE regression_utf8 OWNER TO regress_datdba_before;
18+
REASSIGN OWNED BY regress_datdba_before TO regress_datdba_after;
1519
DROP DATABASE regression_utf8;
20+
DROP ROLE regress_datdba_before;
21+
DROP ROLE regress_datdba_after;

src/test/regress/sql/database.sql

+7
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,11 @@ WHERE datname = 'regression_utf8';
1414
ALTER DATABASE regression_utf8 RESET TABLESPACE;
1515
ROLLBACK;
1616

17+
CREATE ROLE regress_datdba_before;
18+
CREATE ROLE regress_datdba_after;
19+
ALTER DATABASE regression_utf8 OWNER TO regress_datdba_before;
20+
REASSIGN OWNED BY regress_datdba_before TO regress_datdba_after;
21+
1722
DROP DATABASE regression_utf8;
23+
DROP ROLE regress_datdba_before;
24+
DROP ROLE regress_datdba_after;

0 commit comments

Comments
 (0)