View Issue Details

IDProjectCategoryView StatusLast Update
0008450Rocky-Linux-9Generalpublic2024-12-05 23:42
ReporterRyan Plaster Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
PlatformLinuxOSRockyOS Version9
Summary0008450: FANotify FAN_ATTRIB event error
DescriptionWhen watching for FAN_ATTRIB events on the 5.14.0-503.15.1 kernel, an endless loop of FAN_ATTRIB events are reported. This did not occur on the previous kernel release (5.14.0-427.13.1) .

I am not sure how else to test this as far as I am aware fanotify is provided with the kernel.
Steps To ReproduceWatch an XFS filesystem for FAN_ATTRIB events. I attached a test program that can be compiled in C to monitor a filesystem. I tested this on the previous kernel and on the latest Ubuntu release and it works as expected, but on the latest kernel the FAN_ATTRIB event continuously reports.
Additional InformationExample output after a file is moved into the watched filesystem. I had to kill the program since it continuously output the FAN_ATTRIB log.


Kernel: 5.14.0-427.13.1

$ sudo ./fanotify_monitor
Listening for events on /test1.
Event info_type: 2
Directory: "/test1" FAN_CREATE "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_CLOSE_WRITE "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
 

 Kernel 5.14.0-503.15.1:

$ sudo ./fanotify_monitor
Listening for events on /test1.
Event info_type: 2
Directory: "/test1" FAN_CREATE "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Directory: "/test1" FAN_CLOSE_WRITE "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
Event info_type: 2
Directory: "/test1" FAN_ATTRIB "testfile_001" (file)
^C
Tagskernel
Attached Files
FANotify_test_program.txt (4,434 bytes)   
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fanotify.h>
#include <unistd.h>

#define BUF_SIZE 256

int main() {
    int fd, ret, event_fd, mount_fd;
    ssize_t len, path_len;
    char path[PATH_MAX];
    char procfd_path[PATH_MAX];
    char events_buf[BUF_SIZE];
    struct file_handle *file_handle;
    struct fanotify_event_metadata *metadata;
    struct fanotify_event_info_fid *fid;
    const char *file_name;
    struct stat sb;

    const char *monitor_dir = "/test1";

    mount_fd = open(monitor_dir, O_DIRECTORY | O_RDONLY);
    if (mount_fd == -1) {
        perror(monitor_dir);
        exit(EXIT_FAILURE);
    }

    fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME, O_CLOEXEC | O_NONBLOCK);
    if (fd == -1) {
        perror("fanotify_init");
        exit(EXIT_FAILURE);
    }

    ret = fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_FILESYSTEM,
                        FAN_CREATE | FAN_ATTRIB | FAN_DELETE | FAN_MOVE | FAN_CLOSE_WRITE | FAN_ONDIR,
                        AT_FDCWD, monitor_dir);
    if (ret == -1) {
        perror("fanotify_mark");
        exit(EXIT_FAILURE);
    }

    printf("Listening for events on %s.\n", monitor_dir);

    while (1) {
        len = read(fd, events_buf, sizeof(events_buf));
        if (len == -1) {
            if (errno == EAGAIN) continue;
            perror("read");
            exit(EXIT_FAILURE);
        }

        for (metadata = (struct fanotify_event_metadata *) events_buf;
                FAN_EVENT_OK(metadata, len);
                metadata = FAN_EVENT_NEXT(metadata, len)) {

            fid = (struct fanotify_event_info_fid *) (metadata + 1);

            // Print the info_type for debugging
            printf("Event info_type: %d\n", fid->hdr.info_type);

            file_handle = (struct file_handle *) fid->handle;
            file_name = NULL;

            if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID_NAME) {
                file_name = file_handle->f_handle + file_handle->handle_bytes;
            } else {
                continue;
            }

            event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY);
            if (event_fd == -1) {
                if (errno == ESTALE) {
                    printf("File handle is no longer valid. File has been deleted\n");
                    continue;
                } else {
                    perror("open_by_handle_at");
                    exit(EXIT_FAILURE);
                }
            }

            snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d", event_fd);
            path_len = readlink(procfd_path, path, sizeof(path) - 1);
            if (path_len == -1) {
                perror("readlink");
                exit(EXIT_FAILURE);
            }

            path[path_len] = '\0';

            // Determine if it's a directory or file event based on FAN_ONDIR
            const char *entry_type = (metadata->mask & FAN_ONDIR) ? "(directory)" : "(file)";

            // Print event type with directory and file name in the specified format
            if (metadata->mask & FAN_CREATE) {
                printf("Directory: \"%s\" FAN_CREATE \"%s\" %s\n", path, file_name, entry_type);
            }
            if (metadata->mask & FAN_ATTRIB) {
                printf("Directory: \"%s\" FAN_ATTRIB \"%s\" %s\n", path, file_name, entry_type);
            }
            if (metadata->mask & FAN_DELETE) {
                printf("Directory: \"%s\" FAN_DELETE \"%s\" %s\n", path, file_name, entry_type);
            }
            if (metadata->mask & FAN_CLOSE_WRITE) {
                printf("Directory: \"%s\" FAN_CLOSE_WRITE \"%s\" %s\n", path, file_name, entry_type);
            }
            if (metadata->mask & FAN_MOVE) {
                if (metadata->mask & FAN_MOVED_FROM) {
                    printf("Directory: \"%s\" FAN_MOVED_FROM \"%s\" %s\n", path, file_name, entry_type);
                } else if (metadata->mask & FAN_MOVED_TO) {
                    printf("Directory: \"%s\" FAN_MOVED_TO \"%s\" %s\n", path, file_name, entry_type);
                }
            }

            close(event_fd);
        }
    }

    close(fd);
    close(mount_fd);
    return EXIT_SUCCESS;
}
FANotify_test_program.txt (4,434 bytes)   

Activities

Ryan Plaster

Ryan Plaster

2024-12-05 23:42

reporter   ~0009026

This ticket can be deleted/closed. User error. My program was modifying the atime.

Issue History

Date Modified Username Field Change
2024-12-03 06:21 Ryan Plaster New Issue
2024-12-03 06:21 Ryan Plaster Tag Attached: kernel
2024-12-03 06:21 Ryan Plaster File Added: FANotify_test_program.txt
2024-12-05 23:42 Ryan Plaster Note Added: 0009026