libmount: fix mnt_monitor_event_cleanup()

We have to call epoll to drain mountinfo events too. The problem is
visible if the monitor epoll FD is within another (top-level) epoll.

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2015-06-01 13:17:41 +02:00
parent 92441d5c1e
commit 08e193e1e4
1 changed files with 26 additions and 13 deletions

View File

@ -713,7 +713,7 @@ int mnt_monitor_next_change(struct libmnt_monitor *mn,
return -EINVAL;
/*
* if we previously called epoll_wait() (e.g. mnt_monitor_waith()) then
* if we previously called epoll_wait() (e.g. mnt_monitor_wait()) then
* info about unread change is already stored in monitor_entry.
*
* If we get nothing, then ask kernel.
@ -751,7 +751,7 @@ int mnt_monitor_next_change(struct libmnt_monitor *mn,
if (type)
*type = me->type;
DBG(MONITOR, ul_debugobj(mn, " *** success"));
DBG(MONITOR, ul_debugobj(mn, " *** success [changed: %s]", me->path));
return 0; /* success */
}
@ -766,18 +766,13 @@ int mnt_monitor_next_change(struct libmnt_monitor *mn,
*/
int mnt_monitor_event_cleanup(struct libmnt_monitor *mn)
{
struct monitor_entry *me;
struct libmnt_iter itr;
int rc;
if (!mn || mn->fd < 0)
return -EINVAL;
mnt_reset_iter(&itr, MNT_ITER_FORWARD);
while (monitor_next_entry(mn, &itr, &me) == 0) {
if (me->opers->op_event_cleanup != NULL)
me->opers->op_event_cleanup(mn, me);
}
return 0;
while ((rc = mnt_monitor_next_change(mn, NULL, NULL)) == 0);
return rc < 0 ? rc : 0;
}
#ifdef TEST_PROGRAM
@ -821,7 +816,7 @@ err:
/*
* create a monitor and add the monitor fd to epoll
*/
int test_epoll(struct libmnt_test *ts, int argc, char *argv[])
int __test_epoll(struct libmnt_test *ts, int argc, char *argv[], int cleanup)
{
int fd, efd = -1, rc = -1;
struct epoll_event ev;
@ -866,8 +861,12 @@ int test_epoll(struct libmnt_test *ts, int argc, char *argv[])
continue;
printf(" top-level FD active\n");
while (mnt_monitor_next_change(mn, &filename, NULL) == 0)
printf(" %s: change detected\n", filename);
if (cleanup)
mnt_monitor_event_cleanup(mn);
else {
while (mnt_monitor_next_change(mn, &filename, NULL) == 0)
printf(" %s: change detected\n", filename);
}
} while (1);
rc = 0;
@ -878,6 +877,19 @@ done:
return rc;
}
/*
* create a monitor and add the monitor fd to epoll
*/
int test_epoll(struct libmnt_test *ts, int argc, char *argv[])
{
return __test_epoll(ts, argc, argv, 0);
}
int test_epoll_cleanup(struct libmnt_test *ts, int argc, char *argv[])
{
return __test_epoll(ts, argc, argv, 1);
}
/*
* create a monitor and wait for a change
*/
@ -905,6 +917,7 @@ int main(int argc, char *argv[])
{
struct libmnt_test tss[] = {
{ "--epoll", test_epoll, "<userspace kernel ...> monitor in epoll" },
{ "--epoll-clean", test_epoll_cleanup, "<userspace kernel ...> monitor in epoll and clean events" },
{ "--wait", test_wait, "<userspace kernel ...> monitor wait function" },
{ NULL }
};