Mercurial > hg > nginx-quic
annotate src/os/unix/ngx_file_aio_read.c @ 4448:539355d9e675 stable-1.0
Merge of r4404:
Fixed sched_setaffinity(2) to correctly pass size.
Second argument (cpusetsize) is size in bytes, not in bits. Previously
used constant 32 resulted in reading of uninitialized memory and caused
EINVAL to be returned on some Linux kernels.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sun, 05 Feb 2012 19:25:24 +0000 |
parents | d3568507db51 |
children | d620f497c50f |
rev | line source |
---|---|
3052 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 | |
11 | |
12 /* | |
13 * FreeBSD file AIO features and quirks: | |
14 * | |
15 * if an asked data are already in VM cache, then aio_error() returns 0, | |
16 * and the data are already copied in buffer; | |
17 * | |
3065 | 18 * aio_read() preread in VM cache as minimum 16K (probably BKVASIZE); |
19 * the first AIO preload may be up to 128K; | |
3052 | 20 * |
21 * aio_read/aio_error() may return EINPROGRESS for just written data; | |
22 * | |
23 * kqueue EVFILT_AIO filter is level triggered only: an event repeats | |
24 * until aio_return() will be called; | |
25 * | |
4246
d3568507db51
Merging r4132, r4134, r4143, r4183, r4191, r4199:
Igor Sysoev <igor@sysoev.ru>
parents:
4161
diff
changeset
|
26 * aio_cancel() cannot cancel file AIO: it returns AIO_NOTCANCELED always. |
3052 | 27 */ |
28 | |
29 | |
30 extern int ngx_kqueue; | |
31 | |
32 | |
33 static ssize_t ngx_file_aio_result(ngx_file_t *file, ngx_event_aio_t *aio, | |
34 ngx_event_t *ev); | |
35 static void ngx_file_aio_event_handler(ngx_event_t *ev); | |
36 | |
37 | |
38 ssize_t | |
39 ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset, | |
40 ngx_pool_t *pool) | |
41 { | |
3294
04cfc09b8b8d
export aio presence knowledge to prevent using "aio sendfile",
Igor Sysoev <igor@sysoev.ru>
parents:
3065
diff
changeset
|
42 int n; |
04cfc09b8b8d
export aio presence knowledge to prevent using "aio sendfile",
Igor Sysoev <igor@sysoev.ru>
parents:
3065
diff
changeset
|
43 ngx_event_t *ev; |
04cfc09b8b8d
export aio presence knowledge to prevent using "aio sendfile",
Igor Sysoev <igor@sysoev.ru>
parents:
3065
diff
changeset
|
44 ngx_event_aio_t *aio; |
3052 | 45 |
3294
04cfc09b8b8d
export aio presence knowledge to prevent using "aio sendfile",
Igor Sysoev <igor@sysoev.ru>
parents:
3065
diff
changeset
|
46 if (!ngx_file_aio) { |
3052 | 47 return ngx_read_file(file, buf, size, offset); |
48 } | |
49 | |
50 aio = file->aio; | |
51 | |
52 if (aio == NULL) { | |
53 aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t)); | |
54 if (aio == NULL) { | |
55 return NGX_ERROR; | |
56 } | |
57 | |
58 aio->file = file; | |
59 aio->fd = file->fd; | |
60 aio->event.data = aio; | |
61 aio->event.ready = 1; | |
62 aio->event.log = file->log; | |
3065 | 63 #if (NGX_HAVE_AIO_SENDFILE) |
64 aio->last_offset = -1; | |
65 #endif | |
3052 | 66 file->aio = aio; |
67 } | |
68 | |
69 ev = &aio->event; | |
70 | |
71 if (!ev->ready) { | |
72 ngx_log_error(NGX_LOG_ALERT, file->log, 0, | |
73 "second aio post for \"%V\"", &file->name); | |
74 return NGX_AGAIN; | |
75 } | |
76 | |
77 ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, | |
78 "aio complete:%d @%O:%z %V", | |
79 ev->complete, offset, size, &file->name); | |
80 | |
81 if (ev->complete) { | |
82 ev->complete = 0; | |
83 ngx_set_errno(aio->err); | |
84 | |
85 if (aio->err == 0) { | |
86 return aio->nbytes; | |
87 } | |
88 | |
4161 | 89 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, |
90 "aio read \"%s\" failed", file->name.data); | |
91 | |
3052 | 92 return NGX_ERROR; |
93 } | |
94 | |
95 ngx_memzero(&aio->aiocb, sizeof(struct aiocb)); | |
96 | |
97 aio->aiocb.aio_fildes = file->fd; | |
98 aio->aiocb.aio_offset = offset; | |
99 aio->aiocb.aio_buf = buf; | |
100 aio->aiocb.aio_nbytes = size; | |
101 #if (NGX_HAVE_KQUEUE) | |
102 aio->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue; | |
103 aio->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT; | |
104 aio->aiocb.aio_sigevent.sigev_value.sigval_ptr = ev; | |
105 #endif | |
106 ev->handler = ngx_file_aio_event_handler; | |
107 | |
108 n = aio_read(&aio->aiocb); | |
109 | |
110 if (n == -1) { | |
111 n = ngx_errno; | |
112 | |
113 if (n == NGX_EAGAIN) { | |
114 return ngx_read_file(file, buf, size, offset); | |
115 } | |
116 | |
117 ngx_log_error(NGX_LOG_CRIT, file->log, n, | |
118 "aio_read(\"%V\") failed", &file->name); | |
119 | |
120 if (n == NGX_ENOSYS) { | |
3294
04cfc09b8b8d
export aio presence knowledge to prevent using "aio sendfile",
Igor Sysoev <igor@sysoev.ru>
parents:
3065
diff
changeset
|
121 ngx_file_aio = 0; |
3052 | 122 return ngx_read_file(file, buf, size, offset); |
123 } | |
124 | |
125 return NGX_ERROR; | |
126 } | |
127 | |
128 ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, | |
129 "aio_read: fd:%d %d", file->fd, n); | |
130 | |
131 ev->active = 1; | |
132 ev->ready = 0; | |
133 ev->complete = 0; | |
134 | |
135 return ngx_file_aio_result(aio->file, aio, ev); | |
136 } | |
137 | |
138 | |
139 static ssize_t | |
140 ngx_file_aio_result(ngx_file_t *file, ngx_event_aio_t *aio, ngx_event_t *ev) | |
141 { | |
142 int n; | |
143 ngx_err_t err; | |
144 | |
145 n = aio_error(&aio->aiocb); | |
146 | |
147 ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, | |
148 "aio_error: fd:%d %d", file->fd, n); | |
149 | |
150 if (n == -1) { | |
151 err = ngx_errno; | |
152 aio->err = err; | |
153 | |
154 ngx_log_error(NGX_LOG_ALERT, file->log, err, | |
155 "aio_error(\"%V\") failed", &file->name); | |
156 return NGX_ERROR; | |
157 } | |
158 | |
159 if (n != 0) { | |
160 if (n == NGX_EINPROGRESS) { | |
161 if (ev->ready) { | |
162 ev->ready = 0; | |
163 ngx_log_error(NGX_LOG_ALERT, file->log, n, | |
164 "aio_read(\"%V\") still in progress", | |
165 &file->name); | |
166 } | |
167 | |
168 return NGX_AGAIN; | |
169 } | |
170 | |
171 aio->err = n; | |
172 ev->ready = 0; | |
173 | |
174 ngx_log_error(NGX_LOG_CRIT, file->log, n, | |
175 "aio_read(\"%V\") failed", &file->name); | |
176 return NGX_ERROR; | |
177 } | |
178 | |
179 n = aio_return(&aio->aiocb); | |
180 | |
181 if (n == -1) { | |
182 err = ngx_errno; | |
183 aio->err = err; | |
184 ev->ready = 0; | |
185 | |
186 ngx_log_error(NGX_LOG_ALERT, file->log, err, | |
187 "aio_return(\"%V\") failed", &file->name); | |
188 return NGX_ERROR; | |
189 } | |
190 | |
191 aio->err = 0; | |
192 aio->nbytes = n; | |
193 ev->ready = 1; | |
194 ev->active = 0; | |
195 | |
196 ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, | |
197 "aio_return: fd:%d %d", file->fd, n); | |
198 | |
199 return n; | |
200 } | |
201 | |
202 | |
203 static void | |
204 ngx_file_aio_event_handler(ngx_event_t *ev) | |
205 { | |
206 ngx_event_aio_t *aio; | |
207 | |
208 aio = ev->data; | |
209 | |
210 ngx_log_debug2(NGX_LOG_DEBUG_CORE, ev->log, 0, | |
211 "aio event handler fd:%d %V", aio->fd, &aio->file->name); | |
212 | |
213 if (ngx_file_aio_result(aio->file, aio, ev) != NGX_AGAIN) { | |
214 aio->handler(ev); | |
215 } | |
216 } |