Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * tablespace.c
4 : * Commands to manipulate table spaces
5 : *
6 : * Tablespaces in PostgreSQL are designed to allow users to determine
7 : * where the data file(s) for a given database object reside on the file
8 : * system.
9 : *
10 : * A tablespace represents a directory on the file system. At tablespace
11 : * creation time, the directory must be empty. To simplify things and
12 : * remove the possibility of having file name conflicts, we isolate
13 : * files within a tablespace into database-specific subdirectories.
14 : *
15 : * To support file access via the information given in RelFileLocator, we
16 : * maintain a symbolic-link map in $PGDATA/pg_tblspc. The symlinks are
17 : * named by tablespace OIDs and point to the actual tablespace directories.
18 : * There is also a per-cluster version directory in each tablespace.
19 : * Thus the full path to an arbitrary file is
20 : * $PGDATA/pg_tblspc/spcoid/PG_MAJORVER_CATVER/dboid/relfilenumber
21 : * e.g.
22 : * $PGDATA/pg_tblspc/20981/PG_9.0_201002161/719849/83292814
23 : *
24 : * There are two tablespaces created at initdb time: pg_global (for shared
25 : * tables) and pg_default (for everything else). For backwards compatibility
26 : * and to remain functional on platforms without symlinks, these tablespaces
27 : * are accessed specially: they are respectively
28 : * $PGDATA/global/relfilenumber
29 : * $PGDATA/base/dboid/relfilenumber
30 : *
31 : * To allow CREATE DATABASE to give a new database a default tablespace
32 : * that's different from the template database's default, we make the
33 : * provision that a zero in pg_class.reltablespace means the database's
34 : * default tablespace. Without this, CREATE DATABASE would have to go in
35 : * and munge the system catalogs of the new database.
36 : *
37 : *
38 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
39 : * Portions Copyright (c) 1994, Regents of the University of California
40 : *
41 : *
42 : * IDENTIFICATION
43 : * src/backend/commands/tablespace.c
44 : *
45 : *-------------------------------------------------------------------------
46 : */
47 : #include "postgres.h"
48 :
49 : #include <unistd.h>
50 : #include <dirent.h>
51 : #include <sys/stat.h>
52 :
53 : #include "access/heapam.h"
54 : #include "access/htup_details.h"
55 : #include "access/reloptions.h"
56 : #include "access/sysattr.h"
57 : #include "access/tableam.h"
58 : #include "access/xact.h"
59 : #include "access/xloginsert.h"
60 : #include "access/xlogutils.h"
61 : #include "catalog/binary_upgrade.h"
62 : #include "catalog/catalog.h"
63 : #include "catalog/dependency.h"
64 : #include "catalog/indexing.h"
65 : #include "catalog/namespace.h"
66 : #include "catalog/objectaccess.h"
67 : #include "catalog/pg_namespace.h"
68 : #include "catalog/pg_tablespace.h"
69 : #include "commands/comment.h"
70 : #include "commands/seclabel.h"
71 : #include "commands/tablecmds.h"
72 : #include "commands/tablespace.h"
73 : #include "common/file_perm.h"
74 : #include "miscadmin.h"
75 : #include "postmaster/bgwriter.h"
76 : #include "storage/fd.h"
77 : #include "storage/lmgr.h"
78 : #include "storage/standby.h"
79 : #include "utils/acl.h"
80 : #include "utils/builtins.h"
81 : #include "utils/fmgroids.h"
82 : #include "utils/guc_hooks.h"
83 : #include "utils/lsyscache.h"
84 : #include "utils/memutils.h"
85 : #include "utils/rel.h"
86 : #include "utils/varlena.h"
87 :
88 : /* GUC variables */
89 : char *default_tablespace = NULL;
90 : char *temp_tablespaces = NULL;
91 : bool allow_in_place_tablespaces = false;
92 :
93 : Oid binary_upgrade_next_pg_tablespace_oid = InvalidOid;
94 :
95 : static void create_tablespace_directories(const char *location,
96 : const Oid tablespaceoid);
97 : static bool destroy_tablespace_directories(Oid tablespaceoid, bool redo);
98 :
99 :
100 : /*
101 : * Each database using a table space is isolated into its own name space
102 : * by a subdirectory named for the database OID. On first creation of an
103 : * object in the tablespace, create the subdirectory. If the subdirectory
104 : * already exists, fall through quietly.
105 : *
106 : * isRedo indicates that we are creating an object during WAL replay.
107 : * In this case we will cope with the possibility of the tablespace
108 : * directory not being there either --- this could happen if we are
109 : * replaying an operation on a table in a subsequently-dropped tablespace.
110 : * We handle this by making a directory in the place where the tablespace
111 : * symlink would normally be. This isn't an exact replay of course, but
112 : * it's the best we can do given the available information.
113 : *
114 : * If tablespaces are not supported, we still need it in case we have to
115 : * re-create a database subdirectory (of $PGDATA/base) during WAL replay.
116 : */
117 : void
277 rhaas 118 GNC 218866 : TablespaceCreateDbspace(Oid spcOid, Oid dbOid, bool isRedo)
119 : {
120 : struct stat st;
121 : char *dir;
122 :
123 : /*
124 : * The global tablespace doesn't have per-database subdirectories, so
125 : * nothing to do for it.
126 : */
127 218866 : if (spcOid == GLOBALTABLESPACE_OID)
6869 tgl 128 CBC 18612 : return;
129 :
277 rhaas 130 GNC 200254 : Assert(OidIsValid(spcOid));
131 200254 : Assert(OidIsValid(dbOid));
132 :
133 200254 : dir = GetDatabasePath(dbOid, spcOid);
134 :
6869 tgl 135 CBC 200254 : if (stat(dir, &st) < 0)
136 : {
137 : /* Directory does not exist? */
138 20 : if (errno == ENOENT)
139 : {
140 : /*
141 : * Acquire TablespaceCreateLock to ensure that no DROP TABLESPACE
142 : * or TablespaceCreateDbspace is running concurrently.
143 : */
6289 144 20 : LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
145 :
146 : /*
147 : * Recheck to see if someone created the directory while we were
148 : * waiting for lock.
149 : */
6869 150 20 : if (stat(dir, &st) == 0 && S_ISDIR(st.st_mode))
151 : {
152 : /* Directory was created */
153 : }
154 : else
155 : {
156 : /* Directory creation failed? */
1828 sfrost 157 20 : if (MakePGDirectory(dir) < 0)
158 : {
159 : /* Failure other than not exists or not in WAL replay? */
6797 tgl 160 UBC 0 : if (errno != ENOENT || !isRedo)
161 0 : ereport(ERROR,
162 : (errcode_for_file_access(),
163 : errmsg("could not create directory \"%s\": %m",
164 : dir)));
165 :
166 : /*
167 : * During WAL replay, it's conceivable that several levels
168 : * of directories are missing if tablespaces are dropped
169 : * further ahead of the WAL stream than we're currently
170 : * replaying. An easy way forward is to create them as
171 : * plain directories and hope they are removed by further
172 : * WAL replay if necessary. If this also fails, there is
173 : * trouble we cannot get out of, so just report that and
174 : * bail out.
175 : */
255 alvherre 176 0 : if (pg_mkdir_p(dir, pg_dir_create_mode) < 0)
6797 tgl 177 0 : ereport(ERROR,
178 : (errcode_for_file_access(),
179 : errmsg("could not create directory \"%s\": %m",
180 : dir)));
181 : }
182 : }
183 :
6289 tgl 184 CBC 20 : LWLockRelease(TablespaceCreateLock);
185 : }
186 : else
187 : {
6869 tgl 188 UBC 0 : ereport(ERROR,
189 : (errcode_for_file_access(),
190 : errmsg("could not stat directory \"%s\": %m", dir)));
191 : }
192 : }
193 : else
194 : {
195 : /* Is it not a directory? */
6869 tgl 196 CBC 200234 : if (!S_ISDIR(st.st_mode))
6869 tgl 197 UBC 0 : ereport(ERROR,
198 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
199 : errmsg("\"%s\" exists but is not a directory",
200 : dir)));
201 : }
202 :
6869 tgl 203 CBC 200254 : pfree(dir);
204 : }
205 :
206 : /*
207 : * Create a table space
208 : *
209 : * Only superusers can create a tablespace. This seems a reasonable restriction
210 : * since we're determining the system layout and, anyway, we probably have
211 : * root if we're doing this kind of activity
212 : */
213 : Oid
214 48 : CreateTableSpace(CreateTableSpaceStmt *stmt)
215 : {
216 : Relation rel;
6797 bruce 217 ECB : Datum values[Natts_pg_tablespace];
267 peter 218 GNC 48 : bool nulls[Natts_pg_tablespace] = {0};
219 : HeapTuple tuple;
220 : Oid tablespaceoid;
221 : char *location;
222 : Oid ownerId;
223 : Datum newOptions;
224 : bool in_place;
225 :
578 dgustafsson 226 ECB : /* Must be superuser */
6869 tgl 227 GBC 48 : if (!superuser())
6869 tgl 228 UIC 0 : ereport(ERROR,
229 : (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
230 : errmsg("permission denied to create tablespace \"%s\"",
231 : stmt->tablespacename),
232 : errhint("Must be superuser to create a tablespace.")));
233 :
6869 tgl 234 ECB : /* However, the eventual owner of the tablespace need not be */
6869 tgl 235 GBC 48 : if (stmt->owner)
2953 alvherre 236 UIC 0 : ownerId = get_rolespec_oid(stmt->owner, false);
6869 tgl 237 ECB : else
6494 tgl 238 GIC 48 : ownerId = GetUserId();
239 :
6869 tgl 240 ECB : /* Unix-ify the offered path, and strip any trailing slashes */
6869 tgl 241 CBC 48 : location = pstrdup(stmt->location);
6869 tgl 242 GIC 48 : canonicalize_path(location);
243 :
6869 tgl 244 ECB : /* disallow quotes, else CREATE DATABASE would be at risk */
6869 tgl 245 GBC 48 : if (strchr(location, '\''))
6869 tgl 246 UIC 0 : ereport(ERROR,
247 : (errcode(ERRCODE_INVALID_NAME),
248 : errmsg("tablespace location cannot contain single quotes")));
6869 tgl 249 ECB :
450 tmunro 250 GIC 48 : in_place = allow_in_place_tablespaces && strlen(location) == 0;
251 :
252 : /*
253 : * Allowing relative paths seems risky
254 : *
255 : * This also helps us ensure that location is not empty or whitespace,
256 : * unless specifying a developer-only in-place tablespace.
6869 tgl 257 ECB : */
450 tmunro 258 CBC 48 : if (!in_place && !is_absolute_path(location))
6869 tgl 259 GIC 6 : ereport(ERROR,
260 : (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
261 : errmsg("tablespace location must be an absolute path")));
262 :
263 : /*
264 : * Check that location isn't too long. Remember that we're going to append
265 : * 'PG_XXX/<dboid>/<relid>_<fork>.<nnn>'. FYI, we never actually
266 : * reference the whole path here, but MakePGDirectory() uses the first two
267 : * parts.
6869 tgl 268 ECB : */
4835 bruce 269 CBC 42 : if (strlen(location) + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) + 1 +
193 rhaas 270 GBC 42 : OIDCHARS + 1 + OIDCHARS + 1 + FORKNAMECHARS + 1 + OIDCHARS > MAXPGPATH)
6869 tgl 271 UIC 0 : ereport(ERROR,
272 : (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
273 : errmsg("tablespace location \"%s\" is too long",
274 : location)));
275 :
2903 bruce 276 ECB : /* Warn if the tablespace is in the data directory. */
2903 bruce 277 GBC 42 : if (path_is_prefix_of_path(DataDir, location))
2903 bruce 278 UIC 0 : ereport(WARNING,
279 : (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
280 : errmsg("tablespace location should not be inside the data directory")));
281 :
282 : /*
283 : * Disallow creation of tablespaces named "pg_xxx"; we reserve this
284 : * namespace for system purposes.
6866 tgl 285 ECB : */
6866 tgl 286 CBC 42 : if (!allowSystemTableMods && IsReservedName(stmt->tablespacename))
6866 tgl 287 GIC 1 : ereport(ERROR,
288 : (errcode(ERRCODE_RESERVED_NAME),
289 : errmsg("unacceptable tablespace name \"%s\"",
290 : stmt->tablespacename),
291 : errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
292 :
293 : /*
294 : * If built with appropriate switch, whine when regression-testing
295 : * conventions for tablespace names are violated.
296 : */
297 : #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
298 : if (strncmp(stmt->tablespacename, "regress_", 8) != 0)
299 : elog(WARNING, "tablespaces created by regression test cases should have names starting with \"regress_\"");
300 : #endif
301 :
302 : /*
303 : * Check that there is no other tablespace by this name. (The unique
304 : * index would catch this anyway, but might as well give a friendlier
305 : * message.)
6869 tgl 306 ECB : */
4630 rhaas 307 CBC 41 : if (OidIsValid(get_tablespace_oid(stmt->tablespacename, true)))
6869 tgl 308 GIC 1 : ereport(ERROR,
309 : (errcode(ERRCODE_DUPLICATE_OBJECT),
310 : errmsg("tablespace \"%s\" already exists",
311 : stmt->tablespacename)));
312 :
313 : /*
314 : * Insert tuple into pg_tablespace. The purpose of doing this first is to
315 : * lock the proposed tablename against other would-be creators. The
316 : * insertion will roll back if we find problems below.
6869 tgl 317 ECB : */
1539 andres 318 GIC 40 : rel = table_open(TableSpaceRelationId, RowExclusiveLock);
6869 tgl 319 ECB :
447 rhaas 320 GBC 40 : if (IsBinaryUpgrade)
447 rhaas 321 EUB : {
322 : /* Use binary-upgrade override for tablespace oid */
447 rhaas 323 UIC 0 : if (!OidIsValid(binary_upgrade_next_pg_tablespace_oid))
324 0 : ereport(ERROR,
447 rhaas 325 EUB : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
326 : errmsg("pg_tablespace OID value not set when in binary upgrade mode")));
327 :
447 rhaas 328 UIC 0 : tablespaceoid = binary_upgrade_next_pg_tablespace_oid;
447 rhaas 329 LBC 0 : binary_upgrade_next_pg_tablespace_oid = InvalidOid;
330 : }
447 rhaas 331 ECB : else
447 rhaas 332 CBC 40 : tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId,
447 rhaas 333 ECB : Anum_pg_tablespace_oid);
1601 andres 334 CBC 40 : values[Anum_pg_tablespace_oid - 1] = ObjectIdGetDatum(tablespaceoid);
6869 tgl 335 40 : values[Anum_pg_tablespace_spcname - 1] =
336 40 : DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));
6869 tgl 337 GIC 40 : values[Anum_pg_tablespace_spcowner - 1] =
6494 338 40 : ObjectIdGetDatum(ownerId);
5271 tgl 339 CBC 40 : nulls[Anum_pg_tablespace_spcacl - 1] = true;
340 :
341 : /* Generate new proposed spcoptions (text array) */
3368 sfrost 342 40 : newOptions = transformRelOptions((Datum) 0,
3368 sfrost 343 ECB : stmt->options,
344 : NULL, NULL, false, false);
3368 sfrost 345 GIC 40 : (void) tablespace_reloptions(newOptions, true);
3368 sfrost 346 CBC 37 : if (newOptions != (Datum) 0)
3368 sfrost 347 GIC 3 : values[Anum_pg_tablespace_spcoptions - 1] = newOptions;
3368 sfrost 348 ECB : else
3368 sfrost 349 GIC 34 : nulls[Anum_pg_tablespace_spcoptions - 1] = true;
6869 tgl 350 ECB :
5271 tgl 351 GIC 37 : tuple = heap_form_tuple(rel->rd_att, values, nulls);
6869 tgl 352 ECB :
1601 andres 353 GIC 37 : CatalogTupleInsert(rel, tuple);
354 :
6869 tgl 355 CBC 37 : heap_freetuple(tuple);
356 :
357 : /* Record dependency on owner */
6485 358 37 : recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId);
359 :
4518 rhaas 360 ECB : /* Post creation hook for new tablespace */
3686 rhaas 361 GIC 37 : InvokeObjectPostCreateHook(TableSpaceRelationId, tablespaceoid, 0);
362 :
4835 bruce 363 37 : create_tablespace_directories(location, tablespaceoid);
364 :
365 : /* Record the filesystem change in XLOG */
6797 tgl 366 ECB : {
367 : xl_tblspc_create_rec xlrec;
368 :
6797 tgl 369 CBC 33 : xlrec.ts_id = tablespaceoid;
370 :
3062 heikki.linnakangas 371 33 : XLogBeginInsert();
3062 heikki.linnakangas 372 GIC 33 : XLogRegisterData((char *) &xlrec,
3062 heikki.linnakangas 373 ECB : offsetof(xl_tblspc_create_rec, ts_path));
3062 heikki.linnakangas 374 GIC 33 : XLogRegisterData((char *) location, strlen(location) + 1);
375 :
376 33 : (void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_CREATE);
377 : }
378 :
379 : /*
380 : * Force synchronous commit, to minimize the window between creating the
381 : * symlink on-disk and marking the transaction committed. It's not great
5624 bruce 382 ECB : * that there is any window at all, but definitely we don't want to make
383 : * it larger than necessary.
5730 tgl 384 : */
5730 tgl 385 GIC 33 : ForceSyncCommit();
386 :
6869 tgl 387 CBC 33 : pfree(location);
388 :
6797 tgl 389 ECB : /* We keep the lock on pg_tablespace until commit */
1539 andres 390 GIC 33 : table_close(rel, NoLock);
391 :
2773 tgl 392 33 : return tablespaceoid;
393 : }
6869 tgl 394 ECB :
395 : /*
396 : * Drop a table space
397 : *
398 : * Be careful to check that the tablespace is empty.
399 : */
400 : void
6869 tgl 401 GIC 30 : DropTableSpace(DropTableSpaceStmt *stmt)
402 : {
6797 bruce 403 30 : char *tablespacename = stmt->tablespacename;
404 : TableScanDesc scandesc;
405 : Relation rel;
6797 bruce 406 ECB : HeapTuple tuple;
407 : Form_pg_tablespace spcform;
408 : ScanKeyData entry[1];
409 : Oid tablespaceoid;
410 : char *detail;
411 : char *detail_log;
6869 tgl 412 :
413 : /*
414 : * Find the target tuple
415 : */
1539 andres 416 GIC 30 : rel = table_open(TableSpaceRelationId, RowExclusiveLock);
6289 tgl 417 EUB :
6869 tgl 418 GIC 30 : ScanKeyInit(&entry[0],
6869 tgl 419 EUB : Anum_pg_tablespace_spcname,
420 : BTEqualStrategyNumber, F_NAMEEQ,
421 : CStringGetDatum(tablespacename));
1490 andres 422 GIC 30 : scandesc = table_beginscan_catalog(rel, 1, entry);
6869 tgl 423 30 : tuple = heap_getnext(scandesc, ForwardScanDirection);
424 :
425 30 : if (!HeapTupleIsValid(tuple))
6141 andrew 426 EUB : {
6031 bruce 427 UIC 0 : if (!stmt->missing_ok)
428 : {
6141 andrew 429 UBC 0 : ereport(ERROR,
6141 andrew 430 EUB : (errcode(ERRCODE_UNDEFINED_OBJECT),
431 : errmsg("tablespace \"%s\" does not exist",
432 : tablespacename)));
433 : }
434 : else
6141 andrew 435 ECB : {
6141 andrew 436 LBC 0 : ereport(NOTICE,
437 : (errmsg("tablespace \"%s\" does not exist, skipping",
438 : tablespacename)));
1490 andres 439 0 : table_endscan(scandesc);
1539 andres 440 UBC 0 : table_close(rel, NoLock);
441 : }
6141 andrew 442 UIC 0 : return;
443 : }
6869 tgl 444 ECB :
1601 andres 445 GBC 30 : spcform = (Form_pg_tablespace) GETSTRUCT(tuple);
1601 andres 446 GIC 30 : tablespaceoid = spcform->oid;
447 :
448 : /* Must be tablespace owner */
147 peter 449 GNC 30 : if (!object_ownercheck(TableSpaceRelationId, tablespaceoid, GetUserId()))
1954 peter_e 450 UIC 0 : aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE,
6869 tgl 451 ECB : tablespacename);
452 :
453 : /* Disallow drop of the standard tablespaces, even by superuser */
633 tgl 454 GIC 30 : if (IsPinnedObject(TableSpaceRelationId, tablespaceoid))
1954 peter_e 455 UIC 0 : aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE,
456 : tablespacename);
457 :
458 : /* Check for pg_shdepend entries depending on this tablespace */
815 alvherre 459 CBC 30 : if (checkSharedDependencies(TableSpaceRelationId, tablespaceoid,
460 : &detail, &detail_log))
815 alvherre 461 GIC 3 : ereport(ERROR,
462 : (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
463 : errmsg("tablespace \"%s\" cannot be dropped because some objects depend on it",
815 alvherre 464 ECB : tablespacename),
465 : errdetail_internal("%s", detail),
466 : errdetail_log("%s", detail_log)));
467 :
468 : /* DROP hook for the tablespace being removed */
3686 rhaas 469 GIC 27 : InvokeObjectDropHook(TableSpaceRelationId, tablespaceoid, 0);
470 :
6797 tgl 471 ECB : /*
6385 bruce 472 : * Remove the pg_tablespace tuple (this will roll back if we fail below)
473 : */
2258 tgl 474 GIC 27 : CatalogTupleDelete(rel, &tuple->t_self);
475 :
1490 andres 476 27 : table_endscan(scandesc);
6797 tgl 477 ECB :
478 : /*
479 : * Remove any comments or security labels on this tablespace.
480 : */
6265 bruce 481 GIC 27 : DeleteSharedComments(tablespaceoid, TableSpaceRelationId);
4281 rhaas 482 27 : DeleteSharedSecurityLabel(tablespaceoid, TableSpaceRelationId);
6265 bruce 483 ECB :
484 : /*
485 : * Remove dependency on owner.
486 : */
5190 tgl 487 GIC 27 : deleteSharedDependencyRecordsFor(TableSpaceRelationId, tablespaceoid, 0);
6431 tgl 488 ECB :
489 : /*
490 : * Acquire TablespaceCreateLock to ensure that no TablespaceCreateDbspace
491 : * is running concurrently.
492 : */
6289 tgl 493 GIC 27 : LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
494 :
495 : /*
496 : * Try to remove the physical infrastructure.
497 : */
4835 bruce 498 27 : if (!destroy_tablespace_directories(tablespaceoid, false))
5624 tgl 499 ECB : {
500 : /*
501 : * Not all files deleted? However, there can be lingering empty files
502 : * in the directories, left behind by for example DROP TABLE, that
503 : * have been scheduled for deletion at next checkpoint (see comments
504 : * in mdunlink() for details). We could just delete them immediately,
505 : * but we can't tell them apart from important data files that we
506 : * mustn't delete. So instead, we force a checkpoint which will clean
507 : * out any lingering files, and try again.
508 : */
421 tmunro 509 GIC 13 : RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
421 tmunro 510 ECB :
511 : /*
512 : * On Windows, an unlinked file persists in the directory listing
513 : * until no process retains an open handle for the file. The DDL
514 : * commands that schedule files for unlink send invalidation messages
515 : * directing other PostgreSQL processes to close the files, but
516 : * nothing guarantees they'll be processed in time. So, we'll also
517 : * use a global barrier to ask all backends to close all files, and
518 : * wait until they're finished.
519 : */
421 tmunro 520 GIC 13 : LWLockRelease(TablespaceCreateLock);
521 13 : WaitForProcSignalBarrier(EmitProcSignalBarrier(PROCSIGNAL_BARRIER_SMGRRELEASE));
522 13 : LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
523 :
524 : /* And now try again. */
4835 bruce 525 13 : if (!destroy_tablespace_directories(tablespaceoid, false))
526 : {
527 : /* Still not empty, the files must be important then */
5624 tgl 528 4 : ereport(ERROR,
5624 tgl 529 ECB : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
530 : errmsg("tablespace \"%s\" is not empty",
531 : tablespacename)));
532 : }
533 : }
6797 534 :
535 : /* Record the filesystem change in XLOG */
536 : {
537 : xl_tblspc_drop_rec xlrec;
538 :
6797 tgl 539 GIC 23 : xlrec.ts_id = tablespaceoid;
540 :
3062 heikki.linnakangas 541 23 : XLogBeginInsert();
542 23 : XLogRegisterData((char *) &xlrec, sizeof(xl_tblspc_drop_rec));
543 :
544 23 : (void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_DROP);
545 : }
546 :
547 : /*
548 : * Note: because we checked that the tablespace was empty, there should be
6031 bruce 549 ECB : * no need to worry about flushing shared buffers or free space map
550 : * entries for relations in the tablespace.
551 : */
552 :
553 : /*
5624 554 : * Force synchronous commit, to minimize the window between removing the
555 : * files on-disk and marking the transaction committed. It's not great
556 : * that there is any window at all, but definitely we don't want to make
557 : * it larger than necessary.
558 : */
5730 tgl 559 GIC 23 : ForceSyncCommit();
560 :
561 : /*
562 : * Allow TablespaceCreateDbspace again.
563 : */
6289 564 23 : LWLockRelease(TablespaceCreateLock);
565 :
566 : /* We keep the lock on pg_tablespace until commit */
1539 andres 567 23 : table_close(rel, NoLock);
568 : }
569 :
4835 bruce 570 ECB :
571 : /*
572 : * create_tablespace_directories
573 : *
574 : * Attempt to create filesystem infrastructure linking $PGDATA/pg_tblspc/
575 : * to the specified directory
576 : */
577 : static void
4835 bruce 578 GIC 43 : create_tablespace_directories(const char *location, const Oid tablespaceoid)
4835 bruce 579 ECB : {
580 : char *linkloc;
3465 peter_e 581 : char *location_with_version_dir;
3292 tgl 582 EUB : struct stat st;
583 : bool in_place;
584 :
3465 peter_e 585 GIC 43 : linkloc = psprintf("pg_tblspc/%u", tablespaceoid);
586 :
587 : /*
450 tmunro 588 ECB : * If we're asked to make an 'in place' tablespace, create the directory
589 : * directly where the symlink would normally go. This is a developer-only
590 : * option for now, to facilitate regression testing.
591 : */
450 tmunro 592 GIC 43 : in_place = strlen(location) == 0;
593 :
594 43 : if (in_place)
595 : {
596 25 : if (MakePGDirectory(linkloc) < 0 && errno != EEXIST)
450 tmunro 597 LBC 0 : ereport(ERROR,
598 : (errcode_for_file_access(),
450 tmunro 599 ECB : errmsg("could not create directory \"%s\": %m",
600 : linkloc)));
601 : }
602 :
450 tmunro 603 GIC 43 : location_with_version_dir = psprintf("%s/%s", in_place ? linkloc : location,
604 : TABLESPACE_VERSION_DIRECTORY);
605 :
4835 bruce 606 EUB : /*
607 : * Attempt to coerce target directory to safe permissions. If this fails,
608 : * it doesn't exist or has the wrong owner. Not needed for in-place mode,
609 : * because in that case we created the directory with the desired
610 : * permissions.
611 : */
450 tmunro 612 GIC 43 : if (!in_place && chmod(location, pg_dir_create_mode) != 0)
613 : {
4835 bruce 614 4 : if (errno == ENOENT)
615 4 : ereport(ERROR,
616 : (errcode(ERRCODE_UNDEFINED_FILE),
617 : errmsg("directory \"%s\" does not exist", location),
618 : InRecovery ? errhint("Create this directory for the tablespace before "
4382 bruce 619 ECB : "restarting the server.") : 0));
620 : else
4835 bruce 621 LBC 0 : ereport(ERROR,
4790 bruce 622 EUB : (errcode_for_file_access(),
623 : errmsg("could not set permissions on directory \"%s\": %m",
624 : location)));
625 : }
4835 bruce 626 ECB :
4835 bruce 627 EUB : /*
628 : * The creation of the version directory prevents more than one tablespace
629 : * in a single location. This imitates TablespaceCreateDbspace(), but it
630 : * ignores concurrency and missing parent directories. The chmod() would
631 : * have failed in the absence of a parent. pg_tablespace_spcname_index
590 noah 632 ECB : * prevents concurrency.
4835 bruce 633 EUB : */
590 noah 634 GIC 39 : if (stat(location_with_version_dir, &st) < 0)
635 : {
636 36 : if (errno != ENOENT)
4835 bruce 637 LBC 0 : ereport(ERROR,
590 noah 638 EUB : (errcode_for_file_access(),
639 : errmsg("could not stat directory \"%s\": %m",
640 : location_with_version_dir)));
590 noah 641 GIC 36 : else if (MakePGDirectory(location_with_version_dir) < 0)
4835 bruce 642 UIC 0 : ereport(ERROR,
643 : (errcode_for_file_access(),
644 : errmsg("could not create directory \"%s\": %m",
645 : location_with_version_dir)));
4835 bruce 646 ECB : }
590 noah 647 CBC 3 : else if (!S_ISDIR(st.st_mode))
590 noah 648 UIC 0 : ereport(ERROR,
649 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
650 : errmsg("\"%s\" exists but is not a directory",
651 : location_with_version_dir)));
590 noah 652 CBC 3 : else if (!InRecovery)
590 noah 653 UBC 0 : ereport(ERROR,
654 : (errcode(ERRCODE_OBJECT_IN_USE),
655 : errmsg("directory \"%s\" already in use as a tablespace",
656 : location_with_version_dir)));
657 :
3292 tgl 658 ECB : /*
659 : * In recovery, remove old symlink, in case it points to the wrong place.
660 : */
450 tmunro 661 GIC 39 : if (!in_place && InRecovery)
2844 rhaas 662 3 : remove_tablespace_symlink(linkloc);
663 :
664 : /*
665 : * Create the symlink under PGDATA
666 : */
450 tmunro 667 39 : if (!in_place && symlink(location, linkloc) < 0)
4835 bruce 668 UIC 0 : ereport(ERROR,
669 : (errcode_for_file_access(),
670 : errmsg("could not create symbolic link \"%s\": %m",
671 : linkloc)));
672 :
4835 bruce 673 GIC 39 : pfree(linkloc);
674 39 : pfree(location_with_version_dir);
675 39 : }
676 :
4835 bruce 677 ECB :
678 : /*
679 : * destroy_tablespace_directories
680 : *
681 : * Attempt to remove filesystem infrastructure for the tablespace.
682 : *
683 : * 'redo' indicates we are redoing a drop from XLOG; in that case we should
684 : * not throw an ERROR for problems, just LOG them. The worst consequence of
685 : * not removing files here would be failure to release some disk space, which
4080 tgl 686 : * does not justify throwing an error that would require manual intervention
687 : * to get the database running again.
688 : *
689 : * Returns true if successful, false if some subdirectory is not empty
690 : */
691 : static bool
4835 bruce 692 GIC 47 : destroy_tablespace_directories(Oid tablespaceoid, bool redo)
693 : {
694 : char *linkloc;
695 : char *linkloc_with_version_dir;
696 : DIR *dirdesc;
697 : struct dirent *de;
698 : char *subfile;
699 : struct stat st;
700 :
3465 peter_e 701 47 : linkloc_with_version_dir = psprintf("pg_tblspc/%u/%s", tablespaceoid,
702 : TABLESPACE_VERSION_DIRECTORY);
703 :
704 : /*
705 : * Check if the tablespace still contains any files. We try to rmdir each
706 : * per-database directory we find in it. rmdir failure implies there are
707 : * still files in that subdirectory, so give up. (We do not have to worry
708 : * about undoing any already completed rmdirs, since the next attempt to
709 : * use the tablespace from that database will simply recreate the
710 : * subdirectory via TablespaceCreateDbspace.)
6869 tgl 711 ECB : *
6289 712 : * Since we hold TablespaceCreateLock, no one else should be creating any
713 : * fresh subdirectories in parallel. It is possible that new files are
714 : * being created within subdirectories, though, so the rmdir call could
715 : * fail. Worst consequence is a less friendly error message.
5862 716 : *
5862 tgl 717 EUB : * If redo is true then ENOENT is a likely outcome here, and we allow it
718 : * to pass without comment. In normal operation we still allow it, but
719 : * with a warning. This is because even though ProcessUtility disallows
720 : * DROP TABLESPACE in a transaction block, it's possible that a previous
721 : * DROP failed and rolled back after removing the tablespace directories
3260 bruce 722 ECB : * and/or symlink. We want to allow a new DROP attempt to succeed at
723 : * removing the catalog entries (and symlink if still present), so we
3983 tgl 724 EUB : * should not give a hard error here.
725 : */
4835 bruce 726 GIC 47 : dirdesc = AllocateDir(linkloc_with_version_dir);
6869 tgl 727 GBC 47 : if (dirdesc == NULL)
728 : {
5862 tgl 729 GIC 2 : if (errno == ENOENT)
730 : {
5862 tgl 731 GBC 2 : if (!redo)
5862 tgl 732 UBC 0 : ereport(WARNING,
733 : (errcode_for_file_access(),
734 : errmsg("could not open directory \"%s\": %m",
735 : linkloc_with_version_dir)));
736 : /* The symlink might still exist, so go try to remove it */
3983 tgl 737 CBC 2 : goto remove_symlink;
738 : }
4080 tgl 739 LBC 0 : else if (redo)
4080 tgl 740 ECB : {
741 : /* in redo, just log other types of error */
4080 tgl 742 UIC 0 : ereport(LOG,
4080 tgl 743 ECB : (errcode_for_file_access(),
744 : errmsg("could not open directory \"%s\": %m",
745 : linkloc_with_version_dir)));
4080 tgl 746 LBC 0 : pfree(linkloc_with_version_dir);
4080 tgl 747 UIC 0 : return false;
4080 tgl 748 ECB : }
6503 749 : /* else let ReadDir report the error */
6797 750 : }
6869 751 :
4835 bruce 752 GIC 144 : while ((de = ReadDir(dirdesc, linkloc_with_version_dir)) != NULL)
753 : {
6869 tgl 754 116 : if (strcmp(de->d_name, ".") == 0 ||
4835 bruce 755 CBC 79 : strcmp(de->d_name, "..") == 0)
6869 tgl 756 82 : continue;
757 :
3465 peter_e 758 GIC 34 : subfile = psprintf("%s/%s", linkloc_with_version_dir, de->d_name);
759 :
760 : /* This check is just to deliver a friendlier error message */
4080 tgl 761 CBC 34 : if (!redo && !directory_is_empty(subfile))
762 : {
6797 tgl 763 GIC 17 : FreeDir(dirdesc);
4835 bruce 764 CBC 17 : pfree(subfile);
4835 bruce 765 GIC 17 : pfree(linkloc_with_version_dir);
6797 tgl 766 17 : return false;
6797 tgl 767 ECB : }
768 :
4835 bruce 769 : /* remove empty directory */
6869 tgl 770 GIC 17 : if (rmdir(subfile) < 0)
4080 771 1 : ereport(redo ? LOG : ERROR,
772 : (errcode_for_file_access(),
5792 peter_e 773 ECB : errmsg("could not remove directory \"%s\": %m",
6869 tgl 774 : subfile)));
775 :
6869 tgl 776 GIC 17 : pfree(subfile);
777 : }
778 :
779 28 : FreeDir(dirdesc);
780 :
781 : /* remove version directory */
4835 bruce 782 28 : if (rmdir(linkloc_with_version_dir) < 0)
783 : {
4080 tgl 784 1 : ereport(redo ? LOG : ERROR,
785 : (errcode_for_file_access(),
4835 bruce 786 ECB : errmsg("could not remove directory \"%s\": %m",
787 : linkloc_with_version_dir)));
4080 tgl 788 CBC 1 : pfree(linkloc_with_version_dir);
789 1 : return false;
790 : }
4790 bruce 791 ECB :
792 : /*
793 : * Try to remove the symlink. We must however deal with the possibility
794 : * that it's a directory instead of a symlink --- this could happen during
795 : * WAL replay (see TablespaceCreateDbspace).
796 : *
4080 tgl 797 : * Note: in the redo case, we'll return true if this final step fails;
798 : * there's no point in retrying it. Also, ENOENT should provoke no more
3983 799 : * than a warning.
800 : */
3983 tgl 801 GBC 27 : remove_symlink:
4835 bruce 802 GIC 29 : linkloc = pstrdup(linkloc_with_version_dir);
4835 bruce 803 GBC 29 : get_parent_directory(linkloc);
2557 tgl 804 GIC 29 : if (lstat(linkloc, &st) < 0)
805 : {
806 2 : int saved_errno = errno;
807 :
808 2 : ereport(redo ? LOG : (saved_errno == ENOENT ? WARNING : ERROR),
2557 tgl 809 ECB : (errcode_for_file_access(),
810 : errmsg("could not stat file \"%s\": %m",
811 : linkloc)));
812 : }
2557 tgl 813 GBC 27 : else if (S_ISDIR(st.st_mode))
814 : {
4835 bruce 815 20 : if (rmdir(linkloc) < 0)
816 : {
2557 tgl 817 UIC 0 : int saved_errno = errno;
818 :
819 0 : ereport(redo ? LOG : (saved_errno == ENOENT ? WARNING : ERROR),
820 : (errcode_for_file_access(),
821 : errmsg("could not remove directory \"%s\": %m",
822 : linkloc)));
823 : }
6797 tgl 824 EUB : }
2844 rhaas 825 GIC 7 : else if (S_ISLNK(st.st_mode))
826 : {
4835 bruce 827 7 : if (unlink(linkloc) < 0)
828 : {
3357 tgl 829 LBC 0 : int saved_errno = errno;
3357 tgl 830 ECB :
3357 tgl 831 UIC 0 : ereport(redo ? LOG : (saved_errno == ENOENT ? WARNING : ERROR),
6797 tgl 832 ECB : (errcode_for_file_access(),
833 : errmsg("could not remove symbolic link \"%s\": %m",
834 : linkloc)));
835 : }
836 : }
837 : else
838 : {
839 : /* Refuse to remove anything that's not a directory or symlink */
2844 rhaas 840 UIC 0 : ereport(redo ? LOG : ERROR,
2557 tgl 841 ECB : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
842 : errmsg("\"%s\" is not a directory or symbolic link",
843 : linkloc)));
844 : }
845 :
4835 bruce 846 CBC 29 : pfree(linkloc_with_version_dir);
4835 bruce 847 GIC 29 : pfree(linkloc);
6869 tgl 848 ECB :
6797 tgl 849 GIC 29 : return true;
6869 tgl 850 ECB : }
851 :
852 :
853 : /*
854 : * Check if a directory is empty.
855 : *
856 : * This probably belongs somewhere else, but not sure where...
857 : */
6748 858 : bool
6869 tgl 859 GIC 659 : directory_is_empty(const char *path)
860 : {
861 : DIR *dirdesc;
862 : struct dirent *de;
863 :
864 659 : dirdesc = AllocateDir(path);
865 :
6503 866 703 : while ((de = ReadDir(dirdesc, path)) != NULL)
867 : {
6869 868 689 : if (strcmp(de->d_name, ".") == 0 ||
869 667 : strcmp(de->d_name, "..") == 0)
870 44 : continue;
6869 tgl 871 CBC 645 : FreeDir(dirdesc);
6869 tgl 872 GIC 645 : return false;
873 : }
874 :
6869 tgl 875 CBC 14 : FreeDir(dirdesc);
6869 tgl 876 GIC 14 : return true;
6869 tgl 877 ECB : }
878 :
2844 rhaas 879 EUB : /*
880 : * remove_tablespace_symlink
881 : *
882 : * This function removes symlinks in pg_tblspc. On Windows, junction points
883 : * act like directories so we must be able to apply rmdir. This function
2844 rhaas 884 ECB : * works like the symlink removal code in destroy_tablespace_directories,
885 : * except that failure to remove is always an ERROR. But if the file doesn't
886 : * exist at all, that's OK.
887 : */
888 : void
2844 rhaas 889 GIC 4 : remove_tablespace_symlink(const char *linkloc)
2844 rhaas 890 EUB : {
891 : struct stat st;
892 :
2557 tgl 893 GIC 4 : if (lstat(linkloc, &st) < 0)
894 : {
2844 rhaas 895 1 : if (errno == ENOENT)
2844 rhaas 896 CBC 1 : return;
2844 rhaas 897 UIC 0 : ereport(ERROR,
2844 rhaas 898 ECB : (errcode_for_file_access(),
2720 peter_e 899 EUB : errmsg("could not stat file \"%s\": %m", linkloc)));
900 : }
901 :
2844 rhaas 902 GIC 3 : if (S_ISDIR(st.st_mode))
903 : {
904 : /*
905 : * This will fail if the directory isn't empty, but not if it's a
906 : * junction point.
2844 rhaas 907 EUB : */
2557 tgl 908 UIC 0 : if (rmdir(linkloc) < 0 && errno != ENOENT)
2844 rhaas 909 0 : ereport(ERROR,
910 : (errcode_for_file_access(),
911 : errmsg("could not remove directory \"%s\": %m",
912 : linkloc)));
913 : }
2844 rhaas 914 GIC 3 : else if (S_ISLNK(st.st_mode))
915 : {
916 3 : if (unlink(linkloc) < 0 && errno != ENOENT)
2844 rhaas 917 LBC 0 : ereport(ERROR,
918 : (errcode_for_file_access(),
919 : errmsg("could not remove symbolic link \"%s\": %m",
920 : linkloc)));
921 : }
922 : else
923 : {
924 : /* Refuse to remove anything that's not a directory or symlink */
2844 rhaas 925 UIC 0 : ereport(ERROR,
926 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
927 : errmsg("\"%s\" is not a directory or symbolic link",
2844 rhaas 928 ECB : linkloc)));
929 : }
930 : }
931 :
932 : /*
933 : * Rename a tablespace
6862 tgl 934 : */
2959 alvherre 935 : ObjectAddress
6862 tgl 936 CBC 3 : RenameTableSpace(const char *oldname, const char *newname)
6862 tgl 937 EUB : {
938 : Oid tspId;
939 : Relation rel;
940 : ScanKeyData entry[1];
941 : TableScanDesc scan;
6862 tgl 942 ECB : HeapTuple tup;
943 : HeapTuple newtuple;
944 : Form_pg_tablespace newform;
945 : ObjectAddress address;
946 :
947 : /* Search pg_tablespace */
1539 andres 948 GIC 3 : rel = table_open(TableSpaceRelationId, RowExclusiveLock);
6862 tgl 949 ECB :
6862 tgl 950 GBC 3 : ScanKeyInit(&entry[0],
951 : Anum_pg_tablespace_spcname,
952 : BTEqualStrategyNumber, F_NAMEEQ,
6862 tgl 953 ECB : CStringGetDatum(oldname));
1490 andres 954 GBC 3 : scan = table_beginscan_catalog(rel, 1, entry);
6862 tgl 955 GIC 3 : tup = heap_getnext(scan, ForwardScanDirection);
956 3 : if (!HeapTupleIsValid(tup))
6862 tgl 957 UIC 0 : ereport(ERROR,
958 : (errcode(ERRCODE_UNDEFINED_OBJECT),
959 : errmsg("tablespace \"%s\" does not exist",
960 : oldname)));
961 :
6862 tgl 962 GIC 3 : newtuple = heap_copytuple(tup);
963 3 : newform = (Form_pg_tablespace) GETSTRUCT(newtuple);
1601 andres 964 3 : tspId = newform->oid;
965 :
1490 966 3 : table_endscan(scan);
967 :
968 : /* Must be owner */
147 peter 969 GNC 3 : if (!object_ownercheck(TableSpaceRelationId, tspId, GetUserId()))
1954 peter_e 970 UIC 0 : aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE, oldname);
971 :
972 : /* Validate new name */
6862 tgl 973 CBC 3 : if (!allowSystemTableMods && IsReservedName(newname))
6862 tgl 974 LBC 0 : ereport(ERROR,
6862 tgl 975 ECB : (errcode(ERRCODE_RESERVED_NAME),
6862 tgl 976 EUB : errmsg("unacceptable tablespace name \"%s\"", newname),
977 : errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
978 :
979 : /*
980 : * If built with appropriate switch, whine when regression-testing
1380 tgl 981 ECB : * conventions for tablespace names are violated.
982 : */
983 : #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
984 : if (strncmp(newname, "regress_", 8) != 0)
985 : elog(WARNING, "tablespaces created by regression test cases should have names starting with \"regress_\"");
986 : #endif
987 :
6862 988 : /* Make sure the new name doesn't exist */
6862 tgl 989 GIC 3 : ScanKeyInit(&entry[0],
6862 tgl 990 ECB : Anum_pg_tablespace_spcname,
991 : BTEqualStrategyNumber, F_NAMEEQ,
992 : CStringGetDatum(newname));
1490 andres 993 GIC 3 : scan = table_beginscan_catalog(rel, 1, entry);
6862 tgl 994 CBC 3 : tup = heap_getnext(scan, ForwardScanDirection);
6862 tgl 995 GIC 3 : if (HeapTupleIsValid(tup))
6862 tgl 996 UIC 0 : ereport(ERROR,
997 : (errcode(ERRCODE_DUPLICATE_OBJECT),
998 : errmsg("tablespace \"%s\" already exists",
999 : newname)));
1000 :
1490 andres 1001 CBC 3 : table_endscan(scan);
1002 :
1003 : /* OK, update the entry */
6862 tgl 1004 GIC 3 : namestrcpy(&(newform->spcname), newname);
1005 :
2259 alvherre 1006 3 : CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
1007 :
3675 rhaas 1008 3 : InvokeObjectPostAlterHook(TableSpaceRelationId, tspId, 0);
1009 :
2959 alvherre 1010 3 : ObjectAddressSet(address, TableSpaceRelationId, tspId);
1011 :
1539 andres 1012 3 : table_close(rel, NoLock);
1013 :
2959 alvherre 1014 3 : return address;
1015 : }
1016 :
4842 rhaas 1017 ECB : /*
1018 : * Alter table space options
1019 : */
1020 : Oid
4842 rhaas 1021 GIC 12 : AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
4842 rhaas 1022 ECB : {
1023 : Relation rel;
1024 : ScanKeyData entry[1];
1490 andres 1025 : TableScanDesc scandesc;
4842 rhaas 1026 EUB : HeapTuple tup;
1027 : Oid tablespaceoid;
1028 : Datum datum;
1029 : Datum newOptions;
1030 : Datum repl_val[Natts_pg_tablespace];
4842 rhaas 1031 ECB : bool isnull;
1032 : bool repl_null[Natts_pg_tablespace];
1033 : bool repl_repl[Natts_pg_tablespace];
1034 : HeapTuple newtuple;
4842 rhaas 1035 EUB :
1036 : /* Search pg_tablespace */
1539 andres 1037 GIC 12 : rel = table_open(TableSpaceRelationId, RowExclusiveLock);
1038 :
4842 rhaas 1039 CBC 12 : ScanKeyInit(&entry[0],
1040 : Anum_pg_tablespace_spcname,
4842 rhaas 1041 ECB : BTEqualStrategyNumber, F_NAMEEQ,
4842 rhaas 1042 GIC 12 : CStringGetDatum(stmt->tablespacename));
1490 andres 1043 CBC 12 : scandesc = table_beginscan_catalog(rel, 1, entry);
4842 rhaas 1044 12 : tup = heap_getnext(scandesc, ForwardScanDirection);
4842 rhaas 1045 GIC 12 : if (!HeapTupleIsValid(tup))
4842 rhaas 1046 UIC 0 : ereport(ERROR,
4842 rhaas 1047 ECB : (errcode(ERRCODE_UNDEFINED_OBJECT),
1048 : errmsg("tablespace \"%s\" does not exist",
4790 bruce 1049 : stmt->tablespacename)));
4842 rhaas 1050 :
1601 andres 1051 GIC 12 : tablespaceoid = ((Form_pg_tablespace) GETSTRUCT(tup))->oid;
3753 rhaas 1052 EUB :
4842 rhaas 1053 ECB : /* Must be owner of the existing object */
147 peter 1054 GNC 12 : if (!object_ownercheck(TableSpaceRelationId, tablespaceoid, GetUserId()))
1954 peter_e 1055 UIC 0 : aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE,
4842 rhaas 1056 0 : stmt->tablespacename);
1057 :
4842 rhaas 1058 ECB : /* Generate new proposed spcoptions (text array) */
4842 rhaas 1059 GIC 12 : datum = heap_getattr(tup, Anum_pg_tablespace_spcoptions,
4842 rhaas 1060 ECB : RelationGetDescr(rel), &isnull);
4842 rhaas 1061 GIC 12 : newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
4842 rhaas 1062 ECB : stmt->options, NULL, NULL, false,
4842 rhaas 1063 GIC 12 : stmt->isReset);
1064 9 : (void) tablespace_reloptions(newOptions, true);
4842 rhaas 1065 ECB :
1066 : /* Build new tuple. */
4842 rhaas 1067 GIC 6 : memset(repl_null, false, sizeof(repl_null));
4842 rhaas 1068 CBC 6 : memset(repl_repl, false, sizeof(repl_repl));
4842 rhaas 1069 GIC 6 : if (newOptions != (Datum) 0)
1070 6 : repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions;
1071 : else
4842 rhaas 1072 UIC 0 : repl_null[Anum_pg_tablespace_spcoptions - 1] = true;
4842 rhaas 1073 GIC 6 : repl_repl[Anum_pg_tablespace_spcoptions - 1] = true;
1074 6 : newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val,
1075 : repl_null, repl_repl);
1076 :
4842 rhaas 1077 ECB : /* Update system catalog. */
2259 alvherre 1078 GIC 6 : CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
1079 :
1601 andres 1080 6 : InvokeObjectPostAlterHook(TableSpaceRelationId, tablespaceoid, 0);
1081 :
4842 rhaas 1082 6 : heap_freetuple(newtuple);
1083 :
4842 rhaas 1084 ECB : /* Conclude heap scan. */
1490 andres 1085 GIC 6 : table_endscan(scandesc);
1539 andres 1086 CBC 6 : table_close(rel, NoLock);
3753 rhaas 1087 ECB :
3753 rhaas 1088 GIC 6 : return tablespaceoid;
1089 : }
1090 :
1091 : /*
1092 : * Routines for handling the GUC variable 'default_tablespace'.
6729 tgl 1093 EUB : */
1094 :
4385 1095 : /* check_hook: validate new default_tablespace */
1096 : bool
4385 tgl 1097 GIC 2149 : check_default_tablespace(char **newval, void **extra, GucSource source)
1098 : {
1099 : /*
1100 : * If we aren't inside a transaction, or connected to a database, we
1101 : * cannot do the catalog accesses necessary to verify the name. Must
1399 andres 1102 EUB : * accept the value on faith.
1103 : */
1399 andres 1104 GBC 2149 : if (IsTransactionState() && MyDatabaseId != InvalidOid)
1105 : {
4385 tgl 1106 GIC 316 : if (**newval != '\0' &&
1107 24 : !OidIsValid(get_tablespace_oid(*newval, true)))
1108 : {
4087 heikki.linnakangas 1109 ECB : /*
1110 : * When source == PGC_S_TEST, don't throw a hard error for a
1111 : * nonexistent tablespace, only a NOTICE. See comments in guc.h.
1112 : */
4087 heikki.linnakangas 1113 UIC 0 : if (source == PGC_S_TEST)
1114 : {
1115 0 : ereport(NOTICE,
1116 : (errcode(ERRCODE_UNDEFINED_OBJECT),
1117 : errmsg("tablespace \"%s\" does not exist",
1118 : *newval)));
1119 : }
1120 : else
1121 : {
1122 0 : GUC_check_errdetail("Tablespace \"%s\" does not exist.",
1123 : *newval);
1124 0 : return false;
1125 : }
1126 : }
1127 : }
1128 :
4385 tgl 1129 CBC 2149 : return true;
1130 : }
1131 :
1132 : /*
1133 : * GetDefaultTablespace -- get the OID of the current default tablespace
6729 tgl 1134 ECB : *
1135 : * Temporary objects have different default tablespaces, hence the
1445 alvherre 1136 : * relpersistence parameter must be specified. Also, for partitioned tables,
1137 : * we disallow specifying the database default, so that needs to be specified
1138 : * too.
1139 : *
1140 : * May return InvalidOid to indicate "use the database's default tablespace".
5789 tgl 1141 : *
1142 : * Note that caller is expected to check appropriate permissions for any
1143 : * result other than InvalidOid.
1144 : *
1145 : * This exists to hide (and possibly optimize the use of) the
1146 : * default_tablespace GUC variable.
1147 : */
1148 : Oid
1445 alvherre 1149 GIC 108196 : GetDefaultTablespace(char relpersistence, bool partitioned)
1150 : {
6729 tgl 1151 ECB : Oid result;
1152 :
1153 : /* The temp-table case is handled elsewhere */
4500 rhaas 1154 GIC 108196 : if (relpersistence == RELPERSISTENCE_TEMP)
1155 : {
5785 tgl 1156 1895 : PrepareTempTablespaces();
1157 1895 : return GetNextTempTableSpace();
1158 : }
5789 tgl 1159 ECB :
1160 : /* Fast path for default_tablespace == "" */
6729 tgl 1161 CBC 106301 : if (default_tablespace == NULL || default_tablespace[0] == '\0')
1162 106274 : return InvalidOid;
1163 :
1164 : /*
6729 tgl 1165 EUB : * It is tempting to cache this lookup for more speed, but then we would
1166 : * fail to detect the case where the tablespace was dropped since the GUC
6385 bruce 1167 ECB : * variable was set. Note also that we don't complain if the value fails
1168 : * to refer to an existing tablespace; we just silently return InvalidOid,
1169 : * causing the new object to be created in the database's tablespace.
1170 : */
4630 rhaas 1171 GIC 27 : result = get_tablespace_oid(default_tablespace, true);
1172 :
1173 : /*
1174 : * Allow explicit specification of database's default tablespace in
1175 : * default_tablespace without triggering permissions checks. Don't allow
1176 : * specifying that when creating a partitioned table, however, since the
1177 : * result is confusing.
1178 : */
6729 tgl 1179 27 : if (result == MyDatabaseTableSpace)
1180 : {
1445 alvherre 1181 6 : if (partitioned)
1182 6 : ereport(ERROR,
1183 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1445 alvherre 1184 ECB : errmsg("cannot specify default tablespace for partitioned relations")));
6729 tgl 1185 UIC 0 : result = InvalidOid;
1186 : }
6729 tgl 1187 GIC 21 : return result;
1188 : }
1189 :
6729 tgl 1190 ECB :
1191 : /*
1192 : * Routines for handling the GUC variable 'temp_tablespaces'.
5789 1193 : */
1194 :
1195 : typedef struct
4385 tgl 1196 EUB : {
1010 1197 : /* Array of OIDs to be passed to SetTempTablespaces() */
4385 1198 : int numSpcs;
2970 1199 : Oid tblSpcs[FLEXIBLE_ARRAY_MEMBER];
1200 : } temp_tablespaces_extra;
1201 :
1202 : /* check_hook: validate new temp_tablespaces */
1203 : bool
4385 tgl 1204 GIC 1861 : check_temp_tablespaces(char **newval, void **extra, GucSource source)
1205 : {
1206 : char *rawname;
1207 : List *namelist;
5789 tgl 1208 ECB :
1209 : /* Need a modifiable copy of string */
4385 tgl 1210 GIC 1861 : rawname = pstrdup(*newval);
1211 :
1212 : /* Parse string into list of identifiers */
5789 1213 1861 : if (!SplitIdentifierString(rawname, ',', &namelist))
1214 : {
1215 : /* syntax error in name list */
4385 tgl 1216 UBC 0 : GUC_check_errdetail("List syntax is invalid.");
5789 1217 0 : pfree(rawname);
1218 0 : list_free(namelist);
4385 tgl 1219 UIC 0 : return false;
5789 tgl 1220 EUB : }
1221 :
1222 : /*
1223 : * If we aren't inside a transaction, or connected to a database, we
1224 : * cannot do the catalog accesses necessary to verify the name. Must
1378 1225 : * accept the value on faith. Fortunately, there's then also no need to
1226 : * pass the data to fd.c.
1227 : */
1399 andres 1228 GBC 1861 : if (IsTransactionState() && MyDatabaseId != InvalidOid)
5789 tgl 1229 EUB : {
1230 : temp_tablespaces_extra *myextra;
1231 : Oid *tblSpcs;
1232 : int numSpcs;
1233 : ListCell *l;
1234 :
1235 : /* temporary workspace until we are done verifying the list */
4385 tgl 1236 UIC 0 : tblSpcs = (Oid *) palloc(list_length(namelist) * sizeof(Oid));
5785 tgl 1237 UBC 0 : numSpcs = 0;
5789 1238 0 : foreach(l, namelist)
1239 : {
1240 0 : char *curname = (char *) lfirst(l);
5785 tgl 1241 EUB : Oid curoid;
1242 : AclResult aclresult;
1243 :
1244 : /* Allow an empty string (signifying database default) */
5789 tgl 1245 UBC 0 : if (curname[0] == '\0')
1246 : {
1247 : /* InvalidOid signifies database's default tablespace */
5785 tgl 1248 UIC 0 : tblSpcs[numSpcs++] = InvalidOid;
5789 1249 0 : continue;
1250 : }
1251 :
4630 rhaas 1252 EUB : /*
1253 : * In an interactive SET command, we ereport for bad info. When
1254 : * source == PGC_S_TEST, don't throw a hard error for a
3505 tgl 1255 : * nonexistent tablespace, only a NOTICE. See comments in guc.h.
4630 rhaas 1256 : */
4087 heikki.linnakangas 1257 UIC 0 : curoid = get_tablespace_oid(curname, source <= PGC_S_TEST);
5785 tgl 1258 0 : if (curoid == InvalidOid)
1259 : {
4087 heikki.linnakangas 1260 UBC 0 : if (source == PGC_S_TEST)
4087 heikki.linnakangas 1261 UIC 0 : ereport(NOTICE,
4087 heikki.linnakangas 1262 EUB : (errcode(ERRCODE_UNDEFINED_OBJECT),
1263 : errmsg("tablespace \"%s\" does not exist",
1264 : curname)));
5785 tgl 1265 UBC 0 : continue;
4087 heikki.linnakangas 1266 EUB : }
1267 :
1268 : /*
5785 tgl 1269 : * Allow explicit specification of database's default tablespace
1270 : * in temp_tablespaces without triggering permissions checks.
1271 : */
5785 tgl 1272 UIC 0 : if (curoid == MyDatabaseTableSpace)
5785 tgl 1273 EUB : {
1274 : /* InvalidOid signifies database's default tablespace */
5785 tgl 1275 UBC 0 : tblSpcs[numSpcs++] = InvalidOid;
1276 0 : continue;
5785 tgl 1277 EUB : }
1278 :
4385 1279 : /* Check permissions, similarly complaining only if interactive */
147 peter 1280 UNC 0 : aclresult = object_aclcheck(TableSpaceRelationId, curoid, GetUserId(),
5785 tgl 1281 EUB : ACL_CREATE);
5785 tgl 1282 UIC 0 : if (aclresult != ACLCHECK_OK)
1283 : {
5785 tgl 1284 LBC 0 : if (source >= PGC_S_INTERACTIVE)
1954 peter_e 1285 0 : aclcheck_error(aclresult, OBJECT_TABLESPACE, curname);
5785 tgl 1286 UIC 0 : continue;
5785 tgl 1287 ECB : }
1288 :
5785 tgl 1289 UIC 0 : tblSpcs[numSpcs++] = curoid;
1290 : }
1291 :
4385 tgl 1292 ECB : /* Now prepare an "extra" struct for assign_temp_tablespaces */
177 tgl 1293 UNC 0 : myextra = guc_malloc(LOG, offsetof(temp_tablespaces_extra, tblSpcs) +
1294 : numSpcs * sizeof(Oid));
4385 tgl 1295 UIC 0 : if (!myextra)
1296 0 : return false;
1297 0 : myextra->numSpcs = numSpcs;
1298 0 : memcpy(myextra->tblSpcs, tblSpcs, numSpcs * sizeof(Oid));
1299 0 : *extra = (void *) myextra;
1300 :
1301 0 : pfree(tblSpcs);
1302 : }
5789 tgl 1303 ECB :
5789 tgl 1304 GBC 1861 : pfree(rawname);
5789 tgl 1305 GIC 1861 : list_free(namelist);
5789 tgl 1306 ECB :
4385 tgl 1307 CBC 1861 : return true;
1308 : }
1309 :
1310 : /* assign_hook: do extra actions as needed */
1311 : void
4385 tgl 1312 GIC 1861 : assign_temp_tablespaces(const char *newval, void *extra)
1313 : {
1314 1861 : temp_tablespaces_extra *myextra = (temp_tablespaces_extra *) extra;
1315 :
1316 : /*
4385 tgl 1317 ECB : * If check_temp_tablespaces was executed inside a transaction, then pass
1318 : * the list it made to fd.c. Otherwise, clear fd.c's list; we must be
1319 : * still outside a transaction, or else restoring during transaction exit,
1320 : * and in either case we can just let the next PrepareTempTablespaces call
1321 : * make things sane.
1322 : */
4385 tgl 1323 GIC 1861 : if (myextra)
4385 tgl 1324 UIC 0 : SetTempTablespaces(myextra->tblSpcs, myextra->numSpcs);
1325 : else
4385 tgl 1326 CBC 1861 : SetTempTablespaces(NULL, 0);
5789 1327 1861 : }
1328 :
1329 : /*
1330 : * PrepareTempTablespaces -- prepare to use temp tablespaces
1331 : *
1332 : * If we have not already done so in the current transaction, parse the
1333 : * temp_tablespaces GUC variable and tell fd.c which tablespace(s) to use
1334 : * for temp files.
1335 : */
5785 tgl 1336 ECB : void
5785 tgl 1337 CBC 4351 : PrepareTempTablespaces(void)
1338 : {
1339 : char *rawname;
5789 tgl 1340 ECB : List *namelist;
1341 : Oid *tblSpcs;
1342 : int numSpcs;
5785 1343 : ListCell *l;
1344 :
1345 : /* No work if already done in current transaction */
5785 tgl 1346 GBC 4351 : if (TempTablespacesAreSet())
1347 2567 : return;
5789 tgl 1348 EUB :
1349 : /*
1350 : * Can't do catalog access unless within a transaction. This is just a
1351 : * safety check in case this function is called by low-level code that
1352 : * could conceivably execute outside a transaction. Note that in such a
5624 bruce 1353 ECB : * scenario, fd.c will fall back to using the current database's default
5785 tgl 1354 : * tablespace, which should always be OK.
5789 1355 : */
5785 tgl 1356 CBC 1909 : if (!IsTransactionState())
5785 tgl 1357 GIC 125 : return;
5789 tgl 1358 ECB :
1359 : /* Need a modifiable copy of string */
5789 tgl 1360 GIC 1784 : rawname = pstrdup(temp_tablespaces);
1361 :
1362 : /* Parse string into list of identifiers */
5789 tgl 1363 CBC 1784 : if (!SplitIdentifierString(rawname, ',', &namelist))
1364 : {
1365 : /* syntax error in name list */
5785 tgl 1366 UBC 0 : SetTempTablespaces(NULL, 0);
5789 1367 0 : pfree(rawname);
5789 tgl 1368 UIC 0 : list_free(namelist);
5785 1369 0 : return;
1370 : }
5789 tgl 1371 ECB :
5785 1372 : /* Store tablespace OIDs in an array in TopTransactionContext */
5785 tgl 1373 GIC 1784 : tblSpcs = (Oid *) MemoryContextAlloc(TopTransactionContext,
5624 bruce 1374 1784 : list_length(namelist) * sizeof(Oid));
5785 tgl 1375 GBC 1784 : numSpcs = 0;
5785 tgl 1376 GIC 1785 : foreach(l, namelist)
1377 : {
1378 1 : char *curname = (char *) lfirst(l);
1379 : Oid curoid;
1380 : AclResult aclresult;
1381 :
5785 tgl 1382 ECB : /* Allow an empty string (signifying database default) */
5785 tgl 1383 GIC 1 : if (curname[0] == '\0')
1384 : {
1010 tgl 1385 EUB : /* InvalidOid signifies database's default tablespace */
5785 tgl 1386 UBC 0 : tblSpcs[numSpcs++] = InvalidOid;
5785 tgl 1387 UIC 0 : continue;
1388 : }
1389 :
5785 tgl 1390 ECB : /* Else verify that name is a valid tablespace name */
4630 rhaas 1391 GIC 1 : curoid = get_tablespace_oid(curname, true);
5785 tgl 1392 CBC 1 : if (curoid == InvalidOid)
5785 tgl 1393 EUB : {
1394 : /* Skip any bad list elements */
5785 tgl 1395 LBC 0 : continue;
1396 : }
1397 :
5785 tgl 1398 ECB : /*
1399 : * Allow explicit specification of database's default tablespace in
5624 bruce 1400 : * temp_tablespaces without triggering permissions checks.
5785 tgl 1401 : */
5785 tgl 1402 GIC 1 : if (curoid == MyDatabaseTableSpace)
1403 : {
1404 : /* InvalidOid signifies database's default tablespace */
1010 tgl 1405 UIC 0 : tblSpcs[numSpcs++] = InvalidOid;
5785 1406 0 : continue;
1407 : }
1408 :
1409 : /* Check permissions similarly */
147 peter 1410 GNC 1 : aclresult = object_aclcheck(TableSpaceRelationId, curoid, GetUserId(),
1411 : ACL_CREATE);
5785 tgl 1412 CBC 1 : if (aclresult != ACLCHECK_OK)
5785 tgl 1413 UIC 0 : continue;
1414 :
5785 tgl 1415 GIC 1 : tblSpcs[numSpcs++] = curoid;
1416 : }
1417 :
1418 1784 : SetTempTablespaces(tblSpcs, numSpcs);
1419 :
5789 1420 1784 : pfree(rawname);
1421 1784 : list_free(namelist);
1422 : }
1423 :
1424 :
6729 tgl 1425 ECB : /*
1426 : * get_tablespace_oid - given a tablespace name, look up the OID
1427 : *
1428 : * If missing_ok is false, throw an error if tablespace name not found. If
1429 : * true, just return InvalidOid.
1430 : */
1431 : Oid
4630 rhaas 1432 CBC 437 : get_tablespace_oid(const char *tablespacename, bool missing_ok)
1433 : {
1434 : Oid result;
6729 tgl 1435 ECB : Relation rel;
1490 andres 1436 : TableScanDesc scandesc;
1437 : HeapTuple tuple;
6729 tgl 1438 : ScanKeyData entry[1];
1439 :
5789 1440 : /*
1441 : * Search pg_tablespace. We use a heapscan here even though there is an
1442 : * index on name, on the theory that pg_tablespace will usually have just
1443 : * a few entries and so an indexed lookup is a waste of effort.
1444 : */
1539 andres 1445 GIC 437 : rel = table_open(TableSpaceRelationId, AccessShareLock);
1446 :
6729 tgl 1447 437 : ScanKeyInit(&entry[0],
1448 : Anum_pg_tablespace_spcname,
6729 tgl 1449 ECB : BTEqualStrategyNumber, F_NAMEEQ,
1450 : CStringGetDatum(tablespacename));
1490 andres 1451 GIC 437 : scandesc = table_beginscan_catalog(rel, 1, entry);
6729 tgl 1452 437 : tuple = heap_getnext(scandesc, ForwardScanDirection);
1453 :
1454 : /* We assume that there can be at most one matching tuple */
1455 437 : if (HeapTupleIsValid(tuple))
1601 andres 1456 391 : result = ((Form_pg_tablespace) GETSTRUCT(tuple))->oid;
1457 : else
6729 tgl 1458 CBC 46 : result = InvalidOid;
1459 :
1490 andres 1460 GIC 437 : table_endscan(scandesc);
1539 1461 437 : table_close(rel, AccessShareLock);
1462 :
4630 rhaas 1463 437 : if (!OidIsValid(result) && !missing_ok)
4382 bruce 1464 6 : ereport(ERROR,
1465 : (errcode(ERRCODE_UNDEFINED_OBJECT),
1466 : errmsg("tablespace \"%s\" does not exist",
1467 : tablespacename)));
1468 :
6729 tgl 1469 431 : return result;
1470 : }
6729 tgl 1471 ECB :
1472 : /*
1473 : * get_tablespace_name - given a tablespace OID, look up the name
1474 : *
1475 : * Returns a palloc'd string, or NULL if no such tablespace.
1476 : */
1477 : char *
6729 tgl 1478 CBC 128 : get_tablespace_name(Oid spc_oid)
1479 : {
1480 : char *result;
6729 tgl 1481 ECB : Relation rel;
1490 andres 1482 : TableScanDesc scandesc;
1483 : HeapTuple tuple;
6729 tgl 1484 : ScanKeyData entry[1];
1485 :
5789 1486 : /*
1487 : * Search pg_tablespace. We use a heapscan here even though there is an
1488 : * index on oid, on the theory that pg_tablespace will usually have just a
5624 bruce 1489 : * few entries and so an indexed lookup is a waste of effort.
1490 : */
1539 andres 1491 GIC 128 : rel = table_open(TableSpaceRelationId, AccessShareLock);
1492 :
6729 tgl 1493 128 : ScanKeyInit(&entry[0],
1494 : Anum_pg_tablespace_oid,
1495 : BTEqualStrategyNumber, F_OIDEQ,
1496 : ObjectIdGetDatum(spc_oid));
1490 andres 1497 CBC 128 : scandesc = table_beginscan_catalog(rel, 1, entry);
6729 tgl 1498 GIC 128 : tuple = heap_getnext(scandesc, ForwardScanDirection);
6729 tgl 1499 ECB :
1500 : /* We assume that there can be at most one matching tuple */
6729 tgl 1501 GIC 128 : if (HeapTupleIsValid(tuple))
6729 tgl 1502 CBC 119 : result = pstrdup(NameStr(((Form_pg_tablespace) GETSTRUCT(tuple))->spcname));
1503 : else
1504 9 : result = NULL;
1505 :
1490 andres 1506 128 : table_endscan(scandesc);
1539 1507 128 : table_close(rel, AccessShareLock);
1508 :
6729 tgl 1509 128 : return result;
1510 : }
6729 tgl 1511 ECB :
1512 :
6797 1513 : /*
1514 : * TABLESPACE resource manager's routines
1515 : */
1516 : void
3062 heikki.linnakangas 1517 GIC 12 : tblspc_redo(XLogReaderState *record)
1518 : {
1519 12 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1520 :
1521 : /* Backup blocks are not used in tblspc records */
1522 12 : Assert(!XLogRecHasAnyBlockRefs(record));
1523 :
6797 tgl 1524 12 : if (info == XLOG_TBLSPC_CREATE)
1525 : {
1526 6 : xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) XLogRecGetData(record);
1527 6 : char *location = xlrec->ts_path;
1528 :
4835 bruce 1529 6 : create_tablespace_directories(location, xlrec->ts_id);
1530 : }
6797 tgl 1531 6 : else if (info == XLOG_TBLSPC_DROP)
1532 : {
6797 tgl 1533 CBC 6 : xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) XLogRecGetData(record);
1534 :
337 tmunro 1535 ECB : /* Close all smgr fds in all backends. */
337 tmunro 1536 GIC 6 : WaitForProcSignalBarrier(EmitProcSignalBarrier(PROCSIGNAL_BARRIER_SMGRRELEASE));
1537 :
1538 : /*
1539 : * If we issued a WAL record for a drop tablespace it implies that
1540 : * there were no files in it at all when the DROP was done. That means
1541 : * that no permanent objects can exist in it at this point.
1542 : *
1543 : * It is possible for standby users to be using this tablespace as a
1544 : * location for their temporary files, so if we fail to remove all
4790 bruce 1545 ECB : * files then do conflict processing and try again, if currently
4790 bruce 1546 EUB : * enabled.
1547 : *
1548 : * Other possible reasons for failure include bollixed file
1549 : * permissions on a standby server when they were okay on the primary,
1550 : * etc etc. There's not much we can do about that, so just remove what
1551 : * we can and press on.
1552 : */
4835 bruce 1553 GIC 6 : if (!destroy_tablespace_directories(xlrec->ts_id, true))
4859 simon 1554 EUB : {
4833 simon 1555 CBC 1 : ResolveRecoveryConflictWithTablespace(xlrec->ts_id);
1556 :
1557 : /*
1558 : * If we did recovery processing then hopefully the backends who
1559 : * wrote temp files should have cleaned up and exited by now. So
1560 : * retry before complaining. If we fail again, this is just a LOG
1561 : * condition, because it's not worth throwing an ERROR for (as
1562 : * that would crash the database and require manual intervention
1563 : * before we could get past this WAL record on restart).
1564 : */
4835 bruce 1565 GIC 1 : if (!destroy_tablespace_directories(xlrec->ts_id, true))
4080 tgl 1566 UIC 0 : ereport(LOG,
1567 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1568 : errmsg("directories for tablespace %u could not be removed",
1569 : xlrec->ts_id),
1570 : errhint("You can remove the directories manually if necessary.")));
1571 : }
1572 : }
1573 : else
6797 1574 0 : elog(PANIC, "tblspc_redo: unknown op code %u", info);
6797 tgl 1575 GIC 12 : }
|