summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlog.c17
-rw-r--r--src/backend/postmaster/postmaster.c28
-rw-r--r--src/backend/storage/aio/method_worker.c62
-rw-r--r--src/backend/storage/ipc/procarray.c52
-rw-r--r--src/backend/utils/adt/acl.c33
-rw-r--r--src/backend/utils/adt/timestamp.c20
-rw-r--r--src/include/storage/procarray.h1
-rw-r--r--src/test/regress/expected/privileges.out20
-rw-r--r--src/test/regress/sql/privileges.sql8
-rw-r--r--src/tools/pgindent/typedefs.list6
10 files changed, 115 insertions, 132 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 88fb9b45b2a..8e7827c6ed9 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -449,7 +449,6 @@ typedef struct XLogCtlData
/* Protected by info_lck: */
XLogwrtRqst LogwrtRqst;
XLogRecPtr RedoRecPtr; /* a recent copy of Insert->RedoRecPtr */
- FullTransactionId ckptFullXid; /* nextXid of latest checkpoint */
XLogRecPtr asyncXactLSN; /* LSN of newest async commit/abort */
XLogRecPtr replicationSlotMinLSN; /* oldest LSN needed by any slot */
@@ -5744,7 +5743,6 @@ StartupXLOG(void)
SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
SetCommitTsLimit(checkPoint.oldestCommitTsXid,
checkPoint.newestCommitTsXid);
- XLogCtl->ckptFullXid = checkPoint.nextXid;
/*
* Clear out any old relcache cache files. This is *necessary* if we do
@@ -7437,11 +7435,6 @@ CreateCheckPoint(int flags)
UpdateControlFile();
LWLockRelease(ControlFileLock);
- /* Update shared-memory copy of checkpoint XID/epoch */
- SpinLockAcquire(&XLogCtl->info_lck);
- XLogCtl->ckptFullXid = checkPoint.nextXid;
- SpinLockRelease(&XLogCtl->info_lck);
-
/*
* We are now done with critical updates; no need for system panic if we
* have trouble while fooling with old log segments.
@@ -8516,11 +8509,6 @@ xlog_redo(XLogReaderState *record)
ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
LWLockRelease(ControlFileLock);
- /* Update shared-memory copy of checkpoint XID/epoch */
- SpinLockAcquire(&XLogCtl->info_lck);
- XLogCtl->ckptFullXid = checkPoint.nextXid;
- SpinLockRelease(&XLogCtl->info_lck);
-
/*
* We should've already switched to the new TLI before replaying this
* record.
@@ -8577,11 +8565,6 @@ xlog_redo(XLogReaderState *record)
ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
LWLockRelease(ControlFileLock);
- /* Update shared-memory copy of checkpoint XID/epoch */
- SpinLockAcquire(&XLogCtl->info_lck);
- XLogCtl->ckptFullXid = checkPoint.nextXid;
- SpinLockRelease(&XLogCtl->info_lck);
-
/* TLI should not change in an on-line checkpoint */
(void) GetCurrentReplayRecPtr(&replayTLI);
if (checkPoint.ThisTimeLineID != replayTLI)
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 490f7ce3664..cca9b946e53 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4337,15 +4337,15 @@ maybe_start_bgworkers(void)
static bool
maybe_reap_io_worker(int pid)
{
- for (int id = 0; id < MAX_IO_WORKERS; ++id)
+ for (int i = 0; i < MAX_IO_WORKERS; ++i)
{
- if (io_worker_children[id] &&
- io_worker_children[id]->pid == pid)
+ if (io_worker_children[i] &&
+ io_worker_children[i]->pid == pid)
{
- ReleasePostmasterChildSlot(io_worker_children[id]);
+ ReleasePostmasterChildSlot(io_worker_children[i]);
--io_worker_count;
- io_worker_children[id] = NULL;
+ io_worker_children[i] = NULL;
return true;
}
}
@@ -4389,22 +4389,22 @@ maybe_adjust_io_workers(void)
while (io_worker_count < io_workers)
{
PMChild *child;
- int id;
+ int i;
/* find unused entry in io_worker_children array */
- for (id = 0; id < MAX_IO_WORKERS; ++id)
+ for (i = 0; i < MAX_IO_WORKERS; ++i)
{
- if (io_worker_children[id] == NULL)
+ if (io_worker_children[i] == NULL)
break;
}
- if (id == MAX_IO_WORKERS)
- elog(ERROR, "could not find a free IO worker ID");
+ if (i == MAX_IO_WORKERS)
+ elog(ERROR, "could not find a free IO worker slot");
/* Try to launch one. */
child = StartChildProcess(B_IO_WORKER);
if (child != NULL)
{
- io_worker_children[id] = child;
+ io_worker_children[i] = child;
++io_worker_count;
}
else
@@ -4415,11 +4415,11 @@ maybe_adjust_io_workers(void)
if (io_worker_count > io_workers)
{
/* ask the IO worker in the highest slot to exit */
- for (int id = MAX_IO_WORKERS - 1; id >= 0; --id)
+ for (int i = MAX_IO_WORKERS - 1; i >= 0; --i)
{
- if (io_worker_children[id] != NULL)
+ if (io_worker_children[i] != NULL)
{
- kill(io_worker_children[id]->pid, SIGUSR2);
+ kill(io_worker_children[i]->pid, SIGUSR2);
break;
}
}
diff --git a/src/backend/storage/aio/method_worker.c b/src/backend/storage/aio/method_worker.c
index 36be179678d..bf8f77e6ff6 100644
--- a/src/backend/storage/aio/method_worker.c
+++ b/src/backend/storage/aio/method_worker.c
@@ -52,26 +52,26 @@
#define IO_WORKER_WAKEUP_FANOUT 2
-typedef struct AioWorkerSubmissionQueue
+typedef struct PgAioWorkerSubmissionQueue
{
uint32 size;
uint32 mask;
uint32 head;
uint32 tail;
- uint32 ios[FLEXIBLE_ARRAY_MEMBER];
-} AioWorkerSubmissionQueue;
+ uint32 sqes[FLEXIBLE_ARRAY_MEMBER];
+} PgAioWorkerSubmissionQueue;
-typedef struct AioWorkerSlot
+typedef struct PgAioWorkerSlot
{
Latch *latch;
bool in_use;
-} AioWorkerSlot;
+} PgAioWorkerSlot;
-typedef struct AioWorkerControl
+typedef struct PgAioWorkerControl
{
uint64 idle_worker_mask;
- AioWorkerSlot workers[FLEXIBLE_ARRAY_MEMBER];
-} AioWorkerControl;
+ PgAioWorkerSlot workers[FLEXIBLE_ARRAY_MEMBER];
+} PgAioWorkerControl;
static size_t pgaio_worker_shmem_size(void);
@@ -96,8 +96,8 @@ int io_workers = 3;
static int io_worker_queue_size = 64;
static int MyIoWorkerId;
-static AioWorkerSubmissionQueue *io_worker_submission_queue;
-static AioWorkerControl *io_worker_control;
+static PgAioWorkerSubmissionQueue *io_worker_submission_queue;
+static PgAioWorkerControl *io_worker_control;
static size_t
@@ -106,15 +106,15 @@ pgaio_worker_queue_shmem_size(int *queue_size)
/* Round size up to next power of two so we can make a mask. */
*queue_size = pg_nextpower2_32(io_worker_queue_size);
- return offsetof(AioWorkerSubmissionQueue, ios) +
+ return offsetof(PgAioWorkerSubmissionQueue, sqes) +
sizeof(uint32) * *queue_size;
}
static size_t
pgaio_worker_control_shmem_size(void)
{
- return offsetof(AioWorkerControl, workers) +
- sizeof(AioWorkerSlot) * MAX_IO_WORKERS;
+ return offsetof(PgAioWorkerControl, workers) +
+ sizeof(PgAioWorkerSlot) * MAX_IO_WORKERS;
}
static size_t
@@ -162,7 +162,7 @@ pgaio_worker_shmem_init(bool first_time)
}
static int
-pgaio_choose_idle_worker(void)
+pgaio_worker_choose_idle(void)
{
int worker;
@@ -172,6 +172,7 @@ pgaio_choose_idle_worker(void)
/* Find the lowest bit position, and clear it. */
worker = pg_rightmost_one_pos64(io_worker_control->idle_worker_mask);
io_worker_control->idle_worker_mask &= ~(UINT64_C(1) << worker);
+ Assert(io_worker_control->workers[worker].in_use);
return worker;
}
@@ -179,7 +180,7 @@ pgaio_choose_idle_worker(void)
static bool
pgaio_worker_submission_queue_insert(PgAioHandle *ioh)
{
- AioWorkerSubmissionQueue *queue;
+ PgAioWorkerSubmissionQueue *queue;
uint32 new_head;
queue = io_worker_submission_queue;
@@ -191,7 +192,7 @@ pgaio_worker_submission_queue_insert(PgAioHandle *ioh)
return false; /* full */
}
- queue->ios[queue->head] = pgaio_io_get_id(ioh);
+ queue->sqes[queue->head] = pgaio_io_get_id(ioh);
queue->head = new_head;
return true;
@@ -200,14 +201,14 @@ pgaio_worker_submission_queue_insert(PgAioHandle *ioh)
static uint32
pgaio_worker_submission_queue_consume(void)
{
- AioWorkerSubmissionQueue *queue;
+ PgAioWorkerSubmissionQueue *queue;
uint32 result;
queue = io_worker_submission_queue;
if (queue->tail == queue->head)
return UINT32_MAX; /* empty */
- result = queue->ios[queue->tail];
+ result = queue->sqes[queue->tail];
queue->tail = (queue->tail + 1) & (queue->size - 1);
return result;
@@ -240,37 +241,37 @@ pgaio_worker_needs_synchronous_execution(PgAioHandle *ioh)
}
static void
-pgaio_worker_submit_internal(int nios, PgAioHandle *ios[])
+pgaio_worker_submit_internal(int num_staged_ios, PgAioHandle **staged_ios)
{
PgAioHandle *synchronous_ios[PGAIO_SUBMIT_BATCH_SIZE];
int nsync = 0;
Latch *wakeup = NULL;
int worker;
- Assert(nios <= PGAIO_SUBMIT_BATCH_SIZE);
+ Assert(num_staged_ios <= PGAIO_SUBMIT_BATCH_SIZE);
LWLockAcquire(AioWorkerSubmissionQueueLock, LW_EXCLUSIVE);
- for (int i = 0; i < nios; ++i)
+ for (int i = 0; i < num_staged_ios; ++i)
{
- Assert(!pgaio_worker_needs_synchronous_execution(ios[i]));
- if (!pgaio_worker_submission_queue_insert(ios[i]))
+ Assert(!pgaio_worker_needs_synchronous_execution(staged_ios[i]));
+ if (!pgaio_worker_submission_queue_insert(staged_ios[i]))
{
/*
* We'll do it synchronously, but only after we've sent as many as
* we can to workers, to maximize concurrency.
*/
- synchronous_ios[nsync++] = ios[i];
+ synchronous_ios[nsync++] = staged_ios[i];
continue;
}
if (wakeup == NULL)
{
/* Choose an idle worker to wake up if we haven't already. */
- worker = pgaio_choose_idle_worker();
+ worker = pgaio_worker_choose_idle();
if (worker >= 0)
wakeup = io_worker_control->workers[worker].latch;
- pgaio_debug_io(DEBUG4, ios[i],
+ pgaio_debug_io(DEBUG4, staged_ios[i],
"choosing worker %d",
worker);
}
@@ -316,6 +317,7 @@ pgaio_worker_die(int code, Datum arg)
Assert(io_worker_control->workers[MyIoWorkerId].in_use);
Assert(io_worker_control->workers[MyIoWorkerId].latch == MyLatch);
+ io_worker_control->idle_worker_mask &= ~(UINT64_C(1) << MyIoWorkerId);
io_worker_control->workers[MyIoWorkerId].in_use = false;
io_worker_control->workers[MyIoWorkerId].latch = NULL;
LWLockRelease(AioWorkerSubmissionQueueLock);
@@ -488,7 +490,7 @@ IoWorkerMain(const void *startup_data, size_t startup_data_len)
IO_WORKER_WAKEUP_FANOUT);
for (int i = 0; i < nwakeups; ++i)
{
- if ((worker = pgaio_choose_idle_worker()) < 0)
+ if ((worker = pgaio_worker_choose_idle()) < 0)
break;
latches[nlatches++] = io_worker_control->workers[worker].latch;
}
@@ -573,6 +575,12 @@ IoWorkerMain(const void *startup_data, size_t startup_data_len)
}
CHECK_FOR_INTERRUPTS();
+
+ if (ConfigReloadPending)
+ {
+ ConfigReloadPending = false;
+ ProcessConfigFile(PGC_SIGHUP);
+ }
}
error_context_stack = errcallback.previous;
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index e5b945a9ee3..2418967def6 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -1622,58 +1622,6 @@ TransactionIdIsInProgress(TransactionId xid)
return false;
}
-/*
- * TransactionIdIsActive -- is xid the top-level XID of an active backend?
- *
- * This differs from TransactionIdIsInProgress in that it ignores prepared
- * transactions, as well as transactions running on the primary if we're in
- * hot standby. Also, we ignore subtransactions since that's not needed
- * for current uses.
- */
-bool
-TransactionIdIsActive(TransactionId xid)
-{
- bool result = false;
- ProcArrayStruct *arrayP = procArray;
- TransactionId *other_xids = ProcGlobal->xids;
- int i;
-
- /*
- * Don't bother checking a transaction older than RecentXmin; it could not
- * possibly still be running.
- */
- if (TransactionIdPrecedes(xid, RecentXmin))
- return false;
-
- LWLockAcquire(ProcArrayLock, LW_SHARED);
-
- for (i = 0; i < arrayP->numProcs; i++)
- {
- int pgprocno = arrayP->pgprocnos[i];
- PGPROC *proc = &allProcs[pgprocno];
- TransactionId pxid;
-
- /* Fetch xid just once - see GetNewTransactionId */
- pxid = UINT32_ACCESS_ONCE(other_xids[i]);
-
- if (!TransactionIdIsValid(pxid))
- continue;
-
- if (proc->pid == 0)
- continue; /* ignore prepared transactions */
-
- if (TransactionIdEquals(pxid, xid))
- {
- result = true;
- break;
- }
- }
-
- LWLockRelease(ProcArrayLock);
-
- return result;
-}
-
/*
* Determine XID horizons.
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index ca3c5ee3df3..1213f9106d5 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -135,6 +135,22 @@ static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue
/*
+ * Test whether an identifier char can be left unquoted in ACLs.
+ *
+ * Formerly, we used isalnum() even on non-ASCII characters, resulting in
+ * unportable behavior. To ensure dump compatibility with old versions,
+ * we now treat high-bit-set characters as always requiring quoting during
+ * putid(), but getid() will always accept them without quotes.
+ */
+static inline bool
+is_safe_acl_char(unsigned char c, bool is_getid)
+{
+ if (IS_HIGHBIT_SET(c))
+ return is_getid;
+ return isalnum(c) || c == '_';
+}
+
+/*
* getid
* Consumes the first alphanumeric string (identifier) found in string
* 's', ignoring any leading white space. If it finds a double quote
@@ -159,21 +175,22 @@ getid(const char *s, char *n, Node *escontext)
while (isspace((unsigned char) *s))
s++;
- /* This code had better match what putid() does, below */
for (;
*s != '\0' &&
- (isalnum((unsigned char) *s) ||
- *s == '_' ||
- *s == '"' ||
- in_quotes);
+ (in_quotes || *s == '"' || is_safe_acl_char(*s, true));
s++)
{
if (*s == '"')
{
+ if (!in_quotes)
+ {
+ in_quotes = true;
+ continue;
+ }
/* safe to look at next char (could be '\0' though) */
if (*(s + 1) != '"')
{
- in_quotes = !in_quotes;
+ in_quotes = false;
continue;
}
/* it's an escaped double quote; skip the escaping char */
@@ -207,10 +224,10 @@ putid(char *p, const char *s)
const char *src;
bool safe = true;
+ /* Detect whether we need to use double quotes */
for (src = s; *src; src++)
{
- /* This test had better match what getid() does, above */
- if (!isalnum((unsigned char) *src) && *src != '_')
+ if (!is_safe_acl_char(*src, false))
{
safe = false;
break;
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 0a5848a4ab2..25cff56c3d0 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -5312,10 +5312,10 @@ isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
int
date2isoweek(int year, int mon, int mday)
{
- float8 result;
int day0,
day4,
- dayn;
+ dayn,
+ week;
/* current day */
dayn = date2j(year, mon, mday);
@@ -5338,13 +5338,13 @@ date2isoweek(int year, int mon, int mday)
day0 = j2day(day4 - 1);
}
- result = (dayn - (day4 - day0)) / 7 + 1;
+ week = (dayn - (day4 - day0)) / 7 + 1;
/*
* Sometimes the last few days in a year will fall into the first week of
* the next year, so check for this.
*/
- if (result >= 52)
+ if (week >= 52)
{
day4 = date2j(year + 1, 1, 4);
@@ -5352,10 +5352,10 @@ date2isoweek(int year, int mon, int mday)
day0 = j2day(day4 - 1);
if (dayn >= day4 - day0)
- result = (dayn - (day4 - day0)) / 7 + 1;
+ week = (dayn - (day4 - day0)) / 7 + 1;
}
- return (int) result;
+ return week;
}
@@ -5367,10 +5367,10 @@ date2isoweek(int year, int mon, int mday)
int
date2isoyear(int year, int mon, int mday)
{
- float8 result;
int day0,
day4,
- dayn;
+ dayn,
+ week;
/* current day */
dayn = date2j(year, mon, mday);
@@ -5395,13 +5395,13 @@ date2isoyear(int year, int mon, int mday)
year--;
}
- result = (dayn - (day4 - day0)) / 7 + 1;
+ week = (dayn - (day4 - day0)) / 7 + 1;
/*
* Sometimes the last few days in a year will fall into the first week of
* the next year, so check for this.
*/
- if (result >= 52)
+ if (week >= 52)
{
day4 = date2j(year + 1, 1, 4);
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index ef0b733ebe8..e4877d88e8f 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -53,7 +53,6 @@ extern bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc);
extern RunningTransactions GetRunningTransactionData(void);
extern bool TransactionIdIsInProgress(TransactionId xid);
-extern bool TransactionIdIsActive(TransactionId xid);
extern TransactionId GetOldestNonRemovableTransactionId(Relation rel);
extern TransactionId GetOldestTransactionIdConsideredRunning(void);
extern TransactionId GetOldestActiveTransactionId(void);
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index aadc328589d..602a6b255bc 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -2568,6 +2568,26 @@ SELECT makeaclitem('regress_priv_user1'::regrole, 'regress_priv_user2'::regrole,
SELECT makeaclitem('regress_priv_user1'::regrole, 'regress_priv_user2'::regrole,
'SELECT, fake_privilege', FALSE); -- error
ERROR: unrecognized privilege type: "fake_privilege"
+-- Test quoting and dequoting of user names in ACLs
+CREATE ROLE "regress_""quoted";
+SELECT makeaclitem('regress_"quoted'::regrole, 'regress_"quoted'::regrole,
+ 'SELECT', TRUE);
+ makeaclitem
+------------------------------------------
+ "regress_""quoted"=r*/"regress_""quoted"
+(1 row)
+
+SELECT '"regress_""quoted"=r*/"regress_""quoted"'::aclitem;
+ aclitem
+------------------------------------------
+ "regress_""quoted"=r*/"regress_""quoted"
+(1 row)
+
+SELECT '""=r*/""'::aclitem; -- used to be misparsed as """"
+ERROR: a name must follow the "/" sign
+LINE 1: SELECT '""=r*/""'::aclitem;
+ ^
+DROP ROLE "regress_""quoted";
-- Test non-throwing aclitem I/O
SELECT pg_input_is_valid('regress_priv_user1=r/regress_priv_user2', 'aclitem');
pg_input_is_valid
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index 47bd4011dc9..3eacc1340aa 100644
--- a/src/test/regress/sql/privileges.sql
+++ b/src/test/regress/sql/privileges.sql
@@ -1544,6 +1544,14 @@ SELECT makeaclitem('regress_priv_user1'::regrole, 'regress_priv_user2'::regrole,
SELECT makeaclitem('regress_priv_user1'::regrole, 'regress_priv_user2'::regrole,
'SELECT, fake_privilege', FALSE); -- error
+-- Test quoting and dequoting of user names in ACLs
+CREATE ROLE "regress_""quoted";
+SELECT makeaclitem('regress_"quoted'::regrole, 'regress_"quoted'::regrole,
+ 'SELECT', TRUE);
+SELECT '"regress_""quoted"=r*/"regress_""quoted"'::aclitem;
+SELECT '""=r*/""'::aclitem; -- used to be misparsed as """"
+DROP ROLE "regress_""quoted";
+
-- Test non-throwing aclitem I/O
SELECT pg_input_is_valid('regress_priv_user1=r/regress_priv_user2', 'aclitem');
SELECT pg_input_is_valid('regress_priv_user1=r/', 'aclitem');
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 83192038571..ff050e93a50 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -55,9 +55,6 @@ AggStrategy
AggTransInfo
Aggref
AggregateInstrumentation
-AioWorkerControl
-AioWorkerSlot
-AioWorkerSubmissionQueue
AlenState
Alias
AllocBlock
@@ -2184,6 +2181,9 @@ PgAioTargetInfo
PgAioUringCaps
PgAioUringContext
PgAioWaitRef
+PgAioWorkerControl
+PgAioWorkerSlot
+PgAioWorkerSubmissionQueue
PgArchData
PgBackendGSSStatus
PgBackendSSLStatus