]> git.pld-linux.org Git - packages/autofs.git/blob - 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
1 autofs-5.0.4 - fix select fd limit
2
3 From: Ian Kent <raven@themaw.net>
4
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).
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
17 diff --git a/CHANGELOG b/CHANGELOG
18 index 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  -----------------------
29 diff --git a/daemon/spawn.c b/daemon/spawn.c
30 index 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;
72 diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c
73 index 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  
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
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.055621 seconds and 3 git commands to generate.