]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/meta-ti-glsdk.git/blob - recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.9/0071-epoll-limit-paths.patch
u-boot: Fix config-Always-use-GNU-ld patch to work with dash
[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.2 / 3.2.9 / 0071-epoll-limit-paths.patch
1 From 203aa5260edca2ab1872ad8b08386d874f7132f3 Mon Sep 17 00:00:00 2001
2 From: Jason Baron <jbaron@redhat.com>
3 Date: Thu, 12 Jan 2012 17:17:43 -0800
4 Subject: [PATCH 71/73] epoll: limit paths
6 commit 28d82dc1c4edbc352129f97f4ca22624d1fe61de upstream.
8 The current epoll code can be tickled to run basically indefinitely in
9 both loop detection path check (on ep_insert()), and in the wakeup paths.
10 The programs that tickle this behavior set up deeply linked networks of
11 epoll file descriptors that cause the epoll algorithms to traverse them
12 indefinitely.  A couple of these sample programs have been previously
13 posted in this thread: https://lkml.org/lkml/2011/2/25/297.
15 To fix the loop detection path check algorithms, I simply keep track of
16 the epoll nodes that have been already visited.  Thus, the loop detection
17 becomes proportional to the number of epoll file descriptor and links.
18 This dramatically decreases the run-time of the loop check algorithm.  In
19 one diabolical case I tried it reduced the run-time from 15 mintues (all
20 in kernel time) to .3 seconds.
22 Fixing the wakeup paths could be done at wakeup time in a similar manner
23 by keeping track of nodes that have already been visited, but the
24 complexity is harder, since there can be multiple wakeups on different
25 cpus...Thus, I've opted to limit the number of possible wakeup paths when
26 the paths are created.
28 This is accomplished, by noting that the end file descriptor points that
29 are found during the loop detection pass (from the newly added link), are
30 actually the sources for wakeup events.  I keep a list of these file
31 descriptors and limit the number and length of these paths that emanate
32 from these 'source file descriptors'.  In the current implemetation I
33 allow 1000 paths of length 1, 500 of length 2, 100 of length 3, 50 of
34 length 4 and 10 of length 5.  Note that it is sufficient to check the
35 'source file descriptors' reachable from the newly added link, since no
36 other 'source file descriptors' will have newly added links.  This allows
37 us to check only the wakeup paths that may have gotten too long, and not
38 re-check all possible wakeup paths on the system.
40 In terms of the path limit selection, I think its first worth noting that
41 the most common case for epoll, is probably the model where you have 1
42 epoll file descriptor that is monitoring n number of 'source file
43 descriptors'.  In this case, each 'source file descriptor' has a 1 path of
44 length 1.  Thus, I believe that the limits I'm proposing are quite
45 reasonable and in fact may be too generous.  Thus, I'm hoping that the
46 proposed limits will not prevent any workloads that currently work to
47 fail.
49 In terms of locking, I have extended the use of the 'epmutex' to all
50 epoll_ctl add and remove operations.  Currently its only used in a subset
51 of the add paths.  I need to hold the epmutex, so that we can correctly
52 traverse a coherent graph, to check the number of paths.  I believe that
53 this additional locking is probably ok, since its in the setup/teardown
54 paths, and doesn't affect the running paths, but it certainly is going to
55 add some extra overhead.  Also, worth noting is that the epmuex was
56 recently added to the ep_ctl add operations in the initial path loop
57 detection code using the argument that it was not on a critical path.
59 Another thing to note here, is the length of epoll chains that is allowed.
60 Currently, eventpoll.c defines:
62 /* Maximum number of nesting allowed inside epoll sets */
63 #define EP_MAX_NESTS 4
65 This basically means that I am limited to a graph depth of 5 (EP_MAX_NESTS
66 + 1).  However, this limit is currently only enforced during the loop
67 check detection code, and only when the epoll file descriptors are added
68 in a certain order.  Thus, this limit is currently easily bypassed.  The
69 newly added check for wakeup paths, stricly limits the wakeup paths to a
70 length of 5, regardless of the order in which ep's are linked together.
71 Thus, a side-effect of the new code is a more consistent enforcement of
72 the graph depth.
74 Thus far, I've tested this, using the sample programs previously
75 mentioned, which now either return quickly or return -EINVAL.  I've also
76 testing using the piptest.c epoll tester, which showed no difference in
77 performance.  I've also created a number of different epoll networks and
78 tested that they behave as expectded.
80 I believe this solves the original diabolical test cases, while still
81 preserving the sane epoll nesting.
83 Signed-off-by: Jason Baron <jbaron@redhat.com>
84 Cc: Nelson Elhage <nelhage@ksplice.com>
85 Cc: Davide Libenzi <davidel@xmailserver.org>
86 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
87 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
88 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
89 ---
90  fs/eventpoll.c            |  234 ++++++++++++++++++++++++++++++++++++++++-----
91  include/linux/eventpoll.h |    1 +
92  include/linux/fs.h        |    1 +
93  3 files changed, 211 insertions(+), 25 deletions(-)
95 diff --git a/fs/eventpoll.c b/fs/eventpoll.c
96 index 12a772b..ea54cde 100644
97 --- a/fs/eventpoll.c
98 +++ b/fs/eventpoll.c
99 @@ -197,6 +197,12 @@ struct eventpoll {
100  
101         /* The user that created the eventpoll descriptor */
102         struct user_struct *user;
104 +       struct file *file;
106 +       /* used to optimize loop detection check */
107 +       int visited;
108 +       struct list_head visited_list_link;
109  };
110  
111  /* Wait structure used by the poll hooks */
112 @@ -255,6 +261,15 @@ static struct kmem_cache *epi_cache __read_mostly;
113  /* Slab cache used to allocate "struct eppoll_entry" */
114  static struct kmem_cache *pwq_cache __read_mostly;
115  
116 +/* Visited nodes during ep_loop_check(), so we can unset them when we finish */
117 +static LIST_HEAD(visited_list);
119 +/*
120 + * List of files with newly added links, where we may need to limit the number
121 + * of emanating paths. Protected by the epmutex.
122 + */
123 +static LIST_HEAD(tfile_check_list);
125  #ifdef CONFIG_SYSCTL
126  
127  #include <linux/sysctl.h>
128 @@ -276,6 +291,12 @@ ctl_table epoll_table[] = {
129  };
130  #endif /* CONFIG_SYSCTL */
131  
132 +static const struct file_operations eventpoll_fops;
134 +static inline int is_file_epoll(struct file *f)
135 +{
136 +       return f->f_op == &eventpoll_fops;
137 +}
138  
139  /* Setup the structure that is used as key for the RB tree */
140  static inline void ep_set_ffd(struct epoll_filefd *ffd,
141 @@ -728,12 +749,6 @@ static const struct file_operations eventpoll_fops = {
142         .llseek         = noop_llseek,
143  };
144  
145 -/* Fast test to see if the file is an eventpoll file */
146 -static inline int is_file_epoll(struct file *f)
147 -{
148 -       return f->f_op == &eventpoll_fops;
149 -}
151  /*
152   * This is called from eventpoll_release() to unlink files from the eventpoll
153   * interface. We need to have this facility to cleanup correctly files that are
154 @@ -954,6 +969,99 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
155         rb_insert_color(&epi->rbn, &ep->rbr);
156  }
157  
160 +#define PATH_ARR_SIZE 5
161 +/*
162 + * These are the number paths of length 1 to 5, that we are allowing to emanate
163 + * from a single file of interest. For example, we allow 1000 paths of length
164 + * 1, to emanate from each file of interest. This essentially represents the
165 + * potential wakeup paths, which need to be limited in order to avoid massive
166 + * uncontrolled wakeup storms. The common use case should be a single ep which
167 + * is connected to n file sources. In this case each file source has 1 path
168 + * of length 1. Thus, the numbers below should be more than sufficient. These
169 + * path limits are enforced during an EPOLL_CTL_ADD operation, since a modify
170 + * and delete can't add additional paths. Protected by the epmutex.
171 + */
172 +static const int path_limits[PATH_ARR_SIZE] = { 1000, 500, 100, 50, 10 };
173 +static int path_count[PATH_ARR_SIZE];
175 +static int path_count_inc(int nests)
176 +{
177 +       if (++path_count[nests] > path_limits[nests])
178 +               return -1;
179 +       return 0;
180 +}
182 +static void path_count_init(void)
183 +{
184 +       int i;
186 +       for (i = 0; i < PATH_ARR_SIZE; i++)
187 +               path_count[i] = 0;
188 +}
190 +static int reverse_path_check_proc(void *priv, void *cookie, int call_nests)
191 +{
192 +       int error = 0;
193 +       struct file *file = priv;
194 +       struct file *child_file;
195 +       struct epitem *epi;
197 +       list_for_each_entry(epi, &file->f_ep_links, fllink) {
198 +               child_file = epi->ep->file;
199 +               if (is_file_epoll(child_file)) {
200 +                       if (list_empty(&child_file->f_ep_links)) {
201 +                               if (path_count_inc(call_nests)) {
202 +                                       error = -1;
203 +                                       break;
204 +                               }
205 +                       } else {
206 +                               error = ep_call_nested(&poll_loop_ncalls,
207 +                                                       EP_MAX_NESTS,
208 +                                                       reverse_path_check_proc,
209 +                                                       child_file, child_file,
210 +                                                       current);
211 +                       }
212 +                       if (error != 0)
213 +                               break;
214 +               } else {
215 +                       printk(KERN_ERR "reverse_path_check_proc: "
216 +                               "file is not an ep!\n");
217 +               }
218 +       }
219 +       return error;
220 +}
222 +/**
223 + * reverse_path_check - The tfile_check_list is list of file *, which have
224 + *                      links that are proposed to be newly added. We need to
225 + *                      make sure that those added links don't add too many
226 + *                      paths such that we will spend all our time waking up
227 + *                      eventpoll objects.
228 + *
229 + * Returns: Returns zero if the proposed links don't create too many paths,
230 + *         -1 otherwise.
231 + */
232 +static int reverse_path_check(void)
233 +{
234 +       int length = 0;
235 +       int error = 0;
236 +       struct file *current_file;
238 +       /* let's call this for all tfiles */
239 +       list_for_each_entry(current_file, &tfile_check_list, f_tfile_llink) {
240 +               length++;
241 +               path_count_init();
242 +               error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
243 +                                       reverse_path_check_proc, current_file,
244 +                                       current_file, current);
245 +               if (error)
246 +                       break;
247 +       }
248 +       return error;
249 +}
251  /*
252   * Must be called with "mtx" held.
253   */
254 @@ -1015,6 +1123,11 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
255          */
256         ep_rbtree_insert(ep, epi);
257  
258 +       /* now check if we've created too many backpaths */
259 +       error = -EINVAL;
260 +       if (reverse_path_check())
261 +               goto error_remove_epi;
263         /* We have to drop the new item inside our item list to keep track of it */
264         spin_lock_irqsave(&ep->lock, flags);
265  
266 @@ -1039,6 +1152,14 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
267  
268         return 0;
269  
270 +error_remove_epi:
271 +       spin_lock(&tfile->f_lock);
272 +       if (ep_is_linked(&epi->fllink))
273 +               list_del_init(&epi->fllink);
274 +       spin_unlock(&tfile->f_lock);
276 +       rb_erase(&epi->rbn, &ep->rbr);
278  error_unregister:
279         ep_unregister_pollwait(ep, epi);
280  
281 @@ -1303,18 +1424,36 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
282         int error = 0;
283         struct file *file = priv;
284         struct eventpoll *ep = file->private_data;
285 +       struct eventpoll *ep_tovisit;
286         struct rb_node *rbp;
287         struct epitem *epi;
288  
289         mutex_lock_nested(&ep->mtx, call_nests + 1);
290 +       ep->visited = 1;
291 +       list_add(&ep->visited_list_link, &visited_list);
292         for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
293                 epi = rb_entry(rbp, struct epitem, rbn);
294                 if (unlikely(is_file_epoll(epi->ffd.file))) {
295 +                       ep_tovisit = epi->ffd.file->private_data;
296 +                       if (ep_tovisit->visited)
297 +                               continue;
298                         error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
299 -                                              ep_loop_check_proc, epi->ffd.file,
300 -                                              epi->ffd.file->private_data, current);
301 +                                       ep_loop_check_proc, epi->ffd.file,
302 +                                       ep_tovisit, current);
303                         if (error != 0)
304                                 break;
305 +               } else {
306 +                       /*
307 +                        * If we've reached a file that is not associated with
308 +                        * an ep, then we need to check if the newly added
309 +                        * links are going to add too many wakeup paths. We do
310 +                        * this by adding it to the tfile_check_list, if it's
311 +                        * not already there, and calling reverse_path_check()
312 +                        * during ep_insert().
313 +                        */
314 +                       if (list_empty(&epi->ffd.file->f_tfile_llink))
315 +                               list_add(&epi->ffd.file->f_tfile_llink,
316 +                                        &tfile_check_list);
317                 }
318         }
319         mutex_unlock(&ep->mtx);
320 @@ -1335,8 +1474,31 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
321   */
322  static int ep_loop_check(struct eventpoll *ep, struct file *file)
323  {
324 -       return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
325 +       int ret;
326 +       struct eventpoll *ep_cur, *ep_next;
328 +       ret = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
329                               ep_loop_check_proc, file, ep, current);
330 +       /* clear visited list */
331 +       list_for_each_entry_safe(ep_cur, ep_next, &visited_list,
332 +                                                       visited_list_link) {
333 +               ep_cur->visited = 0;
334 +               list_del(&ep_cur->visited_list_link);
335 +       }
336 +       return ret;
337 +}
339 +static void clear_tfile_check_list(void)
340 +{
341 +       struct file *file;
343 +       /* first clear the tfile_check_list */
344 +       while (!list_empty(&tfile_check_list)) {
345 +               file = list_first_entry(&tfile_check_list, struct file,
346 +                                       f_tfile_llink);
347 +               list_del_init(&file->f_tfile_llink);
348 +       }
349 +       INIT_LIST_HEAD(&tfile_check_list);
350  }
351  
352  /*
353 @@ -1344,8 +1506,9 @@ static int ep_loop_check(struct eventpoll *ep, struct file *file)
354   */
355  SYSCALL_DEFINE1(epoll_create1, int, flags)
356  {
357 -       int error;
358 +       int error, fd;
359         struct eventpoll *ep = NULL;
360 +       struct file *file;
361  
362         /* Check the EPOLL_* constant for consistency.  */
363         BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC);
364 @@ -1362,11 +1525,25 @@ SYSCALL_DEFINE1(epoll_create1, int, flags)
365          * Creates all the items needed to setup an eventpoll file. That is,
366          * a file structure and a free file descriptor.
367          */
368 -       error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
369 +       fd = get_unused_fd_flags(O_RDWR | (flags & O_CLOEXEC));
370 +       if (fd < 0) {
371 +               error = fd;
372 +               goto out_free_ep;
373 +       }
374 +       file = anon_inode_getfile("[eventpoll]", &eventpoll_fops, ep,
375                                  O_RDWR | (flags & O_CLOEXEC));
376 -       if (error < 0)
377 -               ep_free(ep);
379 +       if (IS_ERR(file)) {
380 +               error = PTR_ERR(file);
381 +               goto out_free_fd;
382 +       }
383 +       fd_install(fd, file);
384 +       ep->file = file;
385 +       return fd;
387 +out_free_fd:
388 +       put_unused_fd(fd);
389 +out_free_ep:
390 +       ep_free(ep);
391         return error;
392  }
393  
394 @@ -1432,21 +1609,27 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
395         /*
396          * When we insert an epoll file descriptor, inside another epoll file
397          * descriptor, there is the change of creating closed loops, which are
398 -        * better be handled here, than in more critical paths.
399 +        * better be handled here, than in more critical paths. While we are
400 +        * checking for loops we also determine the list of files reachable
401 +        * and hang them on the tfile_check_list, so we can check that we
402 +        * haven't created too many possible wakeup paths.
403          *
404 -        * We hold epmutex across the loop check and the insert in this case, in
405 -        * order to prevent two separate inserts from racing and each doing the
406 -        * insert "at the same time" such that ep_loop_check passes on both
407 -        * before either one does the insert, thereby creating a cycle.
408 +        * We need to hold the epmutex across both ep_insert and ep_remove
409 +        * b/c we want to make sure we are looking at a coherent view of
410 +        * epoll network.
411          */
412 -       if (unlikely(is_file_epoll(tfile) && op == EPOLL_CTL_ADD)) {
413 +       if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) {
414                 mutex_lock(&epmutex);
415                 did_lock_epmutex = 1;
416 -               error = -ELOOP;
417 -               if (ep_loop_check(ep, tfile) != 0)
418 -                       goto error_tgt_fput;
419         }
421 +       if (op == EPOLL_CTL_ADD) {
422 +               if (is_file_epoll(tfile)) {
423 +                       error = -ELOOP;
424 +                       if (ep_loop_check(ep, tfile) != 0)
425 +                               goto error_tgt_fput;
426 +               } else
427 +                       list_add(&tfile->f_tfile_llink, &tfile_check_list);
428 +       }
429  
430         mutex_lock_nested(&ep->mtx, 0);
431  
432 @@ -1465,6 +1648,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
433                         error = ep_insert(ep, &epds, tfile, fd);
434                 } else
435                         error = -EEXIST;
436 +               clear_tfile_check_list();
437                 break;
438         case EPOLL_CTL_DEL:
439                 if (epi)
440 @@ -1483,7 +1667,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
441         mutex_unlock(&ep->mtx);
442  
443  error_tgt_fput:
444 -       if (unlikely(did_lock_epmutex))
445 +       if (did_lock_epmutex)
446                 mutex_unlock(&epmutex);
447  
448         fput(tfile);
449 diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
450 index f362733..657ab55 100644
451 --- a/include/linux/eventpoll.h
452 +++ b/include/linux/eventpoll.h
453 @@ -61,6 +61,7 @@ struct file;
454  static inline void eventpoll_init_file(struct file *file)
455  {
456         INIT_LIST_HEAD(&file->f_ep_links);
457 +       INIT_LIST_HEAD(&file->f_tfile_llink);
458  }
459  
460  
461 diff --git a/include/linux/fs.h b/include/linux/fs.h
462 index e0bc4ff..10b2288 100644
463 --- a/include/linux/fs.h
464 +++ b/include/linux/fs.h
465 @@ -1001,6 +1001,7 @@ struct file {
466  #ifdef CONFIG_EPOLL
467         /* Used by fs/eventpoll.c to link all the hooks to this file */
468         struct list_head        f_ep_links;
469 +       struct list_head        f_tfile_llink;
470  #endif /* #ifdef CONFIG_EPOLL */
471         struct address_space    *f_mapping;
472  #ifdef CONFIG_DEBUG_WRITECOUNT
473 -- 
474 1.7.7.4