1 autofs-5.0.4 - fix select fd limit
3 From: Ian Kent <raven@themaw.net>
5 Using a large number of direct mounts causes autofs to hang. This is
6 because select(2) is limited to 1024 file handles (usually). To resolve
7 this we need to convert calls to select(2) to use poll(2).
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(-)
17 diff --git a/CHANGELOG b/CHANGELOG
18 index 43f3205..0fb7db5 100644
22 - fix nested submount expire deadlock.
23 - fix negative caching for non-existent map keys.
25 +- fix select(2) fd limit.
27 4/11/2008 autofs-5.0.4
28 -----------------------
29 diff --git a/daemon/spawn.c b/daemon/spawn.c
30 index 4ddf46f..e02d926 100644
34 #include <sys/types.h>
40 #include <sys/mount.h>
41 @@ -89,21 +90,21 @@ void reset_signals(void)
43 static int timed_read(int pipe, char *buf, size_t len, int time)
45 - struct timeval timeout = { 0, 0 };
46 - struct timeval *tout = NULL;
48 + struct pollfd pfd[1];
53 - FD_SET(pipe, &rset);
56 + pfd[0].events = POLLIN;
59 - timeout.tv_sec = time;
61 + if (time >= (INT_MAX - 1)/1000)
62 + timeout = INT_MAX - 1;
64 + timeout = time * 1000;
67 - ret = select(pipe + 1, &rset, &wset, NULL, tout);
68 + ret = poll(pfd, 1, timeout);
72 diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c
73 index 9ac3657..7b347a7 100644
77 #include <sys/ioctl.h>
84 @@ -197,14 +198,15 @@ void rpc_destroy_udp_client(struct conn_info *info)
86 * Perform a non-blocking connect on the socket fd.
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.
93 static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
95 + struct pollfd pfd[1];
96 + int timeout = tout->tv_sec;
101 flags = fcntl(fd, F_GETFL, 0);
103 @@ -229,12 +231,10 @@ static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
112 + pfd[0].events = POLLOUT;
114 - ret = select(fd + 1, &rset, &wset, NULL, tout);
115 + ret = poll(pfd, 1, timeout);
119 @@ -243,13 +243,27 @@ static int connect_nb(int fd, struct sockaddr_in *addr, struct timeval *tout)
123 - if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
124 + if (pfd[0].revents) {
128 status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &len);
130 + char buf[MAX_ERR_BUF + 1];
131 + char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
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.
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:"
148 diff --git a/modules/lookup_program.c b/modules/lookup_program.c
149 index 6f4e2a3..f62d3ef 100644
150 --- a/modules/lookup_program.c
151 +++ b/modules/lookup_program.c
153 #include <sys/times.h>
154 #include <sys/types.h>
155 #include <sys/wait.h>
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;
163 int pipefd[2], epipefd[2];
164 + struct pollfd pfd[2];
168 - fd_set readfds, ourfds;
169 enum state { st_space, st_map, st_done } state;
176 @@ -253,30 +252,39 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
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;
188 - max_fd = pipefd[0] > epipefd[0] ? pipefd[0] : epipefd[0];
193 + if (poll(pfd, 2, -1) < 0 && errno != EINTR)
196 + if (pfd[0].fd == -1 && pfd[1].fd == -1)
199 - while (files_left != 0) {
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)
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);
211 + if (pfd[0].revents) {
213 + bytes = read(pipefd[0], &ch, 1);
216 + else if (bytes < 0) {
222 if (!quoted && ch == '\\') {
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 */
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);
243 - } else if (ch == '\n') {
246 - logmsg(">> %s", errbuf);
249 - if (errp >= &errbuf[1023]) {
250 + if (pfd[1].revents) {
252 + bytes = read(epipefd[0], &ch, 1);
255 + else if (bytes < 0) {
258 + } else if (ch == '\n') {
260 - logmsg(">> %s", errbuf);
262 + logmsg(">> %s", errbuf);
265 + if (errp >= &errbuf[1023]) {
267 + logmsg(">> %s", errbuf);