]> git.pld-linux.org Git - packages/autofs.git/blame - autofs-5.0.4-fix-select-fd-limit.patch
- updated to 5.0.5, nfy.
[packages/autofs.git] / autofs-5.0.4-fix-select-fd-limit.patch
CommitLineData
e5fd101c
PS
1autofs-5.0.4 - fix select fd limit
2
3From: Ian Kent <raven@themaw.net>
4
5Using a large number of direct mounts causes autofs to hang. This is
6because select(2) is limited to 1024 file handles (usually). To resolve
7this we need to convert calls to select(2) to use poll(2).
8---
9
10 CHANGELOG | 1 +
11 daemon/spawn.c | 19 ++++++------
12 lib/rpc_subs.c | 32 ++++++++++++++------
13 modules/lookup_program.c | 74 +++++++++++++++++++++++++++-------------------
14 4 files changed, 78 insertions(+), 48 deletions(-)
15
16
17diff --git a/CHANGELOG b/CHANGELOG
18index 43f3205..0fb7db5 100644
19--- a/CHANGELOG
20+++ b/CHANGELOG
21@@ -4,6 +4,7 @@
22 - fix nested submount expire deadlock.
23 - fix negative caching for non-existent map keys.
24 - use CLOEXEC flag.
25+- fix select(2) fd limit.
26
27 4/11/2008 autofs-5.0.4
28 -----------------------
29diff --git a/daemon/spawn.c b/daemon/spawn.c
30index 4ddf46f..e02d926 100644
31--- a/daemon/spawn.c
32+++ b/daemon/spawn.c
33@@ -21,6 +21,7 @@
34 #include <sys/types.h>
35 #include <dirent.h>
36 #include <time.h>
37+#include <poll.h>
38 #include <sys/wait.h>
39 #include <sys/stat.h>
40 #include <sys/mount.h>
41@@ -89,21 +90,21 @@ void reset_signals(void)
42
43 static int timed_read(int pipe, char *buf, size_t len, int time)
44 {
45- struct timeval timeout = { 0, 0 };
46- struct timeval *tout = NULL;
47- fd_set wset, rset;
48+ struct pollfd pfd[1];
49+ int timeout = time;
50 int ret;
51
52- FD_ZERO(&rset);
53- FD_SET(pipe, &rset);
54- wset = rset;
55+ pfd[0].fd = pipe;
56+ pfd[0].events = POLLIN;
57
58 if (time != -1) {
59- timeout.tv_sec = time;
60- tout = &timeout;
61+ if (time >= (INT_MAX - 1)/1000)
62+ timeout = INT_MAX - 1;
63+ else
64+ timeout = time * 1000;
65 }
66
67- ret = select(pipe + 1, &rset, &wset, NULL, tout);
68+ ret = poll(pfd, 1, timeout);
69 if (ret <= 0) {
70 if (ret == 0)
71 ret = -ETIMEDOUT;
72diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c
73index 9ac3657..7b347a7 100644
74--- a/lib/rpc_subs.c
75+++ b/lib/rpc_subs.c
76@@ -31,6 +31,7 @@
77 #include <sys/ioctl.h>
78 #include <ctype.h>
79 #include <pthread.h>
80+#include <poll.h>
81
82 #include "mount.h"
83 #include "rpc_subs.h"
84@@ -197,14 +198,15 @@ void rpc_destroy_udp_client(struct conn_info *info)
85 /*
86 * Perform a non-blocking connect on the socket fd.
87 *
88- * tout contains the timeout. It will be modified to contain the time
89- * remaining (i.e. time provided - time elasped).
90+ * The input struct timeval always has tv_nsec set to zero,
91+ * we only ever use tv_sec for timeouts.
92 */
93 static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
94 {
95+ struct pollfd pfd[1];
96+ int timeout = tout->tv_sec;
97 int flags, ret;
98 socklen_t len;
99- fd_set wset, rset;
100
101 flags = fcntl(fd, F_GETFL, 0);
102 if (flags < 0)
103@@ -229,12 +231,10 @@ static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
104 if (ret == 0)
105 goto done;
106
107- /* now wait */
108- FD_ZERO(&rset);
109- FD_SET(fd, &rset);
110- wset = rset;
111+ pfd[0].fd = fd;
112+ pfd[0].events = POLLOUT;
113
114- ret = select(fd + 1, &rset, &wset, NULL, tout);
115+ ret = poll(pfd, 1, timeout);
116 if (ret <= 0) {
117 if (ret == 0)
118 ret = -ETIMEDOUT;
119@@ -243,13 +243,27 @@ static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
120 goto done;
121 }
122
123- if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
124+ if (pfd[0].revents) {
125 int status;
126
127 len = sizeof(ret);
128 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &len);
129 if (status < 0) {
130+ char buf[MAX_ERR_BUF + 1];
131+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
132+
133+ /*
134+ * We assume getsockopt amounts to a read on the
135+ * descriptor and gives us the errno we need for
136+ * the POLLERR revent case.
137+ */
138 ret = -errno;
139+
140+ /* Unexpected case, log it so we know we got caught */
141+ if (pfd[0].revents & POLLNVAL)
142+ logerr("unexpected poll(2) error on connect:"
143+ " %s", estr);
144+
145 goto done;
146 }
147
148diff --git a/modules/lookup_program.c b/modules/lookup_program.c
149index 6f4e2a3..f62d3ef 100644
150--- a/modules/lookup_program.c
151+++ b/modules/lookup_program.c
152@@ -24,6 +24,7 @@
153 #include <sys/times.h>
154 #include <sys/types.h>
155 #include <sys/wait.h>
156+#include <poll.h>
157
158 #define MODULE_LOOKUP
159 #include "automount.h"
160@@ -113,14 +114,12 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
161 char errbuf[1024], *errp;
162 char ch;
163 int pipefd[2], epipefd[2];
164+ struct pollfd pfd[2];
165 pid_t f;
166- int files_left;
167 int status;
168- fd_set readfds, ourfds;
169 enum state { st_space, st_map, st_done } state;
170 int quoted = 0;
171 int ret = 1;
172- int max_fd;
173 int distance;
174 int alloci = 1;
175
176@@ -253,30 +252,39 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
177 errp = errbuf;
178 state = st_space;
179
180- FD_ZERO(&ourfds);
181- FD_SET(pipefd[0], &ourfds);
182- FD_SET(epipefd[0], &ourfds);
183+ pfd[0].fd = pipefd[0];
184+ pfd[0].events = POLLIN;
185+ pfd[1].fd = epipefd[0];
186+ pfd[1].events = POLLIN;
187
188- max_fd = pipefd[0] > epipefd[0] ? pipefd[0] : epipefd[0];
189+ while (1) {
190+ int bytes;
191
192- files_left = 2;
193+ if (poll(pfd, 2, -1) < 0 && errno != EINTR)
194+ break;
195+
196+ if (pfd[0].fd == -1 && pfd[1].fd == -1)
197+ break;
198
199- while (files_left != 0) {
200- readfds = ourfds;
201- if (select(max_fd + 1, &readfds, NULL, NULL, NULL) < 0 && errno != EINTR)
202+ if ((pfd[0].revents & (POLLIN|POLLHUP)) == POLLHUP &&
203+ (pfd[1].revents & (POLLIN|POLLHUP)) == POLLHUP)
204 break;
205
206 /* Parse maps from stdout */
207- if (FD_ISSET(pipefd[0], &readfds)) {
208- if (read(pipefd[0], &ch, 1) < 1) {
209- FD_CLR(pipefd[0], &ourfds);
210- files_left--;
211+ if (pfd[0].revents) {
212+cont:
213+ bytes = read(pipefd[0], &ch, 1);
214+ if (bytes == 0)
215+ goto next;
216+ else if (bytes < 0) {
217+ pfd[0].fd = -1;
218 state = st_done;
219+ goto next;
220 }
221
222 if (!quoted && ch == '\\') {
223 quoted = 1;
224- continue;
225+ goto cont;
226 }
227
228 switch (state) {
229@@ -333,26 +341,32 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
230 /* Eat characters till there's no more output */
231 break;
232 }
233+ goto cont;
234 }
235 quoted = 0;
236-
237+next:
238 /* Deal with stderr */
239- if (FD_ISSET(epipefd[0], &readfds)) {
240- if (read(epipefd[0], &ch, 1) < 1) {
241- FD_CLR(epipefd[0], &ourfds);
242- files_left--;
243- } else if (ch == '\n') {
244- *errp = '\0';
245- if (errbuf[0])
246- logmsg(">> %s", errbuf);
247- errp = errbuf;
248- } else {
249- if (errp >= &errbuf[1023]) {
250+ if (pfd[1].revents) {
251+ while (1) {
252+ bytes = read(epipefd[0], &ch, 1);
253+ if (bytes == 0)
254+ break;
255+ else if (bytes < 0) {
256+ pfd[1].fd = -1;
257+ break;
258+ } else if (ch == '\n') {
259 *errp = '\0';
260- logmsg(">> %s", errbuf);
261+ if (errbuf[0])
262+ logmsg(">> %s", errbuf);
263 errp = errbuf;
264+ } else {
265+ if (errp >= &errbuf[1023]) {
266+ *errp = '\0';
267+ logmsg(">> %s", errbuf);
268+ errp = errbuf;
269+ }
270+ *(errp++) = ch;
271 }
272- *(errp++) = ch;
273 }
274 }
275 }
This page took 0.082263 seconds and 4 git commands to generate.