aboutsummaryrefslogtreecommitdiffstats
path: root/fs/eventpoll.c
diff options
context:
space:
mode:
authorRobin Holt <holt@sgi.com>2011-01-12 20:00:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 11:03:12 -0500
commit52bd19f7691b2ea6433aef0ef94c08c57efd7e79 (patch)
treedaaa39ee774fb4fe56ca61247eb930ed4f6e1ef1 /fs/eventpoll.c
parent65329bf46bf9ddc37845c9a6823a8e8022d305b9 (diff)
epoll: convert max_user_watches to long
On a 16TB machine, max_user_watches has an integer overflow. Convert it to use a long and handle the associated fallout. Signed-off-by: Robin Holt <holt@sgi.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Acked-by: Davide Libenzi <davidel@xmailserver.org> Cc: Pekka Enberg <penberg@cs.helsinki.fi> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/eventpoll.c')
-rw-r--r--fs/eventpoll.c20
1 files changed, 12 insertions, 8 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 */
220static int max_user_watches __read_mostly; 220static 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
243static int zero; 243static long zero;
244static long long_max = LONG_MAX;
244 245
245ctl_table epoll_table[] = { 246ctl_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);