PostgreSQL Source Code  git master
tablespace.h File Reference
Include dependency graph for tablespace.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  xl_tblspc_create_rec
 
struct  xl_tblspc_drop_rec
 
struct  TableSpaceOpts
 

Macros

#define XLOG_TBLSPC_CREATE   0x00
 
#define XLOG_TBLSPC_DROP   0x10
 

Typedefs

typedef struct xl_tblspc_create_rec xl_tblspc_create_rec
 
typedef struct xl_tblspc_drop_rec xl_tblspc_drop_rec
 
typedef struct TableSpaceOpts TableSpaceOpts
 

Functions

Oid CreateTableSpace (CreateTableSpaceStmt *stmt)
 
void DropTableSpace (DropTableSpaceStmt *stmt)
 
ObjectAddress RenameTableSpace (const char *oldname, const char *newname)
 
Oid AlterTableSpaceOptions (AlterTableSpaceOptionsStmt *stmt)
 
void TablespaceCreateDbspace (Oid spcNode, Oid dbNode, bool isRedo)
 
Oid GetDefaultTablespace (char relpersistence, bool partitioned)
 
void PrepareTempTablespaces (void)
 
Oid get_tablespace_oid (const char *tablespacename, bool missing_ok)
 
char * get_tablespace_name (Oid spc_oid)
 
bool directory_is_empty (const char *path)
 
void remove_tablespace_symlink (const char *linkloc)
 
void tblspc_redo (XLogReaderState *rptr)
 
void tblspc_desc (StringInfo buf, XLogReaderState *rptr)
 
const char * tblspc_identify (uint8 info)
 

Macro Definition Documentation

◆ XLOG_TBLSPC_CREATE

#define XLOG_TBLSPC_CREATE   0x00

Definition at line 23 of file tablespace.h.

◆ XLOG_TBLSPC_DROP

#define XLOG_TBLSPC_DROP   0x10

Definition at line 24 of file tablespace.h.

Typedef Documentation

◆ TableSpaceOpts

◆ xl_tblspc_create_rec

◆ xl_tblspc_drop_rec

Function Documentation

◆ AlterTableSpaceOptions()

Oid AlterTableSpaceOptions ( AlterTableSpaceOptionsStmt stmt)

Definition at line 1016 of file tablespace.c.

1017 {
1018  Relation rel;
1019  ScanKeyData entry[1];
1020  TableScanDesc scandesc;
1021  HeapTuple tup;
1022  Oid tablespaceoid;
1023  Datum datum;
1024  Datum newOptions;
1025  Datum repl_val[Natts_pg_tablespace];
1026  bool isnull;
1027  bool repl_null[Natts_pg_tablespace];
1028  bool repl_repl[Natts_pg_tablespace];
1029  HeapTuple newtuple;
1030 
1031  /* Search pg_tablespace */
1032  rel = table_open(TableSpaceRelationId, RowExclusiveLock);
1033 
1034  ScanKeyInit(&entry[0],
1035  Anum_pg_tablespace_spcname,
1036  BTEqualStrategyNumber, F_NAMEEQ,
1038  scandesc = table_beginscan_catalog(rel, 1, entry);
1039  tup = heap_getnext(scandesc, ForwardScanDirection);
1040  if (!HeapTupleIsValid(tup))
1041  ereport(ERROR,
1042  (errcode(ERRCODE_UNDEFINED_OBJECT),
1043  errmsg("tablespace \"%s\" does not exist",
1044  stmt->tablespacename)));
1045 
1046  tablespaceoid = ((Form_pg_tablespace) GETSTRUCT(tup))->oid;
1047 
1048  /* Must be owner of the existing object */
1049  if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId()))
1051  stmt->tablespacename);
1052 
1053  /* Generate new proposed spcoptions (text array) */
1054  datum = heap_getattr(tup, Anum_pg_tablespace_spcoptions,
1055  RelationGetDescr(rel), &isnull);
1056  newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
1057  stmt->options, NULL, NULL, false,
1058  stmt->isReset);
1059  (void) tablespace_reloptions(newOptions, true);
1060 
1061  /* Build new tuple. */
1062  memset(repl_null, false, sizeof(repl_null));
1063  memset(repl_repl, false, sizeof(repl_repl));
1064  if (newOptions != (Datum) 0)
1065  repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions;
1066  else
1067  repl_null[Anum_pg_tablespace_spcoptions - 1] = true;
1068  repl_repl[Anum_pg_tablespace_spcoptions - 1] = true;
1069  newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val,
1070  repl_null, repl_repl);
1071 
1072  /* Update system catalog. */
1073  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
1074 
1075  InvokeObjectPostAlterHook(TableSpaceRelationId, tablespaceoid, 0);
1076 
1077  heap_freetuple(newtuple);
1078 
1079  /* Conclude heap scan. */
1080  table_endscan(scandesc);
1081  table_close(rel, NoLock);
1082 
1083  return tablespaceoid;
1084 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:181
bool pg_tablespace_ownercheck(Oid spc_oid, Oid roleid)
Definition: aclchk.c:5022
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
int errcode(int sqlerrcode)
Definition: elog.c:698
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1340
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:756
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid GetUserId(void)
Definition: miscinit.c:495
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
@ OBJECT_TABLESPACE
Definition: parsenodes.h:1829
FormData_pg_tablespace * Form_pg_tablespace
Definition: pg_tablespace.h:48
#define CStringGetDatum(X)
Definition: postgres.h:622
uintptr_t Datum
Definition: postgres.h:411
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:503
bytea * tablespace_reloptions(Datum reloptions, bool validate)
Definition: reloptions.c:2080
Datum transformRelOptions(Datum oldOptions, List *defList, const char *namspace, char *validnsps[], bool acceptOidsOff, bool isReset)
Definition: reloptions.c:1149
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
@ ForwardScanDirection
Definition: sdir.h:26
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:993

References aclcheck_error(), ACLCHECK_NOT_OWNER, BTEqualStrategyNumber, CatalogTupleUpdate(), CStringGetDatum, ereport, errcode(), errmsg(), ERROR, ForwardScanDirection, GETSTRUCT, GetUserId(), heap_freetuple(), heap_getattr, heap_getnext(), heap_modify_tuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, AlterTableSpaceOptionsStmt::isReset, NoLock, OBJECT_TABLESPACE, AlterTableSpaceOptionsStmt::options, pg_tablespace_ownercheck(), RelationGetDescr, RowExclusiveLock, ScanKeyInit(), HeapTupleData::t_self, table_beginscan_catalog(), table_close(), table_endscan(), table_open(), tablespace_reloptions(), AlterTableSpaceOptionsStmt::tablespacename, and transformRelOptions().

Referenced by standard_ProcessUtility().

◆ CreateTableSpace()

Oid CreateTableSpace ( CreateTableSpaceStmt stmt)

Definition at line 233 of file tablespace.c.

234 {
235 #ifdef HAVE_SYMLINK
236  Relation rel;
237  Datum values[Natts_pg_tablespace];
238  bool nulls[Natts_pg_tablespace];
239  HeapTuple tuple;
240  Oid tablespaceoid;
241  char *location;
242  Oid ownerId;
243  Datum newOptions;
244 
245  /* Must be superuser */
246  if (!superuser())
247  ereport(ERROR,
248  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
249  errmsg("permission denied to create tablespace \"%s\"",
250  stmt->tablespacename),
251  errhint("Must be superuser to create a tablespace.")));
252 
253  /* However, the eventual owner of the tablespace need not be */
254  if (stmt->owner)
255  ownerId = get_rolespec_oid(stmt->owner, false);
256  else
257  ownerId = GetUserId();
258 
259  /* Unix-ify the offered path, and strip any trailing slashes */
260  location = pstrdup(stmt->location);
261  canonicalize_path(location);
262 
263  /* disallow quotes, else CREATE DATABASE would be at risk */
264  if (strchr(location, '\''))
265  ereport(ERROR,
266  (errcode(ERRCODE_INVALID_NAME),
267  errmsg("tablespace location cannot contain single quotes")));
268 
269  /*
270  * Allowing relative paths seems risky
271  *
272  * this also helps us ensure that location is not empty or whitespace
273  */
274  if (!is_absolute_path(location))
275  ereport(ERROR,
276  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
277  errmsg("tablespace location must be an absolute path")));
278 
279  /*
280  * Check that location isn't too long. Remember that we're going to append
281  * 'PG_XXX/<dboid>/<relid>_<fork>.<nnn>'. FYI, we never actually
282  * reference the whole path here, but MakePGDirectory() uses the first two
283  * parts.
284  */
285  if (strlen(location) + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) + 1 +
286  OIDCHARS + 1 + OIDCHARS + 1 + FORKNAMECHARS + 1 + OIDCHARS > MAXPGPATH)
287  ereport(ERROR,
288  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
289  errmsg("tablespace location \"%s\" is too long",
290  location)));
291 
292  /* Warn if the tablespace is in the data directory. */
293  if (path_is_prefix_of_path(DataDir, location))
295  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
296  errmsg("tablespace location should not be inside the data directory")));
297 
298  /*
299  * Disallow creation of tablespaces named "pg_xxx"; we reserve this
300  * namespace for system purposes.
301  */
303  ereport(ERROR,
304  (errcode(ERRCODE_RESERVED_NAME),
305  errmsg("unacceptable tablespace name \"%s\"",
306  stmt->tablespacename),
307  errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
308 
309  /*
310  * If built with appropriate switch, whine when regression-testing
311  * conventions for tablespace names are violated.
312  */
313 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
314  if (strncmp(stmt->tablespacename, "regress_", 8) != 0)
315  elog(WARNING, "tablespaces created by regression test cases should have names starting with \"regress_\"");
316 #endif
317 
318  /*
319  * Check that there is no other tablespace by this name. (The unique
320  * index would catch this anyway, but might as well give a friendlier
321  * message.)
322  */
323  if (OidIsValid(get_tablespace_oid(stmt->tablespacename, true)))
324  ereport(ERROR,
326  errmsg("tablespace \"%s\" already exists",
327  stmt->tablespacename)));
328 
329  /*
330  * Insert tuple into pg_tablespace. The purpose of doing this first is to
331  * lock the proposed tablename against other would-be creators. The
332  * insertion will roll back if we find problems below.
333  */
334  rel = table_open(TableSpaceRelationId, RowExclusiveLock);
335 
336  MemSet(nulls, false, sizeof(nulls));
337 
338  tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId,
339  Anum_pg_tablespace_oid);
340  values[Anum_pg_tablespace_oid - 1] = ObjectIdGetDatum(tablespaceoid);
341  values[Anum_pg_tablespace_spcname - 1] =
343  values[Anum_pg_tablespace_spcowner - 1] =
344  ObjectIdGetDatum(ownerId);
345  nulls[Anum_pg_tablespace_spcacl - 1] = true;
346 
347  /* Generate new proposed spcoptions (text array) */
348  newOptions = transformRelOptions((Datum) 0,
349  stmt->options,
350  NULL, NULL, false, false);
351  (void) tablespace_reloptions(newOptions, true);
352  if (newOptions != (Datum) 0)
353  values[Anum_pg_tablespace_spcoptions - 1] = newOptions;
354  else
355  nulls[Anum_pg_tablespace_spcoptions - 1] = true;
356 
357  tuple = heap_form_tuple(rel->rd_att, values, nulls);
358 
359  CatalogTupleInsert(rel, tuple);
360 
361  heap_freetuple(tuple);
362 
363  /* Record dependency on owner */
364  recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId);
365 
366  /* Post creation hook for new tablespace */
367  InvokeObjectPostCreateHook(TableSpaceRelationId, tablespaceoid, 0);
368 
369  create_tablespace_directories(location, tablespaceoid);
370 
371  /* Record the filesystem change in XLOG */
372  {
373  xl_tblspc_create_rec xlrec;
374 
375  xlrec.ts_id = tablespaceoid;
376 
377  XLogBeginInsert();
378  XLogRegisterData((char *) &xlrec,
379  offsetof(xl_tblspc_create_rec, ts_path));
380  XLogRegisterData((char *) location, strlen(location) + 1);
381 
382  (void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_CREATE);
383  }
384 
385  /*
386  * Force synchronous commit, to minimize the window between creating the
387  * symlink on-disk and marking the transaction committed. It's not great
388  * that there is any window at all, but definitely we don't want to make
389  * it larger than necessary.
390  */
391  ForceSyncCommit();
392 
393  pfree(location);
394 
395  /* We keep the lock on pg_tablespace until commit */
396  table_close(rel, NoLock);
397 
398  return tablespaceoid;
399 #else /* !HAVE_SYMLINK */
400  ereport(ERROR,
401  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
402  errmsg("tablespaces are not supported on this platform")));
403  return InvalidOid; /* keep compiler quiet */
404 #endif /* HAVE_SYMLINK */
405 }
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5128
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1427
static void create_tablespace_directories(const char *location, const Oid tablespaceoid)
Definition: tablespace.c:588
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define offsetof(type, field)
Definition: c.h:727
#define MemSet(start, val, len)
Definition: c.h:1008
#define OidIsValid(objectId)
Definition: c.h:710
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
bool IsReservedName(const char *name)
Definition: catalog.c:218
int errdetail(const char *fmt,...)
Definition: elog.c:1042
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define WARNING
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:218
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:631
bool allowSystemTableMods
Definition: globals.c:123
char * DataDir
Definition: globals.c:65
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
char * pstrdup(const char *in)
Definition: mcxt.c:1299
void pfree(void *pointer)
Definition: mcxt.c:1169
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define MAXPGPATH
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:163
#define is_absolute_path(filename)
Definition: port.h:91
bool path_is_prefix_of_path(const char *path1, const char *path2)
Definition: path.c:438
void canonicalize_path(char *path)
Definition: path.c:254
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define InvalidOid
Definition: postgres_ext.h:36
#define OIDCHARS
Definition: relpath.h:30
#define FORKNAMECHARS
Definition: relpath.h:57
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
TupleDesc rd_att
Definition: rel.h:110
bool superuser(void)
Definition: superuser.c:46
#define XLOG_TBLSPC_CREATE
Definition: tablespace.h:23
void ForceSyncCommit(void)
Definition: xact.c:1122
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:429
void XLogBeginInsert(void)
Definition: xloginsert.c:136
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:337

References allowSystemTableMods, canonicalize_path(), CatalogTupleInsert(), create_tablespace_directories(), CStringGetDatum, DataDir, DirectFunctionCall1, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errhint(), errmsg(), ERROR, ForceSyncCommit(), FORKNAMECHARS, get_rolespec_oid(), get_tablespace_oid(), GetNewOidWithIndex(), GetUserId(), heap_form_tuple(), heap_freetuple(), InvalidOid, InvokeObjectPostCreateHook, is_absolute_path, IsReservedName(), CreateTableSpaceStmt::location, MAXPGPATH, MemSet, namein(), NoLock, ObjectIdGetDatum, offsetof, OIDCHARS, OidIsValid, CreateTableSpaceStmt::options, CreateTableSpaceStmt::owner, path_is_prefix_of_path(), pfree(), pstrdup(), RelationData::rd_att, recordDependencyOnOwner(), RowExclusiveLock, superuser(), table_close(), table_open(), tablespace_reloptions(), TABLESPACE_VERSION_DIRECTORY, CreateTableSpaceStmt::tablespacename, transformRelOptions(), xl_tblspc_create_rec::ts_id, values, WARNING, XLOG_TBLSPC_CREATE, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by standard_ProcessUtility().

◆ directory_is_empty()

bool directory_is_empty ( const char *  path)

Definition at line 852 of file tablespace.c.

853 {
854  DIR *dirdesc;
855  struct dirent *de;
856 
857  dirdesc = AllocateDir(path);
858 
859  while ((de = ReadDir(dirdesc, path)) != NULL)
860  {
861  if (strcmp(de->d_name, ".") == 0 ||
862  strcmp(de->d_name, "..") == 0)
863  continue;
864  FreeDir(dirdesc);
865  return false;
866  }
867 
868  FreeDir(dirdesc);
869  return true;
870 }
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2787
int FreeDir(DIR *dir)
Definition: fd.c:2839
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2721
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15

References AllocateDir(), dirent::d_name, FreeDir(), and ReadDir().

Referenced by createdb(), destroy_tablespace_directories(), and pg_tablespace_databases().

◆ DropTableSpace()

void DropTableSpace ( DropTableSpaceStmt stmt)

Definition at line 413 of file tablespace.c.

414 {
415 #ifdef HAVE_SYMLINK
416  char *tablespacename = stmt->tablespacename;
417  TableScanDesc scandesc;
418  Relation rel;
419  HeapTuple tuple;
420  Form_pg_tablespace spcform;
421  ScanKeyData entry[1];
422  Oid tablespaceoid;
423  char *detail;
424  char *detail_log;
425 
426  /*
427  * Find the target tuple
428  */
429  rel = table_open(TableSpaceRelationId, RowExclusiveLock);
430 
431  ScanKeyInit(&entry[0],
432  Anum_pg_tablespace_spcname,
433  BTEqualStrategyNumber, F_NAMEEQ,
434  CStringGetDatum(tablespacename));
435  scandesc = table_beginscan_catalog(rel, 1, entry);
436  tuple = heap_getnext(scandesc, ForwardScanDirection);
437 
438  if (!HeapTupleIsValid(tuple))
439  {
440  if (!stmt->missing_ok)
441  {
442  ereport(ERROR,
443  (errcode(ERRCODE_UNDEFINED_OBJECT),
444  errmsg("tablespace \"%s\" does not exist",
445  tablespacename)));
446  }
447  else
448  {
449  ereport(NOTICE,
450  (errmsg("tablespace \"%s\" does not exist, skipping",
451  tablespacename)));
452  table_endscan(scandesc);
453  table_close(rel, NoLock);
454  }
455  return;
456  }
457 
458  spcform = (Form_pg_tablespace) GETSTRUCT(tuple);
459  tablespaceoid = spcform->oid;
460 
461  /* Must be tablespace owner */
462  if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId()))
464  tablespacename);
465 
466  /* Disallow drop of the standard tablespaces, even by superuser */
467  if (IsPinnedObject(TableSpaceRelationId, tablespaceoid))
469  tablespacename);
470 
471  /* Check for pg_shdepend entries depending on this tablespace */
472  if (checkSharedDependencies(TableSpaceRelationId, tablespaceoid,
473  &detail, &detail_log))
474  ereport(ERROR,
475  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
476  errmsg("tablespace \"%s\" cannot be dropped because some objects depend on it",
477  tablespacename),
478  errdetail_internal("%s", detail),
479  errdetail_log("%s", detail_log)));
480 
481  /* DROP hook for the tablespace being removed */
482  InvokeObjectDropHook(TableSpaceRelationId, tablespaceoid, 0);
483 
484  /*
485  * Remove the pg_tablespace tuple (this will roll back if we fail below)
486  */
487  CatalogTupleDelete(rel, &tuple->t_self);
488 
489  table_endscan(scandesc);
490 
491  /*
492  * Remove any comments or security labels on this tablespace.
493  */
494  DeleteSharedComments(tablespaceoid, TableSpaceRelationId);
495  DeleteSharedSecurityLabel(tablespaceoid, TableSpaceRelationId);
496 
497  /*
498  * Remove dependency on owner.
499  */
500  deleteSharedDependencyRecordsFor(TableSpaceRelationId, tablespaceoid, 0);
501 
502  /*
503  * Acquire TablespaceCreateLock to ensure that no TablespaceCreateDbspace
504  * is running concurrently.
505  */
506  LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
507 
508  /*
509  * Try to remove the physical infrastructure.
510  */
511  if (!destroy_tablespace_directories(tablespaceoid, false))
512  {
513  /*
514  * Not all files deleted? However, there can be lingering empty files
515  * in the directories, left behind by for example DROP TABLE, that
516  * have been scheduled for deletion at next checkpoint (see comments
517  * in mdunlink() for details). We could just delete them immediately,
518  * but we can't tell them apart from important data files that we
519  * mustn't delete. So instead, we force a checkpoint which will clean
520  * out any lingering files, and try again.
521  *
522  * XXX On Windows, an unlinked file persists in the directory listing
523  * until no process retains an open handle for the file. The DDL
524  * commands that schedule files for unlink send invalidation messages
525  * directing other PostgreSQL processes to close the files. DROP
526  * TABLESPACE should not give up on the tablespace becoming empty
527  * until all relevant invalidation processing is complete.
528  */
530  if (!destroy_tablespace_directories(tablespaceoid, false))
531  {
532  /* Still not empty, the files must be important then */
533  ereport(ERROR,
534  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
535  errmsg("tablespace \"%s\" is not empty",
536  tablespacename)));
537  }
538  }
539 
540  /* Record the filesystem change in XLOG */
541  {
542  xl_tblspc_drop_rec xlrec;
543 
544  xlrec.ts_id = tablespaceoid;
545 
546  XLogBeginInsert();
547  XLogRegisterData((char *) &xlrec, sizeof(xl_tblspc_drop_rec));
548 
549  (void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_DROP);
550  }
551 
552  /*
553  * Note: because we checked that the tablespace was empty, there should be
554  * no need to worry about flushing shared buffers or free space map
555  * entries for relations in the tablespace.
556  */
557 
558  /*
559  * Force synchronous commit, to minimize the window between removing the
560  * files on-disk and marking the transaction committed. It's not great
561  * that there is any window at all, but definitely we don't want to make
562  * it larger than necessary.
563  */
564  ForceSyncCommit();
565 
566  /*
567  * Allow TablespaceCreateDbspace again.
568  */
569  LWLockRelease(TablespaceCreateLock);
570 
571  /* We keep the lock on pg_tablespace until commit */
572  table_close(rel, NoLock);
573 #else /* !HAVE_SYMLINK */
574  ereport(ERROR,
575  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
576  errmsg("tablespaces are not supported on this platform")));
577 #endif /* HAVE_SYMLINK */
578 }
@ ACLCHECK_NO_PRIV
Definition: acl.h:180
static bool destroy_tablespace_directories(Oid tablespaceoid, bool redo)
Definition: tablespace.c:682
bool IsPinnedObject(Oid classId, Oid objectId)
Definition: catalog.c:307
void RequestCheckpoint(int flags)
Definition: checkpointer.c:920
void DeleteSharedComments(Oid oid, Oid classoid)
Definition: comment.c:374
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1069
int errdetail_log(const char *fmt,...)
Definition: elog.c:1090
#define NOTICE
Definition: elog.h:29
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
@ LW_EXCLUSIVE
Definition: lwlock.h:104
#define InvokeObjectDropHook(classId, objectId, subId)
Definition: objectaccess.h:160
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1000
bool checkSharedDependencies(Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
Definition: pg_shdepend.c:629
void DeleteSharedSecurityLabel(Oid objectId, Oid classId)
Definition: seclabel.c:490
#define XLOG_TBLSPC_DROP
Definition: tablespace.h:24
#define CHECKPOINT_FORCE
Definition: xlog.h:197
#define CHECKPOINT_WAIT
Definition: xlog.h:200
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:196

References aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_NOT_OWNER, BTEqualStrategyNumber, CatalogTupleDelete(), CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, checkSharedDependencies(), CStringGetDatum, DeleteSharedComments(), deleteSharedDependencyRecordsFor(), DeleteSharedSecurityLabel(), destroy_tablespace_directories(), ereport, errcode(), errdetail_internal(), errdetail_log(), errmsg(), ERROR, ForceSyncCommit(), ForwardScanDirection, GETSTRUCT, GetUserId(), heap_getnext(), HeapTupleIsValid, InvokeObjectDropHook, IsPinnedObject(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), DropTableSpaceStmt::missing_ok, NoLock, NOTICE, OBJECT_TABLESPACE, pg_tablespace_ownercheck(), RequestCheckpoint(), RowExclusiveLock, ScanKeyInit(), HeapTupleData::t_self, table_beginscan_catalog(), table_close(), table_endscan(), table_open(), DropTableSpaceStmt::tablespacename, xl_tblspc_drop_rec::ts_id, XLOG_TBLSPC_DROP, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by standard_ProcessUtility().

◆ get_tablespace_name()

char* get_tablespace_name ( Oid  spc_oid)

Definition at line 1473 of file tablespace.c.

1474 {
1475  char *result;
1476  Relation rel;
1477  TableScanDesc scandesc;
1478  HeapTuple tuple;
1479  ScanKeyData entry[1];
1480 
1481  /*
1482  * Search pg_tablespace. We use a heapscan here even though there is an
1483  * index on oid, on the theory that pg_tablespace will usually have just a
1484  * few entries and so an indexed lookup is a waste of effort.
1485  */
1486  rel = table_open(TableSpaceRelationId, AccessShareLock);
1487 
1488  ScanKeyInit(&entry[0],
1489  Anum_pg_tablespace_oid,
1490  BTEqualStrategyNumber, F_OIDEQ,
1491  ObjectIdGetDatum(spc_oid));
1492  scandesc = table_beginscan_catalog(rel, 1, entry);
1493  tuple = heap_getnext(scandesc, ForwardScanDirection);
1494 
1495  /* We assume that there can be at most one matching tuple */
1496  if (HeapTupleIsValid(tuple))
1497  result = pstrdup(NameStr(((Form_pg_tablespace) GETSTRUCT(tuple))->spcname));
1498  else
1499  result = NULL;
1500 
1501  table_endscan(scandesc);
1503 
1504  return result;
1505 }
#define NameStr(name)
Definition: c.h:681
#define AccessShareLock
Definition: lockdefs.h:36

References AccessShareLock, BTEqualStrategyNumber, ForwardScanDirection, GETSTRUCT, heap_getnext(), HeapTupleIsValid, NameStr, ObjectIdGetDatum, pstrdup(), ScanKeyInit(), table_beginscan_catalog(), table_close(), table_endscan(), and table_open().

Referenced by AlterTableMoveAll(), calculate_tablespace_size(), DefineIndex(), DefineRelation(), ExecReindex(), generateClonedIndexStmt(), getObjectDescription(), getObjectIdentityParts(), pg_get_constraintdef_worker(), pg_get_indexdef_worker(), ReindexMultipleInternal(), ReindexRelationConcurrently(), and shdepLockAndCheckObject().

◆ get_tablespace_oid()

Oid get_tablespace_oid ( const char *  tablespacename,
bool  missing_ok 
)

Definition at line 1427 of file tablespace.c.

1428 {
1429  Oid result;
1430  Relation rel;
1431  TableScanDesc scandesc;
1432  HeapTuple tuple;
1433  ScanKeyData entry[1];
1434 
1435  /*
1436  * Search pg_tablespace. We use a heapscan here even though there is an
1437  * index on name, on the theory that pg_tablespace will usually have just
1438  * a few entries and so an indexed lookup is a waste of effort.
1439  */
1440  rel = table_open(TableSpaceRelationId, AccessShareLock);
1441 
1442  ScanKeyInit(&entry[0],
1443  Anum_pg_tablespace_spcname,
1444  BTEqualStrategyNumber, F_NAMEEQ,
1445  CStringGetDatum(tablespacename));
1446  scandesc = table_beginscan_catalog(rel, 1, entry);
1447  tuple = heap_getnext(scandesc, ForwardScanDirection);
1448 
1449  /* We assume that there can be at most one matching tuple */
1450  if (HeapTupleIsValid(tuple))
1451  result = ((Form_pg_tablespace) GETSTRUCT(tuple))->oid;
1452  else
1453  result = InvalidOid;
1454 
1455  table_endscan(scandesc);
1457 
1458  if (!OidIsValid(result) && !missing_ok)
1459  ereport(ERROR,
1460  (errcode(ERRCODE_UNDEFINED_OBJECT),
1461  errmsg("tablespace \"%s\" does not exist",
1462  tablespacename)));
1463 
1464  return result;
1465 }

References AccessShareLock, BTEqualStrategyNumber, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, ForwardScanDirection, GETSTRUCT, heap_getnext(), HeapTupleIsValid, InvalidOid, OidIsValid, ScanKeyInit(), table_beginscan_catalog(), table_close(), table_endscan(), and table_open().

Referenced by AlterTableMoveAll(), ATPrepSetTableSpace(), check_default_tablespace(), check_temp_tablespaces(), convert_tablespace_name(), createdb(), CreateTableSpace(), DefineIndex(), DefineRelation(), ExecReindex(), get_object_address_unqualified(), GetDefaultTablespace(), movedb(), objectNamesToOids(), pg_tablespace_size_name(), and PrepareTempTablespaces().

◆ GetDefaultTablespace()

Oid GetDefaultTablespace ( char  relpersistence,
bool  partitioned 
)

Definition at line 1144 of file tablespace.c.

1145 {
1146  Oid result;
1147 
1148  /* The temp-table case is handled elsewhere */
1149  if (relpersistence == RELPERSISTENCE_TEMP)
1150  {
1152  return GetNextTempTableSpace();
1153  }
1154 
1155  /* Fast path for default_tablespace == "" */
1156  if (default_tablespace == NULL || default_tablespace[0] == '\0')
1157  return InvalidOid;
1158 
1159  /*
1160  * It is tempting to cache this lookup for more speed, but then we would
1161  * fail to detect the case where the tablespace was dropped since the GUC
1162  * variable was set. Note also that we don't complain if the value fails
1163  * to refer to an existing tablespace; we just silently return InvalidOid,
1164  * causing the new object to be created in the database's tablespace.
1165  */
1166  result = get_tablespace_oid(default_tablespace, true);
1167 
1168  /*
1169  * Allow explicit specification of database's default tablespace in
1170  * default_tablespace without triggering permissions checks. Don't allow
1171  * specifying that when creating a partitioned table, however, since the
1172  * result is confusing.
1173  */
1174  if (result == MyDatabaseTableSpace)
1175  {
1176  if (partitioned)
1177  ereport(ERROR,
1178  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1179  errmsg("cannot specify default tablespace for partitioned relations")));
1180  result = InvalidOid;
1181  }
1182  return result;
1183 }
void PrepareTempTablespaces(void)
Definition: tablespace.c:1332
char * default_tablespace
Definition: tablespace.c:88
Oid GetNextTempTableSpace(void)
Definition: fd.c:2988
Oid MyDatabaseTableSpace
Definition: globals.c:90

References default_tablespace, ereport, errcode(), errmsg(), ERROR, get_tablespace_oid(), GetNextTempTableSpace(), InvalidOid, MyDatabaseTableSpace, and PrepareTempTablespaces().

Referenced by DefineIndex(), DefineRelation(), and ExecRefreshMatView().

◆ PrepareTempTablespaces()

void PrepareTempTablespaces ( void  )

Definition at line 1332 of file tablespace.c.

1333 {
1334  char *rawname;
1335  List *namelist;
1336  Oid *tblSpcs;
1337  int numSpcs;
1338  ListCell *l;
1339 
1340  /* No work if already done in current transaction */
1341  if (TempTablespacesAreSet())
1342  return;
1343 
1344  /*
1345  * Can't do catalog access unless within a transaction. This is just a
1346  * safety check in case this function is called by low-level code that
1347  * could conceivably execute outside a transaction. Note that in such a
1348  * scenario, fd.c will fall back to using the current database's default
1349  * tablespace, which should always be OK.
1350  */
1351  if (!IsTransactionState())
1352  return;
1353 
1354  /* Need a modifiable copy of string */
1355  rawname = pstrdup(temp_tablespaces);
1356 
1357  /* Parse string into list of identifiers */
1358  if (!SplitIdentifierString(rawname, ',', &namelist))
1359  {
1360  /* syntax error in name list */
1361  SetTempTablespaces(NULL, 0);
1362  pfree(rawname);
1363  list_free(namelist);
1364  return;
1365  }
1366 
1367  /* Store tablespace OIDs in an array in TopTransactionContext */
1369  list_length(namelist) * sizeof(Oid));
1370  numSpcs = 0;
1371  foreach(l, namelist)
1372  {
1373  char *curname = (char *) lfirst(l);
1374  Oid curoid;
1375  AclResult aclresult;
1376 
1377  /* Allow an empty string (signifying database default) */
1378  if (curname[0] == '\0')
1379  {
1380  /* InvalidOid signifies database's default tablespace */
1381  tblSpcs[numSpcs++] = InvalidOid;
1382  continue;
1383  }
1384 
1385  /* Else verify that name is a valid tablespace name */
1386  curoid = get_tablespace_oid(curname, true);
1387  if (curoid == InvalidOid)
1388  {
1389  /* Skip any bad list elements */
1390  continue;
1391  }
1392 
1393  /*
1394  * Allow explicit specification of database's default tablespace in
1395  * temp_tablespaces without triggering permissions checks.
1396  */
1397  if (curoid == MyDatabaseTableSpace)
1398  {
1399  /* InvalidOid signifies database's default tablespace */
1400  tblSpcs[numSpcs++] = InvalidOid;
1401  continue;
1402  }
1403 
1404  /* Check permissions similarly */
1405  aclresult = pg_tablespace_aclcheck(curoid, GetUserId(),
1406  ACL_CREATE);
1407  if (aclresult != ACLCHECK_OK)
1408  continue;
1409 
1410  tblSpcs[numSpcs++] = curoid;
1411  }
1412 
1413  SetTempTablespaces(tblSpcs, numSpcs);
1414 
1415  pfree(rawname);
1416  list_free(namelist);
1417 }
AclResult
Definition: acl.h:178
@ ACLCHECK_OK
Definition: acl.h:179
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4770
char * temp_tablespaces
Definition: tablespace.c:89
bool TempTablespacesAreSet(void)
Definition: fd.c:2955
void SetTempTablespaces(Oid *tableSpaces, int numSpaces)
Definition: fd.c:2927
void list_free(List *list)
Definition: list.c:1505
MemoryContext TopTransactionContext
Definition: mcxt.c:53
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
#define ACL_CREATE
Definition: parsenodes.h:91
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
Definition: pg_list.h:51
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3746
bool IsTransactionState(void)
Definition: xact.c:372

References ACL_CREATE, ACLCHECK_OK, get_tablespace_oid(), GetUserId(), InvalidOid, IsTransactionState(), lfirst, list_free(), list_length(), MemoryContextAlloc(), MyDatabaseTableSpace, pfree(), pg_tablespace_aclcheck(), pstrdup(), SetTempTablespaces(), SplitIdentifierString(), temp_tablespaces, TempTablespacesAreSet(), and TopTransactionContext.

Referenced by BufFileCreateTemp(), ExecHashIncreaseNumBatches(), ExecHashTableCreate(), FileSetInit(), GetDefaultTablespace(), inittapestate(), and tuplestore_puttuple_common().

◆ remove_tablespace_symlink()

void remove_tablespace_symlink ( const char *  linkloc)

Definition at line 882 of file tablespace.c.

883 {
884  struct stat st;
885 
886  if (lstat(linkloc, &st) < 0)
887  {
888  if (errno == ENOENT)
889  return;
890  ereport(ERROR,
892  errmsg("could not stat file \"%s\": %m", linkloc)));
893  }
894 
895  if (S_ISDIR(st.st_mode))
896  {
897  /*
898  * This will fail if the directory isn't empty, but not if it's a
899  * junction point.
900  */
901  if (rmdir(linkloc) < 0 && errno != ENOENT)
902  ereport(ERROR,
904  errmsg("could not remove directory \"%s\": %m",
905  linkloc)));
906  }
907 #ifdef S_ISLNK
908  else if (S_ISLNK(st.st_mode))
909  {
910  if (unlink(linkloc) < 0 && errno != ENOENT)
911  ereport(ERROR,
913  errmsg("could not remove symbolic link \"%s\": %m",
914  linkloc)));
915  }
916 #endif
917  else
918  {
919  /* Refuse to remove anything that's not a directory or symlink */
920  ereport(ERROR,
921  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
922  errmsg("\"%s\" is not a directory or symbolic link",
923  linkloc)));
924  }
925 }
int errcode_for_file_access(void)
Definition: elog.c:721
#define lstat(path, sb)
Definition: win32_port.h:284
#define S_ISDIR(m)
Definition: win32_port.h:324

References ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, lstat, S_ISDIR, and stat::st_mode.

Referenced by create_tablespace_directories(), and StartupXLOG().

◆ RenameTableSpace()

ObjectAddress RenameTableSpace ( const char *  oldname,
const char *  newname 
)

Definition at line 931 of file tablespace.c.

932 {
933  Oid tspId;
934  Relation rel;
935  ScanKeyData entry[1];
936  TableScanDesc scan;
937  HeapTuple tup;
938  HeapTuple newtuple;
939  Form_pg_tablespace newform;
940  ObjectAddress address;
941 
942  /* Search pg_tablespace */
943  rel = table_open(TableSpaceRelationId, RowExclusiveLock);
944 
945  ScanKeyInit(&entry[0],
946  Anum_pg_tablespace_spcname,
947  BTEqualStrategyNumber, F_NAMEEQ,
948  CStringGetDatum(oldname));
949  scan = table_beginscan_catalog(rel, 1, entry);
950  tup = heap_getnext(scan, ForwardScanDirection);
951  if (!HeapTupleIsValid(tup))
952  ereport(ERROR,
953  (errcode(ERRCODE_UNDEFINED_OBJECT),
954  errmsg("tablespace \"%s\" does not exist",
955  oldname)));
956 
957  newtuple = heap_copytuple(tup);
958  newform = (Form_pg_tablespace) GETSTRUCT(newtuple);
959  tspId = newform->oid;
960 
961  table_endscan(scan);
962 
963  /* Must be owner */
964  if (!pg_tablespace_ownercheck(tspId, GetUserId()))
966 
967  /* Validate new name */
968  if (!allowSystemTableMods && IsReservedName(newname))
969  ereport(ERROR,
970  (errcode(ERRCODE_RESERVED_NAME),
971  errmsg("unacceptable tablespace name \"%s\"", newname),
972  errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
973 
974  /*
975  * If built with appropriate switch, whine when regression-testing
976  * conventions for tablespace names are violated.
977  */
978 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
979  if (strncmp(newname, "regress_", 8) != 0)
980  elog(WARNING, "tablespaces created by regression test cases should have names starting with \"regress_\"");
981 #endif
982 
983  /* Make sure the new name doesn't exist */
984  ScanKeyInit(&entry[0],
985  Anum_pg_tablespace_spcname,
986  BTEqualStrategyNumber, F_NAMEEQ,
987  CStringGetDatum(newname));
988  scan = table_beginscan_catalog(rel, 1, entry);
989  tup = heap_getnext(scan, ForwardScanDirection);
990  if (HeapTupleIsValid(tup))
991  ereport(ERROR,
993  errmsg("tablespace \"%s\" already exists",
994  newname)));
995 
996  table_endscan(scan);
997 
998  /* OK, update the entry */
999  namestrcpy(&(newform->spcname), newname);
1000 
1001  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
1002 
1003  InvokeObjectPostAlterHook(TableSpaceRelationId, tspId, 0);
1004 
1005  ObjectAddressSet(address, TableSpaceRelationId, tspId);
1006 
1007  table_close(rel, NoLock);
1008 
1009  return address;
1010 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40

References aclcheck_error(), ACLCHECK_NO_PRIV, allowSystemTableMods, BTEqualStrategyNumber, CatalogTupleUpdate(), CStringGetDatum, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errmsg(), ERROR, ForwardScanDirection, GETSTRUCT, GetUserId(), heap_copytuple(), heap_getnext(), HeapTupleIsValid, InvokeObjectPostAlterHook, IsReservedName(), namestrcpy(), NoLock, OBJECT_TABLESPACE, ObjectAddressSet, pg_tablespace_ownercheck(), RowExclusiveLock, ScanKeyInit(), HeapTupleData::t_self, table_beginscan_catalog(), table_close(), table_endscan(), table_open(), and WARNING.

Referenced by ExecRenameStmt().

◆ TablespaceCreateDbspace()

void TablespaceCreateDbspace ( Oid  spcNode,
Oid  dbNode,
bool  isRedo 
)

Definition at line 115 of file tablespace.c.

116 {
117  struct stat st;
118  char *dir;
119 
120  /*
121  * The global tablespace doesn't have per-database subdirectories, so
122  * nothing to do for it.
123  */
124  if (spcNode == GLOBALTABLESPACE_OID)
125  return;
126 
127  Assert(OidIsValid(spcNode));
128  Assert(OidIsValid(dbNode));
129 
130  dir = GetDatabasePath(dbNode, spcNode);
131 
132  if (stat(dir, &st) < 0)
133  {
134  /* Directory does not exist? */
135  if (errno == ENOENT)
136  {
137  /*
138  * Acquire TablespaceCreateLock to ensure that no DROP TABLESPACE
139  * or TablespaceCreateDbspace is running concurrently.
140  */
141  LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
142 
143  /*
144  * Recheck to see if someone created the directory while we were
145  * waiting for lock.
146  */
147  if (stat(dir, &st) == 0 && S_ISDIR(st.st_mode))
148  {
149  /* Directory was created */
150  }
151  else
152  {
153  /* Directory creation failed? */
154  if (MakePGDirectory(dir) < 0)
155  {
156  char *parentdir;
157 
158  /* Failure other than not exists or not in WAL replay? */
159  if (errno != ENOENT || !isRedo)
160  ereport(ERROR,
162  errmsg("could not create directory \"%s\": %m",
163  dir)));
164 
165  /*
166  * Parent directories are missing during WAL replay, so
167  * continue by creating simple parent directories rather
168  * than a symlink.
169  */
170 
171  /* create two parents up if not exist */
172  parentdir = pstrdup(dir);
173  get_parent_directory(parentdir);
174  get_parent_directory(parentdir);
175  /* Can't create parent and it doesn't already exist? */
176  if (MakePGDirectory(parentdir) < 0 && errno != EEXIST)
177  ereport(ERROR,
179  errmsg("could not create directory \"%s\": %m",
180  parentdir)));
181  pfree(parentdir);
182 
183  /* create one parent up if not exist */
184  parentdir = pstrdup(dir);
185  get_parent_directory(parentdir);
186  /* Can't create parent and it doesn't already exist? */
187  if (MakePGDirectory(parentdir) < 0 && errno != EEXIST)
188  ereport(ERROR,
190  errmsg("could not create directory \"%s\": %m",
191  parentdir)));
192  pfree(parentdir);
193 
194  /* Create database directory */
195  if (MakePGDirectory(dir) < 0)
196  ereport(ERROR,
198  errmsg("could not create directory \"%s\": %m",
199  dir)));
200  }
201  }
202 
203  LWLockRelease(TablespaceCreateLock);
204  }
205  else
206  {
207  ereport(ERROR,
209  errmsg("could not stat directory \"%s\": %m", dir)));
210  }
211  }
212  else
213  {
214  /* Is it not a directory? */
215  if (!S_ISDIR(st.st_mode))
216  ereport(ERROR,
217  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
218  errmsg("\"%s\" exists but is not a directory",
219  dir)));
220  }
221 
222  pfree(dir);
223 }
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3801
Assert(fmt[strlen(fmt) - 1] !='\n')
void get_parent_directory(char *path)
Definition: path.c:854
char * GetDatabasePath(Oid dbNode, Oid spcNode)
Definition: relpath.c:110
#define stat
Definition: win32_port.h:283

References Assert(), ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, get_parent_directory(), GetDatabasePath(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MakePGDirectory(), OidIsValid, pfree(), pstrdup(), S_ISDIR, stat::st_mode, and stat.

Referenced by mdcreate().

◆ tblspc_desc()

void tblspc_desc ( StringInfo  buf,
XLogReaderState rptr 
)

Definition at line 21 of file tblspcdesc.c.

22 {
23  char *rec = XLogRecGetData(record);
24  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
25 
26  if (info == XLOG_TBLSPC_CREATE)
27  {
29 
30  appendStringInfo(buf, "%u \"%s\"", xlrec->ts_id, xlrec->ts_path);
31  }
32  else if (info == XLOG_TBLSPC_DROP)
33  {
34  xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) rec;
35 
36  appendStringInfo(buf, "%u", xlrec->ts_id);
37  }
38 }
unsigned char uint8
Definition: c.h:439
static char * buf
Definition: pg_test_fsync.c:69
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
char ts_path[FLEXIBLE_ARRAY_MEMBER]
Definition: tablespace.h:29
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:315
#define XLogRecGetData(decoder)
Definition: xlogreader.h:320
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

References appendStringInfo(), buf, xl_tblspc_create_rec::ts_id, xl_tblspc_drop_rec::ts_id, xl_tblspc_create_rec::ts_path, XLOG_TBLSPC_CREATE, XLOG_TBLSPC_DROP, XLogRecGetData, XLogRecGetInfo, and XLR_INFO_MASK.

◆ tblspc_identify()

const char* tblspc_identify ( uint8  info)

Definition at line 41 of file tblspcdesc.c.

42 {
43  const char *id = NULL;
44 
45  switch (info & ~XLR_INFO_MASK)
46  {
47  case XLOG_TBLSPC_CREATE:
48  id = "CREATE";
49  break;
50  case XLOG_TBLSPC_DROP:
51  id = "DROP";
52  break;
53  }
54 
55  return id;
56 }

References XLOG_TBLSPC_CREATE, XLOG_TBLSPC_DROP, and XLR_INFO_MASK.

◆ tblspc_redo()

void tblspc_redo ( XLogReaderState rptr)

Definition at line 1512 of file tablespace.c.

1513 {
1514  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1515 
1516  /* Backup blocks are not used in tblspc records */
1517  Assert(!XLogRecHasAnyBlockRefs(record));
1518 
1519  if (info == XLOG_TBLSPC_CREATE)
1520  {
1522  char *location = xlrec->ts_path;
1523 
1524  create_tablespace_directories(location, xlrec->ts_id);
1525  }
1526  else if (info == XLOG_TBLSPC_DROP)
1527  {
1529 
1530  /*
1531  * If we issued a WAL record for a drop tablespace it implies that
1532  * there were no files in it at all when the DROP was done. That means
1533  * that no permanent objects can exist in it at this point.
1534  *
1535  * It is possible for standby users to be using this tablespace as a
1536  * location for their temporary files, so if we fail to remove all
1537  * files then do conflict processing and try again, if currently
1538  * enabled.
1539  *
1540  * Other possible reasons for failure include bollixed file
1541  * permissions on a standby server when they were okay on the primary,
1542  * etc etc. There's not much we can do about that, so just remove what
1543  * we can and press on.
1544  */
1545  if (!destroy_tablespace_directories(xlrec->ts_id, true))
1546  {
1548 
1549  /*
1550  * If we did recovery processing then hopefully the backends who
1551  * wrote temp files should have cleaned up and exited by now. So
1552  * retry before complaining. If we fail again, this is just a LOG
1553  * condition, because it's not worth throwing an ERROR for (as
1554  * that would crash the database and require manual intervention
1555  * before we could get past this WAL record on restart).
1556  */
1557  if (!destroy_tablespace_directories(xlrec->ts_id, true))
1558  ereport(LOG,
1559  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1560  errmsg("directories for tablespace %u could not be removed",
1561  xlrec->ts_id),
1562  errhint("You can remove the directories manually if necessary.")));
1563  }
1564  }
1565  else
1566  elog(PANIC, "tblspc_redo: unknown op code %u", info);
1567 }
#define LOG
Definition: elog.h:25
#define PANIC
Definition: elog.h:36
void ResolveRecoveryConflictWithTablespace(Oid tsid)
Definition: standby.c:499
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:322

References Assert(), create_tablespace_directories(), destroy_tablespace_directories(), elog, ereport, errcode(), errhint(), errmsg(), LOG, PANIC, ResolveRecoveryConflictWithTablespace(), xl_tblspc_create_rec::ts_id, xl_tblspc_drop_rec::ts_id, xl_tblspc_create_rec::ts_path, XLOG_TBLSPC_CREATE, XLOG_TBLSPC_DROP, XLogRecGetData, XLogRecGetInfo, XLogRecHasAnyBlockRefs, and XLR_INFO_MASK.