X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Fcompat%2Fcompat-epoll.c;h=6a781c7ae04034f321f974c244df6e43e01e58b3;hb=18710679a8ac57fda5dbd26cf16bb180dce9e286;hp=29bd2f868ed38e1e6253b8841f2326025cb8c644;hpb=6c1c0768320135c6936c371b09731851b508c023;p=lttng-tools.git diff --git a/src/common/compat/compat-epoll.c b/src/common/compat/compat-epoll.c index 29bd2f868..6a781c7ae 100644 --- a/src/common/compat/compat-epoll.c +++ b/src/common/compat/compat-epoll.c @@ -15,7 +15,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE #define _LGPL_SOURCE #include #include @@ -24,7 +23,6 @@ #include #include #include -#include #include #include @@ -77,8 +75,14 @@ int compat_epoll_create(struct lttng_poll_event *events, int size, int flags) goto error; } + if (!poll_max_size) { + if (lttng_poll_set_max_size()) { + goto error; + } + } + /* Don't bust the limit here */ - if (size > poll_max_size && poll_max_size != 0) { + if (size > poll_max_size) { size = poll_max_size; } @@ -166,7 +170,7 @@ int compat_epoll_del(struct lttng_poll_event *events, int fd) { int ret; - if (events == NULL || fd < 0) { + if (events == NULL || fd < 0 || events->nb_fd == 0) { goto error; } @@ -193,6 +197,47 @@ error: return -1; } +/* + * Set an fd's events. + */ +int compat_epoll_mod(struct lttng_poll_event *events, int fd, uint32_t req_events) +{ + int ret; + struct epoll_event ev; + + if (events == NULL || fd < 0 || events->nb_fd == 0) { + goto error; + } + + /* + * Zero struct epoll_event to ensure all representations of its + * union are zeroed. + */ + memset(&ev, 0, sizeof(ev)); + ev.events = req_events; + ev.data.fd = fd; + + ret = epoll_ctl(events->epfd, EPOLL_CTL_MOD, fd, &ev); + if (ret < 0) { + switch (errno) { + case ENOENT: + case EPERM: + /* Print PERROR and goto end not failing. Show must go on. */ + PERROR("epoll_ctl MOD"); + goto end; + default: + PERROR("epoll_ctl MOD fatal"); + goto error; + } + } + +end: + return 0; + +error: + return -1; +} + /* * Wait on epoll set. This is a blocking call of timeout value. */ @@ -206,29 +251,19 @@ int compat_epoll_wait(struct lttng_poll_event *events, int timeout) goto error; } + if (events->nb_fd == 0) { + errno = EINVAL; + return -1; + } + /* * Resize if needed before waiting. We could either expand the array or * shrink it down. It's important to note that after this step, we are * ensured that the events argument of the epoll_wait call will be large * enough to hold every possible returned events. */ - if (events->nb_fd > events->alloc_size) { - /* Expand if the nb_fd is higher than the actual size. */ - new_size = max_t(uint32_t, - 1U << utils_get_count_order_u32(events->nb_fd), - events->alloc_size << 1UL); - } else if ((events->nb_fd << 1UL) <= events->alloc_size && - events->nb_fd >= events->init_size) { - /* Shrink if nb_fd multiplied by two is <= than the actual size. */ - new_size = max_t(uint32_t, - utils_get_count_order_u32(events->nb_fd) >> 1U, - events->alloc_size >> 1U); - } else { - /* Indicate that we don't want to resize. */ - new_size = 0; - } - - if (new_size) { + new_size = 1U << utils_get_count_order_u32(events->nb_fd); + if (new_size != events->alloc_size && new_size >= events->init_size) { ret = resize_poll_event(events, new_size); if (ret < 0) { /* ENOMEM problem at this point. */ @@ -258,17 +293,24 @@ error: /* * Setup poll set maximum size. */ -void compat_epoll_set_max_size(void) +int compat_epoll_set_max_size(void) { - int ret, fd; + int ret, fd, retval = 0; ssize_t size_ret; char buf[64]; - poll_max_size = DEFAULT_POLL_SIZE; - fd = open(COMPAT_EPOLL_PROC_PATH, O_RDONLY); if (fd < 0) { - return; + /* + * Failing on opening [1] is not an error per see. [1] was + * introduced in Linux 2.6.28 but epoll is available since + * 2.5.44. Hence, goto end and set a default value without + * setting an error return value. + * + * [1] /proc/sys/fs/epoll/max_user_watches + */ + retval = 0; + goto end; } size_ret = lttng_read(fd, buf, sizeof(buf)); @@ -278,21 +320,20 @@ void compat_epoll_set_max_size(void) */ if (size_ret < 0 || size_ret >= sizeof(buf)) { PERROR("read set max size"); - goto error; + retval = -1; + goto end_read; } buf[size_ret] = '\0'; - poll_max_size = atoi(buf); - if (poll_max_size == 0) { - /* Extra precaution */ - poll_max_size = DEFAULT_POLL_SIZE; - } - - DBG("epoll set max size is %d", poll_max_size); - -error: +end_read: ret = close(fd); if (ret) { PERROR("close"); } +end: + if (!poll_max_size) { + poll_max_size = DEFAULT_POLL_SIZE; + } + DBG("epoll set max size is %d", poll_max_size); + return retval; }