Merge tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
[linux-2.6-microblaze.git] / fs / eventpoll.c
index 1e596e1..06f4c5a 100644 (file)
@@ -723,7 +723,7 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
         */
        call_rcu(&epi->rcu, epi_rcu_free);
 
-       atomic_long_dec(&ep->user->epoll_watches);
+       percpu_counter_dec(&ep->user->epoll_watches);
 
        return 0;
 }
@@ -1439,7 +1439,6 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
 {
        int error, pwake = 0;
        __poll_t revents;
-       long user_watches;
        struct epitem *epi;
        struct ep_pqueue epq;
        struct eventpoll *tep = NULL;
@@ -1449,11 +1448,15 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
 
        lockdep_assert_irqs_enabled();
 
-       user_watches = atomic_long_read(&ep->user->epoll_watches);
-       if (unlikely(user_watches >= max_user_watches))
+       if (unlikely(percpu_counter_compare(&ep->user->epoll_watches,
+                                           max_user_watches) >= 0))
                return -ENOSPC;
-       if (!(epi = kmem_cache_zalloc(epi_cache, GFP_KERNEL)))
+       percpu_counter_inc(&ep->user->epoll_watches);
+
+       if (!(epi = kmem_cache_zalloc(epi_cache, GFP_KERNEL))) {
+               percpu_counter_dec(&ep->user->epoll_watches);
                return -ENOMEM;
+       }
 
        /* Item initialization follow here ... */
        INIT_LIST_HEAD(&epi->rdllink);
@@ -1466,17 +1469,16 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
                mutex_lock_nested(&tep->mtx, 1);
        /* Add the current item to the list of active epoll hook for this file */
        if (unlikely(attach_epitem(tfile, epi) < 0)) {
-               kmem_cache_free(epi_cache, epi);
                if (tep)
                        mutex_unlock(&tep->mtx);
+               kmem_cache_free(epi_cache, epi);
+               percpu_counter_dec(&ep->user->epoll_watches);
                return -ENOMEM;
        }
 
        if (full_check && !tep)
                list_file(tfile);
 
-       atomic_long_inc(&ep->user->epoll_watches);
-
        /*
         * Add the current item to the RB tree. All RB tree operations are
         * protected by "mtx", and ep_insert() is called with "mtx" held.
@@ -1684,8 +1686,8 @@ static int ep_send_events(struct eventpoll *ep,
                if (!revents)
                        continue;
 
-               if (__put_user(revents, &events->events) ||
-                   __put_user(epi->event.data, &events->data)) {
+               events = epoll_put_uevent(revents, epi->event.data, events);
+               if (!events) {
                        list_add(&epi->rdllink, &txlist);
                        ep_pm_stay_awake(epi);
                        if (!res)
@@ -1693,7 +1695,6 @@ static int ep_send_events(struct eventpoll *ep,
                        break;
                }
                res++;
-               events++;
                if (epi->event.events & EPOLLONESHOT)
                        epi->event.events &= EP_PRIVATE_BITS;
                else if (!(epi->event.events & EPOLLET)) {