Mercurial > hg > nginx
annotate src/os/unix/ngx_linux_aio_read.c @ 5356:acd51b0f6fd4
Disable symlinks: use O_PATH to open path components.
It was introduced in Linux 2.6.39, glibc 2.14 and allows to obtain
file descriptors without actually opening files. Thus made it possible
to traverse path with openat() syscalls without the need to have read
permissions for path components. It is effectively emulates O_SEARCH
which is missing on Linux.
O_PATH is used in combination with O_RDONLY. The last one is ignored
if O_PATH is used, but it allows nginx to not fail when it was built on
modern system (i.e. glibc 2.14+) and run with a kernel older than 2.6.39.
Then O_PATH is unknown to the kernel and ignored, while O_RDONLY is used.
Sadly, fstat() is not working with O_PATH descriptors till Linux 3.6.
As a workaround we fallback to fstatat() with the AT_EMPTY_PATH flag
that was introduced at the same time as O_PATH.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Mon, 02 Sep 2013 08:07:59 +0400 |
parents | d620f497c50f |
children | ccad84a174e0 |
rev | line source |
---|---|
3052 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
3052 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_event.h> | |
11 | |
12 | |
13 extern int ngx_eventfd; | |
14 extern aio_context_t ngx_aio_ctx; | |
15 | |
16 | |
17 static void ngx_file_aio_event_handler(ngx_event_t *ev); | |
18 | |
19 | |
4129
6903dac6ad19
Fixing Linux AIO syscalls return value handling:
Igor Sysoev <igor@sysoev.ru>
parents:
4076
diff
changeset
|
20 static int |
3052 | 21 io_submit(aio_context_t ctx, long n, struct iocb **paiocb) |
22 { | |
23 return syscall(SYS_io_submit, ctx, n, paiocb); | |
24 } | |
25 | |
26 | |
27 ssize_t | |
28 ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset, | |
29 ngx_pool_t *pool) | |
30 { | |
4129
6903dac6ad19
Fixing Linux AIO syscalls return value handling:
Igor Sysoev <igor@sysoev.ru>
parents:
4076
diff
changeset
|
31 ngx_err_t err; |
3294
04cfc09b8b8d
export aio presence knowledge to prevent using "aio sendfile",
Igor Sysoev <igor@sysoev.ru>
parents:
3052
diff
changeset
|
32 struct iocb *piocb[1]; |
04cfc09b8b8d
export aio presence knowledge to prevent using "aio sendfile",
Igor Sysoev <igor@sysoev.ru>
parents:
3052
diff
changeset
|
33 ngx_event_t *ev; |
04cfc09b8b8d
export aio presence knowledge to prevent using "aio sendfile",
Igor Sysoev <igor@sysoev.ru>
parents:
3052
diff
changeset
|
34 ngx_event_aio_t *aio; |
3052 | 35 |
3294
04cfc09b8b8d
export aio presence knowledge to prevent using "aio sendfile",
Igor Sysoev <igor@sysoev.ru>
parents:
3052
diff
changeset
|
36 if (!ngx_file_aio) { |
3052 | 37 return ngx_read_file(file, buf, size, offset); |
38 } | |
39 | |
40 aio = file->aio; | |
41 | |
42 if (aio == NULL) { | |
43 aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t)); | |
44 if (aio == NULL) { | |
45 return NGX_ERROR; | |
46 } | |
47 | |
48 aio->file = file; | |
49 aio->fd = file->fd; | |
50 aio->event.data = aio; | |
51 aio->event.ready = 1; | |
52 aio->event.log = file->log; | |
53 file->aio = aio; | |
54 } | |
55 | |
56 ev = &aio->event; | |
57 | |
58 if (!ev->ready) { | |
59 ngx_log_error(NGX_LOG_ALERT, file->log, 0, | |
60 "second aio post for \"%V\"", &file->name); | |
61 return NGX_AGAIN; | |
62 } | |
63 | |
64 ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, | |
65 "aio complete:%d @%O:%z %V", | |
66 ev->complete, offset, size, &file->name); | |
67 | |
68 if (ev->complete) { | |
69 ev->active = 0; | |
70 ev->complete = 0; | |
71 | |
72 if (aio->res >= 0) { | |
73 ngx_set_errno(0); | |
74 return aio->res; | |
75 } | |
76 | |
77 ngx_set_errno(-aio->res); | |
4076
37da005a5808
Bugfix: open_file_cache lost is_directio flag.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3777
diff
changeset
|
78 |
37da005a5808
Bugfix: open_file_cache lost is_directio flag.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3777
diff
changeset
|
79 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, |
37da005a5808
Bugfix: open_file_cache lost is_directio flag.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3777
diff
changeset
|
80 "aio read \"%s\" failed", file->name.data); |
37da005a5808
Bugfix: open_file_cache lost is_directio flag.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3777
diff
changeset
|
81 |
3052 | 82 return NGX_ERROR; |
83 } | |
84 | |
85 ngx_memzero(&aio->aiocb, sizeof(struct iocb)); | |
86 | |
87 aio->aiocb.aio_data = (uint64_t) (uintptr_t) ev; | |
88 aio->aiocb.aio_lio_opcode = IOCB_CMD_PREAD; | |
89 aio->aiocb.aio_fildes = file->fd; | |
90 aio->aiocb.aio_buf = (uint64_t) (uintptr_t) buf; | |
91 aio->aiocb.aio_nbytes = size; | |
92 aio->aiocb.aio_offset = offset; | |
93 aio->aiocb.aio_flags = IOCB_FLAG_RESFD; | |
94 aio->aiocb.aio_resfd = ngx_eventfd; | |
95 | |
96 ev->handler = ngx_file_aio_event_handler; | |
97 | |
98 piocb[0] = &aio->aiocb; | |
99 | |
4129
6903dac6ad19
Fixing Linux AIO syscalls return value handling:
Igor Sysoev <igor@sysoev.ru>
parents:
4076
diff
changeset
|
100 if (io_submit(ngx_aio_ctx, 1, piocb) == 1) { |
3777
cd04f652478c
update event flags after successful io_submit()
Igor Sysoev <igor@sysoev.ru>
parents:
3294
diff
changeset
|
101 ev->active = 1; |
cd04f652478c
update event flags after successful io_submit()
Igor Sysoev <igor@sysoev.ru>
parents:
3294
diff
changeset
|
102 ev->ready = 0; |
cd04f652478c
update event flags after successful io_submit()
Igor Sysoev <igor@sysoev.ru>
parents:
3294
diff
changeset
|
103 ev->complete = 0; |
cd04f652478c
update event flags after successful io_submit()
Igor Sysoev <igor@sysoev.ru>
parents:
3294
diff
changeset
|
104 |
3052 | 105 return NGX_AGAIN; |
106 } | |
107 | |
4129
6903dac6ad19
Fixing Linux AIO syscalls return value handling:
Igor Sysoev <igor@sysoev.ru>
parents:
4076
diff
changeset
|
108 err = ngx_errno; |
3052 | 109 |
4129
6903dac6ad19
Fixing Linux AIO syscalls return value handling:
Igor Sysoev <igor@sysoev.ru>
parents:
4076
diff
changeset
|
110 if (err == NGX_EAGAIN) { |
3052 | 111 return ngx_read_file(file, buf, size, offset); |
112 } | |
113 | |
4129
6903dac6ad19
Fixing Linux AIO syscalls return value handling:
Igor Sysoev <igor@sysoev.ru>
parents:
4076
diff
changeset
|
114 ngx_log_error(NGX_LOG_CRIT, file->log, err, |
3052 | 115 "io_submit(\"%V\") failed", &file->name); |
116 | |
4129
6903dac6ad19
Fixing Linux AIO syscalls return value handling:
Igor Sysoev <igor@sysoev.ru>
parents:
4076
diff
changeset
|
117 if (err == NGX_ENOSYS) { |
3294
04cfc09b8b8d
export aio presence knowledge to prevent using "aio sendfile",
Igor Sysoev <igor@sysoev.ru>
parents:
3052
diff
changeset
|
118 ngx_file_aio = 0; |
3052 | 119 return ngx_read_file(file, buf, size, offset); |
120 } | |
121 | |
122 return NGX_ERROR; | |
123 } | |
124 | |
125 | |
126 static void | |
127 ngx_file_aio_event_handler(ngx_event_t *ev) | |
128 { | |
129 ngx_event_aio_t *aio; | |
130 | |
131 aio = ev->data; | |
132 | |
133 ngx_log_debug2(NGX_LOG_DEBUG_CORE, ev->log, 0, | |
134 "aio event handler fd:%d %V", aio->fd, &aio->file->name); | |
135 | |
136 aio->handler(ev); | |
137 } |