]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: ignore unwanted kernel events in monitor
authorKarel Zak <kzak@redhat.com>
Mon, 22 Jan 2024 12:04:44 +0000 (13:04 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 22 Jan 2024 12:04:44 +0000 (13:04 +0100)
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>
libmount/docs/libmount-sections.txt
libmount/src/libmount.h.in
libmount/src/libmount.sym
libmount/src/monitor.c

index 58e1b99f5da74879b3f0561f012f8aaaf24bf183..0b4adb5950e786b69a7df422ba383e88a47118c4 100644 (file)
@@ -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>
index 97d151a693095e072f8c60b19aed8e415f21ddaa..d893c26493bb8230d410c33bab51f518f5c1e546 100644 (file)
@@ -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);
index 3df497bd9946d3667aff3558a96ea2fecbc7b1da..0b43160f3a73eaf6b93c1bd5a4dfdffcc86a3846 100644 (file)
@@ -379,4 +379,5 @@ MOUNT_2_39 {
 MOUNT_2_40 {
        mnt_ref_lock;
        mnt_unref_lock;
+       mnt_monitor_veil_kernel;
 } MOUNT_2_39;
index ef53b6d69d462b4b05509ebee86ac9d19a00c285..941f5d5b8ef41196705334c5d2705bf431a8c199 100644 (file)
@@ -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 }
        };