From: Arnaldo Carvalho de Melo <[email protected]>

As noticed by receiving a POLLHUP for its pollfd entry.

Cc: Adrian Hunter <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jean Pihet <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
 tools/perf/util/evlist.c | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 6d2499cfd789..fdb755f6e299 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -25,6 +25,8 @@
 #include <linux/bitops.h>
 #include <linux/hash.h>
 
+static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
+
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
 #define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
 
@@ -424,14 +426,35 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
        return 0;
 }
 
+static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int 
idx)
+{
+       int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP);
+       /*
+        * Save the idx so that when we filter out fds POLLHUP'ed we can
+        * close the associated evlist->mmap[] entry.
+        */
+       if (pos >= 0)
+               evlist->pollfd.priv[pos] = idx;
+
+       return pos;
+}
+
 int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
 {
-       return fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP);
+       return __perf_evlist__add_pollfd(evlist, fd, -1);
+}
+
+static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd)
+{
+       struct perf_evlist *evlist = container_of(fda, struct perf_evlist, 
pollfd);
+
+       perf_evlist__mmap_put(evlist, fda->priv[fd]);
 }
 
 int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short 
revents_and_mask)
 {
-       return fdarray__filter(&evlist->pollfd, revents_and_mask, NULL);
+       return fdarray__filter(&evlist->pollfd, revents_and_mask,
+                              perf_evlist__munmap_filtered);
 }
 
 int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
@@ -751,7 +774,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist 
*evlist, int idx,
                        perf_evlist__mmap_get(evlist, idx);
                }
 
-               if (perf_evlist__add_pollfd(evlist, fd) < 0) {
+               if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
                        perf_evlist__mmap_put(evlist, idx);
                        return -1;
                }
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to