aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak <kzak@redhat.com>2024-01-22 13:04:44 +0100
committerKarel Zak <kzak@redhat.com>2024-01-22 13:04:44 +0100
commita2b5a4e0adf9543843bb0aef94d21e7105cf8159 (patch)
treefa94846d66d81b97422c188d55e0896b55eead92
parent9218c9678a6aa9b163705364246ed128e94fabb7 (diff)
downloadutil-linux-a2b5a4e0adf9543843bb0aef94d21e7105cf8159.tar.gz
libmount: ignore unwanted kernel events in monitor
If the mount operation requires multiple steps, it's optimal for the libmount monitor to ignore the steps until we get a complete mount (reported by the utab.event file). This commit adds a new API function, mnt_monitor_veil_kernel(), to ignore unwanted kernel mount events. Note that this only makes sense when the application monitors kernel and userspace events simultaneously. Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--libmount/docs/libmount-sections.txt1
-rw-r--r--libmount/src/libmount.h.in2
-rw-r--r--libmount/src/libmount.sym1
-rw-r--r--libmount/src/monitor.c55
4 files changed, 54 insertions, 5 deletions
diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt
index 58e1b99f5d..0b4adb5950 100644
--- a/libmount/docs/libmount-sections.txt
+++ b/libmount/docs/libmount-sections.txt
@@ -456,5 +456,6 @@ mnt_monitor_get_fd
mnt_monitor_close_fd
mnt_monitor_next_change
mnt_monitor_event_cleanup
+mnt_monitor_veil_kernel
mnt_monitor_wait
</SECTION>
diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in
index 97d151a693..d893c26493 100644
--- a/libmount/src/libmount.h.in
+++ b/libmount/src/libmount.h.in
@@ -699,6 +699,8 @@ extern int mnt_monitor_enable_kernel(struct libmnt_monitor *mn, int enable);
extern int mnt_monitor_enable_userspace(struct libmnt_monitor *mn,
int enable, const char *filename);
+extern int mnt_monitor_veil_kernel(struct libmnt_monitor *mn, int enable);
+
extern int mnt_monitor_get_fd(struct libmnt_monitor *mn);
extern int mnt_monitor_close_fd(struct libmnt_monitor *mn);
extern int mnt_monitor_wait(struct libmnt_monitor *mn, int timeout);
diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym
index 3df497bd99..0b43160f3a 100644
--- a/libmount/src/libmount.sym
+++ b/libmount/src/libmount.sym
@@ -379,4 +379,5 @@ MOUNT_2_39 {
MOUNT_2_40 {
mnt_ref_lock;
mnt_unref_lock;
+ mnt_monitor_veil_kernel;
} MOUNT_2_39;
diff --git a/libmount/src/monitor.c b/libmount/src/monitor.c
index ef53b6d69d..941f5d5b8e 100644
--- a/libmount/src/monitor.c
+++ b/libmount/src/monitor.c
@@ -64,6 +64,8 @@ struct libmnt_monitor {
int fd; /* public monitor file descriptor */
struct list_head ents;
+
+ unsigned int kernel_veiled: 1;
};
struct monitor_opers {
@@ -471,12 +473,28 @@ err:
return rc;
}
+static int kernel_event_verify(struct libmnt_monitor *mn,
+ struct monitor_entry *me)
+{
+ int status = 1;
+
+ if (!mn || !me || me->fd < 0)
+ return 0;
+
+ if (mn->kernel_veiled && access(MNT_PATH_UTAB ".act", F_OK) == 0) {
+ status = 0;
+ DBG(MONITOR, ul_debugobj(mn, "kernel event veiled"));
+ }
+ return status;
+}
+
/*
* kernel monitor operations
*/
static const struct monitor_opers kernel_opers = {
.op_get_fd = kernel_monitor_get_fd,
.op_close_fd = kernel_monitor_close_fd,
+ .op_event_verify = kernel_event_verify
};
/**
@@ -545,6 +563,28 @@ err:
return rc;
}
+/**
+ * mnt_monitor_veil_kernel:
+ * @mn: monitor instance
+ * @enable: 1 or 0
+ *
+ * Force monitor to ignore kernel events if the same mount/umount operation
+ * will generate an userspace event later. The kernel-only mount operation will
+ * be not affected.
+ *
+ * Return: 0 on success and <0 on error.
+ *
+ * Since: 2.40
+ */
+int mnt_monitor_veil_kernel(struct libmnt_monitor *mn, int enable)
+{
+ if (!mn)
+ return -EINVAL;
+
+ mn->kernel_veiled = enable ? 1 : 0;
+ return 0;
+}
+
/*
* Add/Remove monitor entry to/from monitor epoll.
*/
@@ -852,6 +892,8 @@ static struct libmnt_monitor *create_test_monitor(int argc, char *argv[])
warn("failed to initialize kernel monitor");
goto err;
}
+ } else if (strcmp(argv[i], "veil") == 0) {
+ mnt_monitor_veil_kernel(mn, 1);
}
}
if (i == 1) {
@@ -899,12 +941,14 @@ static int __test_epoll(struct libmnt_test *ts __attribute__((unused)),
goto done;
}
- printf("waiting for changes...\n");
do {
const char *filename = NULL;
struct epoll_event events[1];
- int n = epoll_wait(efd, events, 1, -1);
+ int n;
+
+ printf("waiting for changes...\n");
+ n = epoll_wait(efd, events, 1, -1);
if (n < 0) {
rc = -errno;
warn("polling error");
@@ -962,6 +1006,7 @@ static int test_wait(struct libmnt_test *ts __attribute__((unused)),
while (mnt_monitor_next_change(mn, &filename, NULL) == 0)
printf(" %s: change detected\n", filename);
+ printf("waiting for changes...\n");
}
mnt_unref_monitor(mn);
return 0;
@@ -970,9 +1015,9 @@ static int test_wait(struct libmnt_test *ts __attribute__((unused)),
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" },
+ { "--epoll", test_epoll, "<userspace kernel veil ...> monitor in epoll" },
+ { "--epoll-clean", test_epoll_cleanup, "<userspace kernel veil ...> monitor in epoll and clean events" },
+ { "--wait", test_wait, "<userspace kernel veil ...> monitor wait function" },
{ NULL }
};