PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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-2026, 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
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
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 ((PgAioOp) ioh->op)
125 {
126 case PGAIO_OP_READV:
128 result = pg_preadv(ioh->op_data.read.fd, iov,
129 ioh->op_data.read.iov_length,
130 ioh->op_data.read.offset);
132 break;
133 case PGAIO_OP_WRITEV:
135 result = pg_pwritev(ioh->op_data.write.fd, iov,
136 ioh->op_data.write.iov_length,
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 /*
145 * ssize_t to int conversion should be ok because result should be no more
146 * than PG_IOV_MAX times BLCKSZ.
147 */
149 ioh->result = result < 0 ? -errno : result;
150
152
154}
155
156/*
157 * Helper function to be called by IO operation preparation functions, before
158 * any data in the handle is set. Mostly to centralize assertions.
159 */
160static void
162{
163 Assert(ioh->state == PGAIO_HS_HANDED_OUT);
167
168 /*
169 * Otherwise the FDs referenced by the IO could be closed due to interrupt
170 * processing.
171 */
173}
174
175/*
176 * Could be made part of the public interface, but it's not clear there's
177 * really a use case for that.
178 */
179const char *
181{
182 Assert(ioh->op >= 0 && ioh->op < PGAIO_OP_COUNT);
183
184 switch ((PgAioOp) ioh->op)
185 {
186 case PGAIO_OP_INVALID:
187 return "invalid";
188 case PGAIO_OP_READV:
189 return "readv";
190 case PGAIO_OP_WRITEV:
191 return "writev";
192 }
193
194 return NULL; /* silence compiler */
195}
196
197/*
198 * Used to determine if an IO needs to be waited upon before the file
199 * descriptor can be closed.
200 */
201bool
203{
204 Assert(ioh->state >= PGAIO_HS_DEFINED);
205
206 switch ((PgAioOp) ioh->op)
207 {
208 case PGAIO_OP_READV:
209 return ioh->op_data.read.fd == fd;
210 case PGAIO_OP_WRITEV:
211 return ioh->op_data.write.fd == fd;
212 case PGAIO_OP_INVALID:
213 return false;
214 }
215
216 return false; /* silence compiler */
217}
218
219/*
220 * Return the iovec and its length. Currently only expected to be used by
221 * debugging infrastructure
222 */
223int
225{
226 Assert(ioh->state >= PGAIO_HS_DEFINED);
227
228 *iov = &pgaio_ctl->iovecs[ioh->iovec_off];
229
230 switch ((PgAioOp) ioh->op)
231 {
232 case PGAIO_OP_READV:
233 return ioh->op_data.read.iov_length;
234 case PGAIO_OP_WRITEV:
235 return ioh->op_data.write.iov_length;
236 default:
238 return 0;
239 }
240}
void pgaio_io_process_completion(PgAioHandle *ioh, int result)
Definition aio.c:528
PgAioBackend * pgaio_my_backend
Definition aio.c:81
void pgaio_io_stage(PgAioHandle *ioh, PgAioOp op)
Definition aio.c:424
PgAioCtl * pgaio_ctl
Definition aio.c:78
#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
@ PGAIO_HS_HANDED_OUT
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:180
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:202
static void pgaio_io_before_start(PgAioHandle *ioh)
Definition aio_io.c:161
PgAioOp pgaio_io_get_op(PgAioHandle *ioh)
Definition aio_io.c:52
int pgaio_io_get_iovec_length(PgAioHandle *ioh, struct iovec **iov)
Definition aio_io.c:224
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:40
#define Assert(condition)
Definition c.h:1002
uint64_t uint64
Definition c.h:684
#define pg_unreachable()
Definition c.h:426
uint32 result
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define INTERRUPTS_CAN_BE_PROCESSED()
Definition miscadmin.h:132
#define START_CRIT_SECTION()
Definition miscadmin.h:152
#define END_CRIT_SECTION()
Definition miscadmin.h:154
static ssize_t pg_preadv(int fd, const struct iovec *iov, int iovcnt, pgoff_t offset)
Definition pg_iovec.h:54
#define PG_IOV_MAX
Definition pg_iovec.h:47
static ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, pgoff_t offset)
Definition pg_iovec.h:93
static int fd(const char *x, int i)
static int fb(int x)
PgAioHandle * handed_out_io
struct iovec * iovecs
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition wait_event.h:67
static void pgstat_report_wait_end(void)
Definition wait_event.h:83