Mercurial > hg > nginx-quic
comparison src/event/modules/ngx_epoll_module.c @ 4164:c48662671609 stable-1.0
Merging r4130, r4131, r4135:
Linux AIO related fixes:
*) Fixing Linux AIO syscalls return value handling:
syscall(2) uses usual libc convention, it returns -1 on error and
sets errno. Obsolete _syscall(2) returns negative value of error.
*) Fixing Linux AIO initiatialization: AIO operations are disabled
if kernel does not support them. Previously worker just exited.
*) The "worker_aio_requests" directive.
The default value is 32 AIO simultaneous requests per worker. Previously
they were hardcoded to 1024, and it was too large, since Linux allocated
them early on io_setup(), but not on request itself. So with default value
of /proc/sys/fs/aio-max-nr equal to 65536 only 64 worker processes could
be run simultaneously. 32 AIO requests are enough for modern disks even if
server runs only 1 worker.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 30 Sep 2011 14:12:53 +0000 |
parents | 159b58f9c0bd |
children | e99e429947f9 |
comparison
equal
deleted
inserted
replaced
4163:b8b4766fec8c | 4164:c48662671609 |
---|---|
84 #endif | 84 #endif |
85 | 85 |
86 | 86 |
87 typedef struct { | 87 typedef struct { |
88 ngx_uint_t events; | 88 ngx_uint_t events; |
89 ngx_uint_t aio_requests; | |
89 } ngx_epoll_conf_t; | 90 } ngx_epoll_conf_t; |
90 | 91 |
91 | 92 |
92 static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer); | 93 static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer); |
93 static void ngx_epoll_done(ngx_cycle_t *cycle); | 94 static void ngx_epoll_done(ngx_cycle_t *cycle); |
129 { ngx_string("epoll_events"), | 130 { ngx_string("epoll_events"), |
130 NGX_EVENT_CONF|NGX_CONF_TAKE1, | 131 NGX_EVENT_CONF|NGX_CONF_TAKE1, |
131 ngx_conf_set_num_slot, | 132 ngx_conf_set_num_slot, |
132 0, | 133 0, |
133 offsetof(ngx_epoll_conf_t, events), | 134 offsetof(ngx_epoll_conf_t, events), |
135 NULL }, | |
136 | |
137 { ngx_string("worker_aio_requests"), | |
138 NGX_EVENT_CONF|NGX_CONF_TAKE1, | |
139 ngx_conf_set_num_slot, | |
140 0, | |
141 offsetof(ngx_epoll_conf_t, aio_requests), | |
134 NULL }, | 142 NULL }, |
135 | 143 |
136 ngx_null_command | 144 ngx_null_command |
137 }; | 145 }; |
138 | 146 |
182 * Also we do not use eventfd() in glibc, because glibc supports it | 190 * Also we do not use eventfd() in glibc, because glibc supports it |
183 * since 2.8 version and glibc maps two syscalls eventfd() and eventfd2() | 191 * since 2.8 version and glibc maps two syscalls eventfd() and eventfd2() |
184 * into single eventfd() function with different number of parameters. | 192 * into single eventfd() function with different number of parameters. |
185 */ | 193 */ |
186 | 194 |
187 static long | 195 static int |
188 io_setup(u_int nr_reqs, aio_context_t *ctx) | 196 io_setup(u_int nr_reqs, aio_context_t *ctx) |
189 { | 197 { |
190 return syscall(SYS_io_setup, nr_reqs, ctx); | 198 return syscall(SYS_io_setup, nr_reqs, ctx); |
191 } | 199 } |
192 | 200 |
196 { | 204 { |
197 return syscall(SYS_io_destroy, ctx); | 205 return syscall(SYS_io_destroy, ctx); |
198 } | 206 } |
199 | 207 |
200 | 208 |
201 static long | 209 static int |
202 io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events, | 210 io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events, |
203 struct timespec *tmo) | 211 struct timespec *tmo) |
204 { | 212 { |
205 return syscall(SYS_io_getevents, ctx, min_nr, nr, events, tmo); | 213 return syscall(SYS_io_getevents, ctx, min_nr, nr, events, tmo); |
214 } | |
215 | |
216 | |
217 static void | |
218 ngx_epoll_aio_init(ngx_cycle_t *cycle, ngx_epoll_conf_t *epcf) | |
219 { | |
220 int n; | |
221 struct epoll_event ee; | |
222 | |
223 ngx_eventfd = syscall(SYS_eventfd, 0); | |
224 | |
225 if (ngx_eventfd == -1) { | |
226 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
227 "eventfd() failed"); | |
228 ngx_file_aio = 0; | |
229 return; | |
230 } | |
231 | |
232 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
233 "eventfd: %d", ngx_eventfd); | |
234 | |
235 n = 1; | |
236 | |
237 if (ioctl(ngx_eventfd, FIONBIO, &n) == -1) { | |
238 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
239 "ioctl(eventfd, FIONBIO) failed"); | |
240 goto failed; | |
241 } | |
242 | |
243 if (io_setup(epcf->aio_requests, &ngx_aio_ctx) == -1) { | |
244 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
245 "io_setup() failed"); | |
246 goto failed; | |
247 } | |
248 | |
249 ngx_eventfd_event.data = &ngx_eventfd_conn; | |
250 ngx_eventfd_event.handler = ngx_epoll_eventfd_handler; | |
251 ngx_eventfd_event.log = cycle->log; | |
252 ngx_eventfd_event.active = 1; | |
253 ngx_eventfd_conn.fd = ngx_eventfd; | |
254 ngx_eventfd_conn.read = &ngx_eventfd_event; | |
255 ngx_eventfd_conn.log = cycle->log; | |
256 | |
257 ee.events = EPOLLIN|EPOLLET; | |
258 ee.data.ptr = &ngx_eventfd_conn; | |
259 | |
260 if (epoll_ctl(ep, EPOLL_CTL_ADD, ngx_eventfd, &ee) != -1) { | |
261 return; | |
262 } | |
263 | |
264 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
265 "epoll_ctl(EPOLL_CTL_ADD, eventfd) failed"); | |
266 | |
267 if (io_destroy(ngx_aio_ctx) == -1) { | |
268 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
269 "io_destroy() failed"); | |
270 } | |
271 | |
272 failed: | |
273 | |
274 if (close(ngx_eventfd) == -1) { | |
275 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
276 "eventfd close() failed"); | |
277 } | |
278 | |
279 ngx_eventfd = -1; | |
280 ngx_aio_ctx = 0; | |
281 ngx_file_aio = 0; | |
206 } | 282 } |
207 | 283 |
208 #endif | 284 #endif |
209 | 285 |
210 | 286 |
223 "epoll_create() failed"); | 299 "epoll_create() failed"); |
224 return NGX_ERROR; | 300 return NGX_ERROR; |
225 } | 301 } |
226 | 302 |
227 #if (NGX_HAVE_FILE_AIO) | 303 #if (NGX_HAVE_FILE_AIO) |
228 { | 304 |
229 int n; | 305 ngx_epoll_aio_init(cycle, epcf); |
230 struct epoll_event ee; | 306 |
231 | |
232 ngx_eventfd = syscall(SYS_eventfd, 0); | |
233 | |
234 if (ngx_eventfd == -1) { | |
235 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
236 "eventfd() failed"); | |
237 return NGX_ERROR; | |
238 } | |
239 | |
240 n = 1; | |
241 | |
242 if (ioctl(ngx_eventfd, FIONBIO, &n) == -1) { | |
243 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
244 "ioctl(eventfd, FIONBIO) failed"); | |
245 } | |
246 | |
247 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
248 "eventfd: %d", ngx_eventfd); | |
249 | |
250 n = io_setup(1024, &ngx_aio_ctx); | |
251 | |
252 if (n != 0) { | |
253 ngx_log_error(NGX_LOG_EMERG, cycle->log, -n, "io_setup() failed"); | |
254 return NGX_ERROR; | |
255 } | |
256 | |
257 ngx_eventfd_event.data = &ngx_eventfd_conn; | |
258 ngx_eventfd_event.handler = ngx_epoll_eventfd_handler; | |
259 ngx_eventfd_event.log = cycle->log; | |
260 ngx_eventfd_event.active = 1; | |
261 ngx_eventfd_conn.fd = ngx_eventfd; | |
262 ngx_eventfd_conn.read = &ngx_eventfd_event; | |
263 ngx_eventfd_conn.log = cycle->log; | |
264 | |
265 ee.events = EPOLLIN|EPOLLET; | |
266 ee.data.ptr = &ngx_eventfd_conn; | |
267 | |
268 if (epoll_ctl(ep, EPOLL_CTL_ADD, ngx_eventfd, &ee) == -1) { | |
269 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
270 "epoll_ctl(EPOLL_CTL_ADD, eventfd) failed"); | |
271 return NGX_ERROR; | |
272 } | |
273 } | |
274 #endif | 307 #endif |
275 } | 308 } |
276 | 309 |
277 if (nevents < epcf->events) { | 310 if (nevents < epcf->events) { |
278 if (event_list) { | 311 if (event_list) { |
314 | 347 |
315 ep = -1; | 348 ep = -1; |
316 | 349 |
317 #if (NGX_HAVE_FILE_AIO) | 350 #if (NGX_HAVE_FILE_AIO) |
318 | 351 |
319 if (io_destroy(ngx_aio_ctx) != 0) { | 352 if (ngx_eventfd != -1) { |
320 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 353 |
321 "io_destroy() failed"); | 354 if (io_destroy(ngx_aio_ctx) == -1) { |
355 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
356 "io_destroy() failed"); | |
357 } | |
358 | |
359 if (close(ngx_eventfd) == -1) { | |
360 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
361 "eventfd close() failed"); | |
362 } | |
363 | |
364 ngx_eventfd = -1; | |
322 } | 365 } |
323 | 366 |
324 ngx_aio_ctx = 0; | 367 ngx_aio_ctx = 0; |
325 | 368 |
326 #endif | 369 #endif |
665 #if (NGX_HAVE_FILE_AIO) | 708 #if (NGX_HAVE_FILE_AIO) |
666 | 709 |
667 static void | 710 static void |
668 ngx_epoll_eventfd_handler(ngx_event_t *ev) | 711 ngx_epoll_eventfd_handler(ngx_event_t *ev) |
669 { | 712 { |
670 int n; | 713 int n, events; |
671 long i, events; | 714 long i; |
672 uint64_t ready; | 715 uint64_t ready; |
673 ngx_err_t err; | 716 ngx_err_t err; |
674 ngx_event_t *e; | 717 ngx_event_t *e; |
675 ngx_event_aio_t *aio; | 718 ngx_event_aio_t *aio; |
676 struct io_event event[64]; | 719 struct io_event event[64]; |
736 | 779 |
737 if (events == 0) { | 780 if (events == 0) { |
738 return; | 781 return; |
739 } | 782 } |
740 | 783 |
741 /* events < 0 */ | 784 /* events == -1 */ |
742 ngx_log_error(NGX_LOG_ALERT, ev->log, -events, "io_getevents() failed"); | 785 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, |
786 "io_getevents() failed"); | |
743 return; | 787 return; |
744 } | 788 } |
745 } | 789 } |
746 | 790 |
747 #endif | 791 #endif |
756 if (epcf == NULL) { | 800 if (epcf == NULL) { |
757 return NULL; | 801 return NULL; |
758 } | 802 } |
759 | 803 |
760 epcf->events = NGX_CONF_UNSET; | 804 epcf->events = NGX_CONF_UNSET; |
805 epcf->aio_requests = NGX_CONF_UNSET; | |
761 | 806 |
762 return epcf; | 807 return epcf; |
763 } | 808 } |
764 | 809 |
765 | 810 |
767 ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf) | 812 ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf) |
768 { | 813 { |
769 ngx_epoll_conf_t *epcf = conf; | 814 ngx_epoll_conf_t *epcf = conf; |
770 | 815 |
771 ngx_conf_init_uint_value(epcf->events, 512); | 816 ngx_conf_init_uint_value(epcf->events, 512); |
817 ngx_conf_init_uint_value(epcf->aio_requests, 32); | |
772 | 818 |
773 return NGX_CONF_OK; | 819 return NGX_CONF_OK; |
774 } | 820 } |