]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: (monitor) add fanotify_next_fs()
authorKarel Zak <kzak@redhat.com>
Tue, 5 Aug 2025 13:39:53 +0000 (15:39 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 7 Aug 2025 09:27:55 +0000 (11:27 +0200)
This function returns a unique filesystem ID to the caller.

Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/monitor.c
libmount/src/monitor_fanotify.c

index 2202c712cce3512d20e82e68dbf65c62d2684b5b..194817aacda5ab2a92878548e5931da16c925a30 100644 (file)
@@ -449,7 +449,7 @@ int mnt_monitor_next_change(struct libmnt_monitor *mn,
        if (type)
                *type = me->type;
 
-       DBG(MONITOR, ul_debugobj(mn, " *** success [changed: %s]", me->path));
+       DBG(MONITOR, ul_debugobj(mn, " *** success [changed: %s, type=%d]", me->path, me->type));
        return 0;
 }
 
@@ -564,6 +564,7 @@ static int __test_epoll(struct libmnt_test *ts __attribute__((unused)),
        int fd, efd = -1, rc = -1;
        struct epoll_event ev;
        struct libmnt_monitor *mn = create_test_monitor(argc, argv);
+       struct libmnt_fs *fs = NULL;
 
        if (!mn)
                return -1;
@@ -609,8 +610,25 @@ static int __test_epoll(struct libmnt_test *ts __attribute__((unused)),
                if (cleanup)
                        mnt_monitor_event_cleanup(mn);
                else {
-                       while (mnt_monitor_next_change(mn, &filename, NULL) == 0)
+                       int type = 0;
+
+                       while (mnt_monitor_next_change(mn, &filename, &type) == 0) {
                                printf("  %s: change detected\n", filename);
+
+                               if (type == MNT_MONITOR_TYPE_FANOTIFY) {
+                                       if (!fs)
+                                               fs = mnt_new_fs();
+                                       while (mnt_monitor_event_next_fs(mn, fs) == 0) {
+                                               mnt_fs_fetch_statmount(fs, 0);
+                                               printf("ID=%ju (%s %s)\n",
+                                                       mnt_fs_get_uniq_id(fs),
+                                                       mnt_fs_get_target(fs),
+                                                       mnt_fs_is_attached(fs) ? "ATTACHED" :
+                                                       mnt_fs_is_detached(fs) ? "DETACHED" :
+                                                       mnt_fs_is_moved(fs) ? "MOVED" : "???");
+                                       }
+                               }
+                       }
                }
        } while (1);
 
@@ -619,6 +637,7 @@ done:
        if (efd >= 0)
                close(efd);
        mnt_unref_monitor(mn);
+       mnt_unref_fs(fs);
        return rc;
 }
 
index 6adb6e5afeaf262f7d383cdeaeefacaf8bea1235..7e6903bebd5a018df07fe4e23e521581fcb30a08 100644 (file)
@@ -125,8 +125,8 @@ static int fanotify_process_event(
        struct monitor_entrydata *data;
        ssize_t len;
 
-       if (!mn || !me || me->fd < 0)
-               return 0;
+       if (!mn || !me || me->fd < 0 || !me->data)
+               return -EINVAL;
 
        DBG(MONITOR, ul_debugobj(mn, "reading fanotify event"));
 
@@ -148,13 +148,72 @@ static int fanotify_process_event(
        }
 
        len = read(me->fd, data->buf, sizeof(data->buf));
-       if (len < 0)
+       if (len <= 0)
                return 1;       /* nothing */
 
        data->remaining = (size_t) len;
-       DBG(MONITOR, ul_debugobj(mn, " fanotify event [len=%zu]", data->remaining));
+       DBG(MONITOR, ul_debugobj(mn, " fanotify event [len=%zu %p]",
+                               data->remaining, data->current));
+
+       return 0;
+}
+
+/* Returns: <0 error; 0 success; 1 nothing */
+static int fanotify_next_fs(struct libmnt_monitor *mn, struct monitor_entry *me,
+                       struct libmnt_fs *fs)
+{
+       struct monitor_entrydata *data;
+       size_t thislen;
+
+       struct fanotify_event_metadata *meta;
+       struct fanotify_event_info_mnt *mnt;
+
+       if (!mn || !me || me->fd < 0 || !me->data)
+               return -EINVAL;
+
+       DBG(MONITOR, ul_debugobj(mn, "next fanotify fs"));
 
+       data = (struct monitor_entrydata *) me->data;
+       if (!fs || !data->remaining)
+               goto nothing;
+        else {
+               struct libmnt_statmnt *tmp = fs->stmnt;
+               fs->stmnt = NULL;
+               mnt_reset_fs(fs);
+               fs->stmnt = tmp;
+       }
+
+       meta = (struct fanotify_event_metadata *) data->current;
+
+       if (!FAN_EVENT_OK(meta, data->remaining) ||
+           meta->vers != FANOTIFY_METADATA_VERSION)
+               goto nothing;
+
+       thislen = meta->event_len - sizeof(*meta);
+
+       mnt = (struct fanotify_event_info_mnt *)
+                       (data->current + meta->event_len - thislen);
+
+
+       mnt_fs_set_uniq_id(fs, mnt->mnt_id);
+
+       if (meta->mask & FAN_MNT_ATTACH)
+               fs->flags |= MNT_FS_STATUS_ATTACH;
+       if (meta->mask & FAN_MNT_DETACH)
+               fs->flags |= MNT_FS_STATUS_DETACH;
+
+       DBG(MONITOR, ul_debugobj(mn, "fanotify fs id=%ju %s\n",
+               (uintmax_t) mnt_fs_get_uniq_id(fs),
+               mnt_fs_is_attached(fs) ? "ATTACHED" :
+               mnt_fs_is_detached(fs) ? "DETACHED" :
+               mnt_fs_is_moved(fs) ? "MOVED" : "???"));
+
+       data->current = (char *) FAN_EVENT_NEXT(meta, data->remaining);
        return 0;
+
+nothing:
+       data->remaining = 0;
+       return 1;
 }
 
 /*
@@ -164,7 +223,8 @@ static const struct monitor_opers fanotify_opers = {
        .op_get_fd              = fanotify_get_fd,
        .op_close_fd            = fanotify_close_fd,
        .op_free_data           = fanotify_free_data,
-       .op_process_event       = fanotify_process_event
+       .op_process_event       = fanotify_process_event,
+       .op_next_fs             = fanotify_next_fs
 };
 
 /**