diff options
Diffstat (limited to 'fs/eventpoll.c')
-rw-r--r-- | fs/eventpoll.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index ae1dbcf47e97..cde60741cad2 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -94,6 +94,11 @@ | |||
94 | /* Epoll private bits inside the event mask */ | 94 | /* Epoll private bits inside the event mask */ |
95 | #define EP_PRIVATE_BITS (EPOLLWAKEUP | EPOLLONESHOT | EPOLLET | EPOLLEXCLUSIVE) | 95 | #define EP_PRIVATE_BITS (EPOLLWAKEUP | EPOLLONESHOT | EPOLLET | EPOLLEXCLUSIVE) |
96 | 96 | ||
97 | #define EPOLLINOUT_BITS (POLLIN | POLLOUT) | ||
98 | |||
99 | #define EPOLLEXCLUSIVE_OK_BITS (EPOLLINOUT_BITS | POLLERR | POLLHUP | \ | ||
100 | EPOLLWAKEUP | EPOLLET | EPOLLEXCLUSIVE) | ||
101 | |||
97 | /* Maximum number of nesting allowed inside epoll sets */ | 102 | /* Maximum number of nesting allowed inside epoll sets */ |
98 | #define EP_MAX_NESTS 4 | 103 | #define EP_MAX_NESTS 4 |
99 | 104 | ||
@@ -1068,7 +1073,22 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k | |||
1068 | * wait list. | 1073 | * wait list. |
1069 | */ | 1074 | */ |
1070 | if (waitqueue_active(&ep->wq)) { | 1075 | if (waitqueue_active(&ep->wq)) { |
1071 | ewake = 1; | 1076 | if ((epi->event.events & EPOLLEXCLUSIVE) && |
1077 | !((unsigned long)key & POLLFREE)) { | ||
1078 | switch ((unsigned long)key & EPOLLINOUT_BITS) { | ||
1079 | case POLLIN: | ||
1080 | if (epi->event.events & POLLIN) | ||
1081 | ewake = 1; | ||
1082 | break; | ||
1083 | case POLLOUT: | ||
1084 | if (epi->event.events & POLLOUT) | ||
1085 | ewake = 1; | ||
1086 | break; | ||
1087 | case 0: | ||
1088 | ewake = 1; | ||
1089 | break; | ||
1090 | } | ||
1091 | } | ||
1072 | wake_up_locked(&ep->wq); | 1092 | wake_up_locked(&ep->wq); |
1073 | } | 1093 | } |
1074 | if (waitqueue_active(&ep->poll_wait)) | 1094 | if (waitqueue_active(&ep->poll_wait)) |
@@ -1875,9 +1895,13 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, | |||
1875 | * so EPOLLEXCLUSIVE is not allowed for a EPOLL_CTL_MOD operation. | 1895 | * so EPOLLEXCLUSIVE is not allowed for a EPOLL_CTL_MOD operation. |
1876 | * Also, we do not currently supported nested exclusive wakeups. | 1896 | * Also, we do not currently supported nested exclusive wakeups. |
1877 | */ | 1897 | */ |
1878 | if ((epds.events & EPOLLEXCLUSIVE) && (op == EPOLL_CTL_MOD || | 1898 | if (epds.events & EPOLLEXCLUSIVE) { |
1879 | (op == EPOLL_CTL_ADD && is_file_epoll(tf.file)))) | 1899 | if (op == EPOLL_CTL_MOD) |
1880 | goto error_tgt_fput; | 1900 | goto error_tgt_fput; |
1901 | if (op == EPOLL_CTL_ADD && (is_file_epoll(tf.file) || | ||
1902 | (epds.events & ~EPOLLEXCLUSIVE_OK_BITS))) | ||
1903 | goto error_tgt_fput; | ||
1904 | } | ||
1881 | 1905 | ||
1882 | /* | 1906 | /* |
1883 | * At this point it is safe to assume that the "private_data" contains | 1907 | * At this point it is safe to assume that the "private_data" contains |
@@ -1950,8 +1974,10 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, | |||
1950 | break; | 1974 | break; |
1951 | case EPOLL_CTL_MOD: | 1975 | case EPOLL_CTL_MOD: |
1952 | if (epi) { | 1976 | if (epi) { |
1953 | epds.events |= POLLERR | POLLHUP; | 1977 | if (!(epi->event.events & EPOLLEXCLUSIVE)) { |
1954 | error = ep_modify(ep, epi, &epds); | 1978 | epds.events |= POLLERR | POLLHUP; |
1979 | error = ep_modify(ep, epi, &epds); | ||
1980 | } | ||
1955 | } else | 1981 | } else |
1956 | error = -ENOENT; | 1982 | error = -ENOENT; |
1957 | break; | 1983 | break; |