diff options
author | Robin Holt <holt@sgi.com> | 2011-01-12 20:00:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-13 11:03:12 -0500 |
commit | 52bd19f7691b2ea6433aef0ef94c08c57efd7e79 (patch) | |
tree | daaa39ee774fb4fe56ca61247eb930ed4f6e1ef1 /fs/eventpoll.c | |
parent | 65329bf46bf9ddc37845c9a6823a8e8022d305b9 (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.c | 20 |
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 */ |
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); |