diff options
| -rw-r--r-- | fs/eventpoll.c | 4 | ||||
| -rw-r--r-- | fs/signalfd.c | 11 | ||||
| -rw-r--r-- | include/asm-generic/poll.h | 2 | ||||
| -rw-r--r-- | include/linux/signalfd.h | 5 | ||||
| -rw-r--r-- | kernel/fork.c | 5 |
5 files changed, 25 insertions, 2 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index aabdfc38cf24..34bbfc6dd8dc 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
| @@ -842,6 +842,10 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k | |||
| 842 | struct epitem *epi = ep_item_from_wait(wait); | 842 | struct epitem *epi = ep_item_from_wait(wait); |
| 843 | struct eventpoll *ep = epi->ep; | 843 | struct eventpoll *ep = epi->ep; |
| 844 | 844 | ||
| 845 | /* the caller holds eppoll_entry->whead->lock */ | ||
| 846 | if ((unsigned long)key & POLLFREE) | ||
| 847 | list_del_init(&wait->task_list); | ||
| 848 | |||
| 845 | spin_lock_irqsave(&ep->lock, flags); | 849 | spin_lock_irqsave(&ep->lock, flags); |
| 846 | 850 | ||
| 847 | /* | 851 | /* |
diff --git a/fs/signalfd.c b/fs/signalfd.c index 492465b451dd..79c1eea98a3a 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c | |||
| @@ -30,6 +30,17 @@ | |||
| 30 | #include <linux/signalfd.h> | 30 | #include <linux/signalfd.h> |
| 31 | #include <linux/syscalls.h> | 31 | #include <linux/syscalls.h> |
| 32 | 32 | ||
| 33 | void signalfd_cleanup(struct sighand_struct *sighand) | ||
| 34 | { | ||
| 35 | wait_queue_head_t *wqh = &sighand->signalfd_wqh; | ||
| 36 | |||
| 37 | if (likely(!waitqueue_active(wqh))) | ||
| 38 | return; | ||
| 39 | |||
| 40 | /* wait_queue_t->func(POLLFREE) should do remove_wait_queue() */ | ||
| 41 | wake_up_poll(wqh, POLLHUP | POLLFREE); | ||
| 42 | } | ||
| 43 | |||
| 33 | struct signalfd_ctx { | 44 | struct signalfd_ctx { |
| 34 | sigset_t sigmask; | 45 | sigset_t sigmask; |
| 35 | }; | 46 | }; |
diff --git a/include/asm-generic/poll.h b/include/asm-generic/poll.h index 44bce836d350..9ce7f44aebd2 100644 --- a/include/asm-generic/poll.h +++ b/include/asm-generic/poll.h | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | #define POLLRDHUP 0x2000 | 28 | #define POLLRDHUP 0x2000 |
| 29 | #endif | 29 | #endif |
| 30 | 30 | ||
| 31 | #define POLLFREE 0x4000 /* currently only for epoll */ | ||
| 32 | |||
| 31 | struct pollfd { | 33 | struct pollfd { |
| 32 | int fd; | 34 | int fd; |
| 33 | short events; | 35 | short events; |
diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h index 3ff4961da9b5..247399b2979a 100644 --- a/include/linux/signalfd.h +++ b/include/linux/signalfd.h | |||
| @@ -61,13 +61,16 @@ static inline void signalfd_notify(struct task_struct *tsk, int sig) | |||
| 61 | wake_up(&tsk->sighand->signalfd_wqh); | 61 | wake_up(&tsk->sighand->signalfd_wqh); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | extern void signalfd_cleanup(struct sighand_struct *sighand); | ||
| 65 | |||
| 64 | #else /* CONFIG_SIGNALFD */ | 66 | #else /* CONFIG_SIGNALFD */ |
| 65 | 67 | ||
| 66 | static inline void signalfd_notify(struct task_struct *tsk, int sig) { } | 68 | static inline void signalfd_notify(struct task_struct *tsk, int sig) { } |
| 67 | 69 | ||
| 70 | static inline void signalfd_cleanup(struct sighand_struct *sighand) { } | ||
| 71 | |||
| 68 | #endif /* CONFIG_SIGNALFD */ | 72 | #endif /* CONFIG_SIGNALFD */ |
| 69 | 73 | ||
| 70 | #endif /* __KERNEL__ */ | 74 | #endif /* __KERNEL__ */ |
| 71 | 75 | ||
| 72 | #endif /* _LINUX_SIGNALFD_H */ | 76 | #endif /* _LINUX_SIGNALFD_H */ |
| 73 | |||
diff --git a/kernel/fork.c b/kernel/fork.c index b77fd559c78e..e2cd3e2a5ae8 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | #include <linux/user-return-notifier.h> | 66 | #include <linux/user-return-notifier.h> |
| 67 | #include <linux/oom.h> | 67 | #include <linux/oom.h> |
| 68 | #include <linux/khugepaged.h> | 68 | #include <linux/khugepaged.h> |
| 69 | #include <linux/signalfd.h> | ||
| 69 | 70 | ||
| 70 | #include <asm/pgtable.h> | 71 | #include <asm/pgtable.h> |
| 71 | #include <asm/pgalloc.h> | 72 | #include <asm/pgalloc.h> |
| @@ -935,8 +936,10 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) | |||
| 935 | 936 | ||
| 936 | void __cleanup_sighand(struct sighand_struct *sighand) | 937 | void __cleanup_sighand(struct sighand_struct *sighand) |
| 937 | { | 938 | { |
| 938 | if (atomic_dec_and_test(&sighand->count)) | 939 | if (atomic_dec_and_test(&sighand->count)) { |
| 940 | signalfd_cleanup(sighand); | ||
| 939 | kmem_cache_free(sighand_cachep, sighand); | 941 | kmem_cache_free(sighand_cachep, sighand); |
| 942 | } | ||
| 940 | } | 943 | } |
| 941 | 944 | ||
| 942 | 945 | ||
