diff options
-rw-r--r-- | fs/eventpoll.c | 20 | ||||
-rw-r--r-- | include/linux/sched.h | 2 |
2 files changed, 13 insertions, 9 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 8cf07242067d..cc8a9b7d6064 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -217,7 +217,7 @@ struct ep_send_events_data { | |||
217 | * Configuration options available inside /proc/sys/fs/epoll/ | 217 | * Configuration options available inside /proc/sys/fs/epoll/ |
218 | */ | 218 | */ |
219 | /* Maximum number of epoll watched descriptors, per user */ | 219 | /* Maximum number of epoll watched descriptors, per user */ |
220 | static int max_user_watches __read_mostly; | 220 | static long max_user_watches __read_mostly; |
221 | 221 | ||
222 | /* | 222 | /* |
223 | * This mutex is used to serialize ep_free() and eventpoll_release_file(). | 223 | * This mutex is used to serialize ep_free() and eventpoll_release_file(). |
@@ -240,16 +240,18 @@ static struct kmem_cache *pwq_cache __read_mostly; | |||
240 | 240 | ||
241 | #include <linux/sysctl.h> | 241 | #include <linux/sysctl.h> |
242 | 242 | ||
243 | static int zero; | 243 | static long zero; |
244 | static long long_max = LONG_MAX; | ||
244 | 245 | ||
245 | ctl_table epoll_table[] = { | 246 | ctl_table epoll_table[] = { |
246 | { | 247 | { |
247 | .procname = "max_user_watches", | 248 | .procname = "max_user_watches", |
248 | .data = &max_user_watches, | 249 | .data = &max_user_watches, |
249 | .maxlen = sizeof(int), | 250 | .maxlen = sizeof(max_user_watches), |
250 | .mode = 0644, | 251 | .mode = 0644, |
251 | .proc_handler = proc_dointvec_minmax, | 252 | .proc_handler = proc_doulongvec_minmax, |
252 | .extra1 = &zero, | 253 | .extra1 = &zero, |
254 | .extra2 = &long_max, | ||
253 | }, | 255 | }, |
254 | { } | 256 | { } |
255 | }; | 257 | }; |
@@ -561,7 +563,7 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi) | |||
561 | /* At this point it is safe to free the eventpoll item */ | 563 | /* At this point it is safe to free the eventpoll item */ |
562 | kmem_cache_free(epi_cache, epi); | 564 | kmem_cache_free(epi_cache, epi); |
563 | 565 | ||
564 | atomic_dec(&ep->user->epoll_watches); | 566 | atomic_long_dec(&ep->user->epoll_watches); |
565 | 567 | ||
566 | return 0; | 568 | return 0; |
567 | } | 569 | } |
@@ -898,11 +900,12 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, | |||
898 | { | 900 | { |
899 | int error, revents, pwake = 0; | 901 | int error, revents, pwake = 0; |
900 | unsigned long flags; | 902 | unsigned long flags; |
903 | long user_watches; | ||
901 | struct epitem *epi; | 904 | struct epitem *epi; |
902 | struct ep_pqueue epq; | 905 | struct ep_pqueue epq; |
903 | 906 | ||
904 | if (unlikely(atomic_read(&ep->user->epoll_watches) >= | 907 | user_watches = atomic_long_read(&ep->user->epoll_watches); |
905 | max_user_watches)) | 908 | if (unlikely(user_watches >= max_user_watches)) |
906 | return -ENOSPC; | 909 | return -ENOSPC; |
907 | if (!(epi = kmem_cache_alloc(epi_cache, GFP_KERNEL))) | 910 | if (!(epi = kmem_cache_alloc(epi_cache, GFP_KERNEL))) |
908 | return -ENOMEM; | 911 | return -ENOMEM; |
@@ -966,7 +969,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, | |||
966 | 969 | ||
967 | spin_unlock_irqrestore(&ep->lock, flags); | 970 | spin_unlock_irqrestore(&ep->lock, flags); |
968 | 971 | ||
969 | atomic_inc(&ep->user->epoll_watches); | 972 | atomic_long_inc(&ep->user->epoll_watches); |
970 | 973 | ||
971 | /* We have to call this outside the lock */ | 974 | /* We have to call this outside the lock */ |
972 | if (pwake) | 975 | if (pwake) |
@@ -1426,6 +1429,7 @@ static int __init eventpoll_init(void) | |||
1426 | */ | 1429 | */ |
1427 | max_user_watches = (((si.totalram - si.totalhigh) / 25) << PAGE_SHIFT) / | 1430 | max_user_watches = (((si.totalram - si.totalhigh) / 25) << PAGE_SHIFT) / |
1428 | EP_ITEM_COST; | 1431 | EP_ITEM_COST; |
1432 | BUG_ON(max_user_watches < 0); | ||
1429 | 1433 | ||
1430 | /* Initialize the structure used to perform safe poll wait head wake ups */ | 1434 | /* Initialize the structure used to perform safe poll wait head wake ups */ |
1431 | ep_nested_calls_init(&poll_safewake_ncalls); | 1435 | ep_nested_calls_init(&poll_safewake_ncalls); |
diff --git a/include/linux/sched.h b/include/linux/sched.h index abc527aa8550..96e23215e276 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -683,7 +683,7 @@ struct user_struct { | |||
683 | atomic_t fanotify_listeners; | 683 | atomic_t fanotify_listeners; |
684 | #endif | 684 | #endif |
685 | #ifdef CONFIG_EPOLL | 685 | #ifdef CONFIG_EPOLL |
686 | atomic_t epoll_watches; /* The number of file descriptors currently watched */ | 686 | atomic_long_t epoll_watches; /* The number of file descriptors currently watched */ |
687 | #endif | 687 | #endif |
688 | #ifdef CONFIG_POSIX_MQUEUE | 688 | #ifdef CONFIG_POSIX_MQUEUE |
689 | /* protected by mq_lock */ | 689 | /* protected by mq_lock */ |