ioloop-notify-inotify.c revision dad206f8341603837b7de4309a7c195da26cf9aa
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (c) 2005-2015 Dovecot authors, see the included COPYING file */
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen#define _GNU_SOURCE
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen#include "lib.h"
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen#ifdef IOLOOP_NOTIFY_INOTIFY
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
6246b93fb37890dcb2f4df9896438f3f376ab284Timo Sirainen#include "fd-close-on-exec.h"
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen#include "fd-set-nonblock.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "ioloop-private.h"
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen#include "ioloop-notify-fd.h"
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen#include "buffer.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen#include "ipwd.h"
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen#include <stdio.h>
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen#include <unistd.h>
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen#include <fcntl.h>
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen#include <sys/ioctl.h>
660b4d36110c44b1e4b4b45a78c22d1569ccdb54Timo Sirainen#include <sys/inotify.h>
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen#define INOTIFY_BUFLEN (32*1024)
283ccfe110ed62e48f36e0d84e47da8cae5106beTimo Sirainen
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainenstruct ioloop_notify_handler_context {
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct ioloop_notify_fd_context fd_ctx;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen int inotify_fd;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen struct io *event_io;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool disabled;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen};
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainenstatic struct ioloop_notify_handler_context *io_loop_notify_handler_init(void);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainenstatic bool inotify_input_more(struct ioloop *ioloop)
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen{
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen struct ioloop_notify_handler_context *ctx =
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen ioloop->notify_handler_context;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen const struct inotify_event *event;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen unsigned char event_buf[INOTIFY_BUFLEN];
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct io_notify *io;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen ssize_t ret, pos;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen /* read as many events as there is available and fit into our buffer.
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen only full events are returned by the kernel. */
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen ret = read(ctx->inotify_fd, event_buf, sizeof(event_buf));
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen if (ret <= 0) {
8d6a6eccd3f2e34df967b90bb45e20755241bdbbTimo Sirainen if (ret == 0 || errno == EAGAIN) {
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen /* nothing more to read */
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen return FALSE;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen }
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen i_fatal("read(inotify) failed: %m");
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen }
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
306f6bb8791755257c0db900f17659402c660057Timo Sirainen if (gettimeofday(&ioloop_timeval, NULL) < 0)
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen i_fatal("gettimeofday(): %m");
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen ioloop_time = ioloop_timeval.tv_sec;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen for (pos = 0; pos < ret; ) {
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen if ((size_t)(ret - pos) < sizeof(*event))
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen break;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen event = (struct inotify_event *)(event_buf + pos);
0abbd167fe12a6b0aba98d38552f023a5fa8ffa7Timo Sirainen i_assert(event->len < (size_t)ret);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen pos += sizeof(*event) + event->len;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen io = io_notify_fd_find(&ctx->fd_ctx, event->wd);
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen if (io != NULL) {
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen if ((event->mask & IN_IGNORED) != 0) {
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen /* calling inotify_rm_watch() would now give
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen EINVAL */
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen io->fd = -1;
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen }
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen io_loop_call_io(&io->io);
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen }
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen }
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen if (pos != ret)
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen i_error("read(inotify) returned partial event");
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen return (size_t)ret >= sizeof(event_buf)-512;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen}
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainenstatic void inotify_input(struct ioloop *ioloop)
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen{
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen while (inotify_input_more(ioloop)) ;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen}
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen#undef io_add_notify
f6845101f2d6b8068e352a0b5a0d4bb04e20ad74Timo Sirainenenum io_notify_result
f6845101f2d6b8068e352a0b5a0d4bb04e20ad74Timo Sirainenio_add_notify(const char *path, unsigned int source_linenum,
f6845101f2d6b8068e352a0b5a0d4bb04e20ad74Timo Sirainen io_callback_t *callback, void *context, struct io **io_r)
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen{
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen struct ioloop_notify_handler_context *ctx =
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen current_ioloop->notify_handler_context;
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen int wd;
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen *io_r = NULL;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen if (ctx == NULL)
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen ctx = io_loop_notify_handler_init();
d6500661eb699ff335ac570c8646b6e067e1aac6Timo Sirainen if (ctx->disabled)
0a3d3ca7db7cbdc947ccabe740c40561b3f5c066Timo Sirainen return IO_NOTIFY_NOSUPPORT;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen wd = inotify_add_watch(ctx->inotify_fd, path,
d514e6e6ea2320c18c58e0ade9184f5aa67d491bTimo Sirainen IN_CREATE | IN_DELETE | IN_DELETE_SELF |
85e2264f7d3b1a336ac5066c99130414dfc77902Timo Sirainen IN_MOVE | IN_MODIFY);
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen if (wd < 0) {
36d2b3dc8766ef336a289a51075ca2f3236ef1efTimo Sirainen /* ESTALE could happen with NFS. Don't bother giving an error
36d2b3dc8766ef336a289a51075ca2f3236ef1efTimo Sirainen message then. */
5561fe7754843250d0f2701332f63467f77f71dbTimo Sirainen if (errno == ENOENT || errno == ESTALE)
5561fe7754843250d0f2701332f63467f77f71dbTimo Sirainen return IO_NOTIFY_NOTFOUND;
5561fe7754843250d0f2701332f63467f77f71dbTimo Sirainen
c7398cd92a003144358c121bdea63fba35b884aeTimo Sirainen if (errno != ENOSPC)
c7398cd92a003144358c121bdea63fba35b884aeTimo Sirainen i_error("inotify_add_watch(%s) failed: %m", path);
c7398cd92a003144358c121bdea63fba35b884aeTimo Sirainen else {
c7398cd92a003144358c121bdea63fba35b884aeTimo Sirainen i_warning("Inotify watch limit for user exceeded, "
c7398cd92a003144358c121bdea63fba35b884aeTimo Sirainen "disabling. Increase "
c7398cd92a003144358c121bdea63fba35b884aeTimo Sirainen "/proc/sys/fs/inotify/max_user_watches");
c7398cd92a003144358c121bdea63fba35b884aeTimo Sirainen }
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen ctx->disabled = TRUE;
0a3d3ca7db7cbdc947ccabe740c40561b3f5c066Timo Sirainen return IO_NOTIFY_NOSUPPORT;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen }
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
d6500661eb699ff335ac570c8646b6e067e1aac6Timo Sirainen if (ctx->event_io == NULL) {
d6500661eb699ff335ac570c8646b6e067e1aac6Timo Sirainen ctx->event_io = io_add(ctx->inotify_fd, IO_READ,
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen inotify_input, current_ioloop);
d6500661eb699ff335ac570c8646b6e067e1aac6Timo Sirainen }
d6500661eb699ff335ac570c8646b6e067e1aac6Timo Sirainen
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen *io_r = io_notify_fd_add(&ctx->fd_ctx, wd, callback, context);
f6845101f2d6b8068e352a0b5a0d4bb04e20ad74Timo Sirainen (*io_r)->source_linenum = source_linenum;
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen return IO_NOTIFY_ADDED;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen}
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainenvoid io_loop_notify_remove(struct io *_io)
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen{
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen struct ioloop_notify_handler_context *ctx =
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen _io->ioloop->notify_handler_context;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct io_notify *io = (struct io_notify *)_io;
d6500661eb699ff335ac570c8646b6e067e1aac6Timo Sirainen
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen if (io->fd != -1) {
d514e6e6ea2320c18c58e0ade9184f5aa67d491bTimo Sirainen /* ernro=EINVAL happens if the file itself is deleted and
d514e6e6ea2320c18c58e0ade9184f5aa67d491bTimo Sirainen kernel has sent IN_IGNORED event which we haven't read. */
d514e6e6ea2320c18c58e0ade9184f5aa67d491bTimo Sirainen if (inotify_rm_watch(ctx->inotify_fd, io->fd) < 0 &&
d514e6e6ea2320c18c58e0ade9184f5aa67d491bTimo Sirainen errno != EINVAL)
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen i_error("inotify_rm_watch() failed: %m");
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen }
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen io_notify_fd_free(&ctx->fd_ctx, io);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen if (ctx->fd_ctx.notifies == NULL && ctx->event_io != NULL)
2a4e8f370c566ffd360922227fc73d0ee36abee7Timo Sirainen io_remove(&ctx->event_io);
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen}
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainenstatic void ioloop_inotify_user_limit_exceeded(void)
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen{
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen struct passwd pw;
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen const char *name;
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen uid_t uid = geteuid();
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (i_getpwuid(uid, &pw) <= 0)
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen name = t_strdup_printf("UID %s", dec2str(uid));
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen else {
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen name = t_strdup_printf("%s (UID %s)",
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen dec2str(uid), pw.pw_name);
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen }
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen i_warning("Inotify instance limit for user %s exceeded, disabling. "
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen "Increase /proc/sys/fs/inotify/max_user_instances", name);
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen}
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainenstatic struct ioloop_notify_handler_context *io_loop_notify_handler_init(void)
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen{
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct ioloop *ioloop = current_ioloop;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen struct ioloop_notify_handler_context *ctx;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen ctx = ioloop->notify_handler_context =
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen i_new(struct ioloop_notify_handler_context, 1);
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
6246b93fb37890dcb2f4df9896438f3f376ab284Timo Sirainen ctx->inotify_fd = inotify_init();
6246b93fb37890dcb2f4df9896438f3f376ab284Timo Sirainen if (ctx->inotify_fd == -1) {
c8b29548f94160e0fe2f02e66d899d9e6cb495b3Timo Sirainen if (errno != EMFILE)
c8b29548f94160e0fe2f02e66d899d9e6cb495b3Timo Sirainen i_error("inotify_init() failed: %m");
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen else
fdb97244fa45c32c3593726c15aa69ce29bc7121Timo Sirainen ioloop_inotify_user_limit_exceeded();
d6500661eb699ff335ac570c8646b6e067e1aac6Timo Sirainen ctx->disabled = TRUE;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen } else {
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen fd_close_on_exec(ctx->inotify_fd, TRUE);
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen fd_set_nonblock(ctx->inotify_fd, TRUE);
d6500661eb699ff335ac570c8646b6e067e1aac6Timo Sirainen }
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen return ctx;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen}
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainenvoid io_loop_notify_handler_deinit(struct ioloop *ioloop)
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen{
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen struct ioloop_notify_handler_context *ctx =
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen ioloop->notify_handler_context;
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen while (ctx->fd_ctx.notifies != NULL) {
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen struct io_notify *io = ctx->fd_ctx.notifies;
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen struct io *_io = &io->io;
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen i_warning("I/O notify leak: %p (line %u, fd %d)",
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen (void *)_io->callback,
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen _io->source_linenum, io->fd);
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen io_remove(&_io);
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen }
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen if (ctx->inotify_fd != -1) {
6246b93fb37890dcb2f4df9896438f3f376ab284Timo Sirainen if (close(ctx->inotify_fd) < 0)
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen i_error("close(inotify) failed: %m");
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen ctx->inotify_fd = -1;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen }
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen i_free(ctx);
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen}
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainenint io_loop_extract_notify_fd(struct ioloop *ioloop)
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen{
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen struct ioloop_notify_handler_context *ctx =
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen ioloop->notify_handler_context;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen struct io_notify *io;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen int fd, new_inotify_fd;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen if (ctx->inotify_fd == -1)
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen return -1;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen new_inotify_fd = inotify_init();
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen if (new_inotify_fd == -1) {
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen if (errno != EMFILE)
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen i_error("inotify_init() failed: %m");
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen else
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen ioloop_inotify_user_limit_exceeded();
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen return -1;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen }
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen for (io = ctx->fd_ctx.notifies; io != NULL; io = io->next)
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen io->fd = -1;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen if (ctx->event_io != NULL)
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen io_remove(&ctx->event_io);
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen fd = ctx->inotify_fd;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen ctx->inotify_fd = new_inotify_fd;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen return fd;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen}
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen
9d7451b57769988f7e3e41cd8790e65429ffc5c7Timo Sirainen#endif