PostgreSQL Source Code
git master
Loading...
Searching...
No Matches
aio_funcs.c
Go to the documentation of this file.
1
/*-------------------------------------------------------------------------
2
*
3
* aio_funcs.c
4
* AIO - SQL interface for AIO
5
*
6
*
7
* Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8
* Portions Copyright (c) 1994, Regents of the University of California
9
*
10
* IDENTIFICATION
11
* src/backend/storage/aio/aio_funcs.c
12
*
13
*-------------------------------------------------------------------------
14
*/
15
16
#include "
postgres.h
"
17
18
#include "
fmgr.h
"
19
#include "
funcapi.h
"
20
#include "
nodes/execnodes.h
"
21
#include "
port/atomics.h
"
22
#include "
storage/aio_internal.h
"
23
#include "
storage/lock.h
"
24
#include "
storage/proc.h
"
25
#include "
storage/procnumber.h
"
26
#include "
utils/builtins.h
"
27
#include "utils/fmgrprotos.h"
28
#include "
utils/tuplestore.h
"
29
30
31
/*
32
* Byte length of an iovec.
33
*/
34
static
size_t
35
iov_byte_length
(
const
struct
iovec
*
iov
,
int
cnt)
36
{
37
size_t
len
= 0;
38
39
for
(
int
i
= 0;
i
< cnt;
i
++)
40
{
41
len
+=
iov
[
i
].iov_len;
42
}
43
44
return
len
;
45
}
46
47
Datum
48
pg_get_aios
(
PG_FUNCTION_ARGS
)
49
{
50
ReturnSetInfo
*
rsinfo
= (
ReturnSetInfo
*) fcinfo->resultinfo;
51
52
InitMaterializedSRF
(fcinfo, 0);
53
54
#define PG_GET_AIOS_COLS 15
55
56
for
(
uint64
i
= 0;
i
<
pgaio_ctl
->
io_handle_count
;
i
++)
57
{
58
PgAioHandle
*
live_ioh
= &
pgaio_ctl
->
io_handles
[
i
];
59
int
ioh_id
=
pgaio_io_get_id
(
live_ioh
);
60
Datum
values
[
PG_GET_AIOS_COLS
] = {0};
61
bool
nulls[
PG_GET_AIOS_COLS
] = {0};
62
ProcNumber
owner;
63
PGPROC
*
owner_proc
;
64
int32
owner_pid;
65
PgAioHandleState
start_state;
66
uint64
start_generation
;
67
PgAioHandle
ioh_copy
;
68
struct
iovec
iov_copy
[
PG_IOV_MAX
];
69
70
71
/*
72
* There is no lock that could prevent the state of the IO to advance
73
* concurrently - and we don't want to introduce one, as that would
74
* introduce atomics into a very common path. Instead we
75
*
76
* 1) Determine the state + generation of the IO.
77
*
78
* 2) Copy the IO to local memory.
79
*
80
* 3) Check if state or generation of the IO changed. If the state
81
* changed, retry, if the generation changed don't display the IO.
82
*/
83
84
/* 1) from above */
85
start_generation
=
live_ioh
->
generation
;
86
87
/*
88
* Retry at this point, so we can accept changing states, but not
89
* changing generations.
90
*/
91
retry
:
92
pg_read_barrier
();
93
start_state =
live_ioh
->state;
94
95
if
(start_state ==
PGAIO_HS_IDLE
)
96
continue
;
97
98
/* 2) from above */
99
memcpy
(&
ioh_copy
,
live_ioh
,
sizeof
(
PgAioHandle
));
100
101
/*
102
* Safe to copy even if no iovec is used - we always reserve the
103
* required space.
104
*/
105
memcpy
(&
iov_copy
, &
pgaio_ctl
->
iovecs
[
ioh_copy
.iovec_off],
106
PG_IOV_MAX
*
sizeof
(
struct
iovec
));
107
108
/*
109
* Copy information about owner before 3) below, if the process exited
110
* it'd have to wait for the IO to finish first, which we would detect
111
* in 3).
112
*/
113
owner =
ioh_copy
.owner_procno;
114
owner_proc
=
GetPGProcByNumber
(owner);
115
owner_pid =
owner_proc
->pid;
116
117
/* 3) from above */
118
pg_read_barrier
();
119
120
/*
121
* The IO completed and a new one was started with the same ID. Don't
122
* display it - it really started after this function was called.
123
* There be a risk of a livelock if we just retried endlessly, if IOs
124
* complete very quickly.
125
*/
126
if
(
live_ioh
->generation !=
start_generation
)
127
continue
;
128
129
/*
130
* The IO's state changed while we were "rendering" it. Just start
131
* from scratch. There's no risk of a livelock here, as an IO has a
132
* limited sets of states it can be in, and state changes go only in a
133
* single direction.
134
*/
135
if
(
live_ioh
->state != start_state)
136
goto
retry
;
137
138
/*
139
* Now that we have copied the IO into local memory and checked that
140
* it's still in the same state, we are not allowed to access "live"
141
* memory anymore. To make it slightly easier to catch such cases, set
142
* the "live" pointers to NULL.
143
*/
144
live_ioh
=
NULL
;
145
owner_proc
=
NULL
;
146
147
148
/* column: owning pid */
149
if
(owner_pid != 0)
150
values
[0] =
Int32GetDatum
(owner_pid);
151
else
152
nulls[0] =
false
;
153
154
/* column: IO's id */
155
values
[1] =
Int32GetDatum
(
ioh_id
);
156
157
/* column: IO's generation */
158
values
[2] =
Int64GetDatum
(
start_generation
);
159
160
/* column: IO's state */
161
values
[3] =
CStringGetTextDatum
(
pgaio_io_get_state_name
(&
ioh_copy
));
162
163
/*
164
* If the IO is in PGAIO_HS_HANDED_OUT state, none of the following
165
* fields are valid yet (or are in the process of being set).
166
* Therefore we don't want to display any other columns.
167
*/
168
if
(start_state ==
PGAIO_HS_HANDED_OUT
)
169
{
170
memset
(nulls + 4, 1, (
lengthof
(nulls) - 4) *
sizeof
(
bool
));
171
goto
display
;
172
}
173
174
/* column: IO's operation */
175
values
[4] =
CStringGetTextDatum
(
pgaio_io_get_op_name
(&
ioh_copy
));
176
177
/* columns: details about the IO's operation (offset, length) */
178
switch
((
PgAioOp
)
ioh_copy
.op)
179
{
180
case
PGAIO_OP_INVALID
:
181
nulls[5] =
true
;
182
nulls[6] =
true
;
183
break
;
184
case
PGAIO_OP_READV
:
185
values
[5] =
Int64GetDatum
(
ioh_copy
.op_data.read.offset);
186
values
[6] =
187
Int64GetDatum
(
iov_byte_length
(
iov_copy
,
ioh_copy
.op_data.read.iov_length));
188
break
;
189
case
PGAIO_OP_WRITEV
:
190
values
[5] =
Int64GetDatum
(
ioh_copy
.op_data.write.offset);
191
values
[6] =
192
Int64GetDatum
(
iov_byte_length
(
iov_copy
,
ioh_copy
.op_data.write.iov_length));
193
break
;
194
}
195
196
/* column: IO's target */
197
values
[7] =
CStringGetTextDatum
(
pgaio_io_get_target_name
(&
ioh_copy
));
198
199
/* column: length of IO's data array */
200
values
[8] =
Int16GetDatum
(
ioh_copy
.handle_data_len);
201
202
/* column: raw result (i.e. some form of syscall return value) */
203
if
(start_state ==
PGAIO_HS_COMPLETED_IO
204
|| start_state ==
PGAIO_HS_COMPLETED_SHARED
205
|| start_state ==
PGAIO_HS_COMPLETED_LOCAL
)
206
values
[9] =
Int32GetDatum
(
ioh_copy
.result);
207
else
208
nulls[9] =
true
;
209
210
/*
211
* column: result in the higher level representation (unknown if not
212
* finished)
213
*/
214
values
[10] =
215
CStringGetTextDatum
(
pgaio_result_status_string
(
ioh_copy
.distilled_result.status));
216
217
/* column: target description */
218
values
[11] =
CStringGetTextDatum
(
pgaio_io_get_target_description
(&
ioh_copy
));
219
220
/* columns: one for each flag */
221
values
[12] =
BoolGetDatum
(
ioh_copy
.flags &
PGAIO_HF_SYNCHRONOUS
);
222
values
[13] =
BoolGetDatum
(
ioh_copy
.flags &
PGAIO_HF_REFERENCES_LOCAL
);
223
values
[14] =
BoolGetDatum
(
ioh_copy
.flags &
PGAIO_HF_BUFFERED
);
224
225
display
:
226
tuplestore_putvalues
(
rsinfo
->setResult,
rsinfo
->setDesc,
values
, nulls);
227
}
228
229
return
(
Datum
) 0;
230
}
pgaio_io_get_id
int pgaio_io_get_id(PgAioHandle *ioh)
Definition
aio.c:342
pgaio_result_status_string
const char * pgaio_result_status_string(PgAioResultStatus rs)
Definition
aio.c:934
pgaio_ctl
PgAioCtl * pgaio_ctl
Definition
aio.c:78
pgaio_io_get_state_name
const char * pgaio_io_get_state_name(PgAioHandle *ioh)
Definition
aio.c:928
PgAioOp
PgAioOp
Definition
aio.h:88
PGAIO_OP_WRITEV
@ PGAIO_OP_WRITEV
Definition
aio.h:93
PGAIO_OP_INVALID
@ PGAIO_OP_INVALID
Definition
aio.h:90
PGAIO_OP_READV
@ PGAIO_OP_READV
Definition
aio.h:92
PGAIO_HF_SYNCHRONOUS
@ PGAIO_HF_SYNCHRONOUS
Definition
aio.h:70
PGAIO_HF_REFERENCES_LOCAL
@ PGAIO_HF_REFERENCES_LOCAL
Definition
aio.h:60
PGAIO_HF_BUFFERED
@ PGAIO_HF_BUFFERED
Definition
aio.h:77
iov_byte_length
static size_t iov_byte_length(const struct iovec *iov, int cnt)
Definition
aio_funcs.c:35
PG_GET_AIOS_COLS
#define PG_GET_AIOS_COLS
pg_get_aios
Datum pg_get_aios(PG_FUNCTION_ARGS)
Definition
aio_funcs.c:48
aio_internal.h
PgAioHandleState
PgAioHandleState
Definition
aio_internal.h:44
PGAIO_HS_COMPLETED_SHARED
@ PGAIO_HS_COMPLETED_SHARED
Definition
aio_internal.h:82
PGAIO_HS_IDLE
@ PGAIO_HS_IDLE
Definition
aio_internal.h:46
PGAIO_HS_HANDED_OUT
@ PGAIO_HS_HANDED_OUT
Definition
aio_internal.h:53
PGAIO_HS_COMPLETED_IO
@ PGAIO_HS_COMPLETED_IO
Definition
aio_internal.h:72
PGAIO_HS_COMPLETED_LOCAL
@ PGAIO_HS_COMPLETED_LOCAL
Definition
aio_internal.h:89
pgaio_io_get_op_name
const char * pgaio_io_get_op_name(PgAioHandle *ioh)
Definition
aio_io.c:175
pgaio_io_get_target_name
const char * pgaio_io_get_target_name(PgAioHandle *ioh)
Definition
aio_target.c:50
pgaio_io_get_target_description
char * pgaio_io_get_target_description(PgAioHandle *ioh)
Definition
aio_target.c:84
atomics.h
pg_read_barrier
#define pg_read_barrier()
Definition
atomics.h:154
values
static Datum values[MAXATTR]
Definition
bootstrap.c:155
builtins.h
CStringGetTextDatum
#define CStringGetTextDatum(s)
Definition
builtins.h:97
int32
int32_t int32
Definition
c.h:542
uint64
uint64_t uint64
Definition
c.h:547
lengthof
#define lengthof(array)
Definition
c.h:803
execnodes.h
fmgr.h
PG_FUNCTION_ARGS
#define PG_FUNCTION_ARGS
Definition
fmgr.h:193
InitMaterializedSRF
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition
funcapi.c:76
funcapi.h
i
int i
Definition
isn.c:77
lock.h
len
const void size_t len
Definition
pg_crc32c_sse42.c:28
PG_IOV_MAX
#define PG_IOV_MAX
Definition
pg_iovec.h:47
postgres.h
Int64GetDatum
static Datum Int64GetDatum(int64 X)
Definition
postgres.h:423
Int16GetDatum
static Datum Int16GetDatum(int16 X)
Definition
postgres.h:182
BoolGetDatum
static Datum BoolGetDatum(bool X)
Definition
postgres.h:112
Datum
uint64_t Datum
Definition
postgres.h:70
Int32GetDatum
static Datum Int32GetDatum(int32 X)
Definition
postgres.h:222
fb
static int fb(int x)
Definition
preproc-init.c:92
proc.h
GetPGProcByNumber
#define GetPGProcByNumber(n)
Definition
proc.h:446
procnumber.h
ProcNumber
int ProcNumber
Definition
procnumber.h:24
PGPROC
Definition
proc.h:179
PgAioCtl::iovecs
struct iovec * iovecs
Definition
aio_internal.h:240
PgAioCtl::io_handles
PgAioHandle * io_handles
Definition
aio_internal.h:252
PgAioCtl::io_handle_count
uint32 io_handle_count
Definition
aio_internal.h:251
PgAioHandle
Definition
aio_internal.h:103
PgAioHandle::generation
uint64 generation
Definition
aio_internal.h:152
ReturnSetInfo
Definition
execnodes.h:355
tuplestore_putvalues
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition
tuplestore.c:784
tuplestore.h
src
backend
storage
aio
aio_funcs.c
Generated on Tue Jan 27 2026 12:13:13 for PostgreSQL Source Code by
1.9.8