PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
aio_io.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * aio_io.c
4 * AIO - Low Level IO Handling
5 *
6 * Functions related to associating IO operations to IO Handles and IO-method
7 * independent support functions for actually performing IO.
8 *
9 *
10 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
11 * Portions Copyright (c) 1994, Regents of the University of California
12 *
13 * IDENTIFICATION
14 * src/backend/storage/aio/aio_io.c
15 *
16 *-------------------------------------------------------------------------
17 */
18
19#include "postgres.h"
20
21#include "miscadmin.h"
22#include "storage/aio.h"
24#include "storage/fd.h"
25#include "utils/wait_event.h"
26
27
28static void pgaio_io_before_start(PgAioHandle *ioh);
29
30
31
32/* --------------------------------------------------------------------------------
33 * Public IO related functions operating on IO Handles
34 * --------------------------------------------------------------------------------
35 */
36
37/*
38 * Scatter/gather IO needs to associate an iovec with the Handle. To support
39 * worker mode this data needs to be in shared memory.
40 */
41int
42pgaio_io_get_iovec(PgAioHandle *ioh, struct iovec **iov)
43{
45
46 *iov = &pgaio_ctl->iovecs[ioh->iovec_off];
47
48 return PG_IOV_MAX;
49}
50
53{
54 return ioh->op;
55}
56
59{
60 return &ioh->op_data;
61}
62
63
64
65/* --------------------------------------------------------------------------------
66 * "Start" routines for individual IO operations
67 *
68 * These are called by the code actually initiating an IO, to associate the IO
69 * specific data with an AIO handle.
70 *
71 * Each of the "start" routines first needs to call pgaio_io_before_start(),
72 * then fill IO specific fields in the handle and then finally call
73 * pgaio_io_stage().
74 * --------------------------------------------------------------------------------
75 */
76
77void
79 int fd, int iovcnt, uint64 offset)
80{
82
83 ioh->op_data.read.fd = fd;
84 ioh->op_data.read.offset = offset;
85 ioh->op_data.read.iov_length = iovcnt;
86
88}
89
90void
92 int fd, int iovcnt, uint64 offset)
93{
95
96 ioh->op_data.write.fd = fd;
97 ioh->op_data.write.offset = offset;
98 ioh->op_data.write.iov_length = iovcnt;
99
101}
102
103
104
105/* --------------------------------------------------------------------------------
106 * Internal IO related functions operating on IO Handles
107 * --------------------------------------------------------------------------------
108 */
109
110/*
111 * Execute IO operation synchronously. This is implemented here, not in
112 * method_sync.c, because other IO methods also might use it / fall back to
113 * it.
114 */
115void
117{
118 ssize_t result = 0;
119 struct iovec *iov = &pgaio_ctl->iovecs[ioh->iovec_off];
120
122
123 /* Perform IO. */
124 switch (ioh->op)
125 {
126 case PGAIO_OP_READV:
127 pgstat_report_wait_start(WAIT_EVENT_DATA_FILE_READ);
128 result = pg_preadv(ioh->op_data.read.fd, iov,
130 ioh->op_data.read.offset);
132 break;
133 case PGAIO_OP_WRITEV:
134 pgstat_report_wait_start(WAIT_EVENT_DATA_FILE_WRITE);
135 result = pg_pwritev(ioh->op_data.write.fd, iov,
137 ioh->op_data.write.offset);
139 break;
140 case PGAIO_OP_INVALID:
141 elog(ERROR, "trying to execute invalid IO operation");
142 }
143
144 ioh->result = result < 0 ? -errno : result;
145
147
149}
150
151/*
152 * Helper function to be called by IO operation preparation functions, before
153 * any data in the handle is set. Mostly to centralize assertions.
154 */
155static void
157{
161 Assert(ioh->op == PGAIO_OP_INVALID);
162
163 /*
164 * Otherwise the FDs referenced by the IO could be closed due to interrupt
165 * processing.
166 */
168}
169
170/*
171 * Could be made part of the public interface, but it's not clear there's
172 * really a use case for that.
173 */
174const char *
176{
177 Assert(ioh->op >= 0 && ioh->op < PGAIO_OP_COUNT);
178
179 switch (ioh->op)
180 {
181 case PGAIO_OP_INVALID:
182 return "invalid";
183 case PGAIO_OP_READV:
184 return "read";
185 case PGAIO_OP_WRITEV:
186 return "write";
187 }
188
189 return NULL; /* silence compiler */
190}
191
192/*
193 * Used to determine if an IO needs to be waited upon before the file
194 * descriptor can be closed.
195 */
196bool
198{
200
201 switch (ioh->op)
202 {
203 case PGAIO_OP_READV:
204 return ioh->op_data.read.fd == fd;
205 case PGAIO_OP_WRITEV:
206 return ioh->op_data.write.fd == fd;
207 case PGAIO_OP_INVALID:
208 return false;
209 }
210
211 return false; /* silence compiler */
212}
void pgaio_io_process_completion(PgAioHandle *ioh, int result)
Definition: aio.c:498
PgAioBackend * pgaio_my_backend
Definition: aio.c:82
void pgaio_io_stage(PgAioHandle *ioh, PgAioOp op)
Definition: aio.c:403
PgAioCtl * pgaio_ctl
Definition: aio.c:79
#define PGAIO_OP_COUNT
Definition: aio.h:107
PgAioOp
Definition: aio.h:88
@ PGAIO_OP_WRITEV
Definition: aio.h:93
@ PGAIO_OP_INVALID
Definition: aio.h:90
@ PGAIO_OP_READV
Definition: aio.h:92
@ PGAIO_HS_DEFINED
Definition: aio_internal.h:54
@ PGAIO_HS_HANDED_OUT
Definition: aio_internal.h:48
void pgaio_io_perform_synchronously(PgAioHandle *ioh)
Definition: aio_io.c:116
const char * pgaio_io_get_op_name(PgAioHandle *ioh)
Definition: aio_io.c:175
void pgaio_io_start_readv(PgAioHandle *ioh, int fd, int iovcnt, uint64 offset)
Definition: aio_io.c:78
PgAioOpData * pgaio_io_get_op_data(PgAioHandle *ioh)
Definition: aio_io.c:58
bool pgaio_io_uses_fd(PgAioHandle *ioh, int fd)
Definition: aio_io.c:197
static void pgaio_io_before_start(PgAioHandle *ioh)
Definition: aio_io.c:156
PgAioOp pgaio_io_get_op(PgAioHandle *ioh)
Definition: aio_io.c:52
void pgaio_io_start_writev(PgAioHandle *ioh, int fd, int iovcnt, uint64 offset)
Definition: aio_io.c:91
int pgaio_io_get_iovec(PgAioHandle *ioh, struct iovec **iov)
Definition: aio_io.c:42
bool pgaio_io_has_target(PgAioHandle *ioh)
Definition: aio_target.c:38
uint64_t uint64
Definition: c.h:503
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
Assert(PointerIsAligned(start, uint64))
#define INTERRUPTS_CAN_BE_PROCESSED()
Definition: miscadmin.h:129
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
static ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
Definition: pg_iovec.h:87
static ssize_t pg_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
Definition: pg_iovec.h:48
#define PG_IOV_MAX
Definition: pg_iovec.h:41
static int fd(const char *x, int i)
Definition: preproc-init.c:105
PgAioHandle * handed_out_io
Definition: aio_internal.h:195
struct iovec * iovecs
Definition: aio_internal.h:229
PgAioOp op
Definition: aio_internal.h:100
PgAioOpData op_data
Definition: aio_internal.h:169
uint32 iovec_off
Definition: aio_internal.h:159
PgAioHandleState state
Definition: aio_internal.h:94
uint64 offset
Definition: aio.h:139
int fd
Definition: aio.h:137
uint16 iov_length
Definition: aio.h:138
struct PgAioOpData::@123 write
struct PgAioOpData::@122 read
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:85
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101