Re: [PATCH v4 15/16] samples: Add fs error monitoring example

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jul 20, 2021 at 7:00 PM Gabriel Krisman Bertazi
<krisman@xxxxxxxxxxxxx> wrote:
>
> Introduce an example of a FAN_FS_ERROR fanotify user to track filesystem
> errors.
>
> Signed-off-by: Gabriel Krisman Bertazi <krisman@xxxxxxxxxxxxx>
>

Reviewed-by: Amir Goldstein <amir73il@xxxxxxxxx>

except for one small nit

> ---
> Changes since v1:
>   - minor fixes
> ---
>  samples/Kconfig               |   9 +++
>  samples/Makefile              |   1 +
>  samples/fanotify/Makefile     |   5 ++
>  samples/fanotify/fs-monitor.c | 134 ++++++++++++++++++++++++++++++++++
>  4 files changed, 149 insertions(+)
>  create mode 100644 samples/fanotify/Makefile
>  create mode 100644 samples/fanotify/fs-monitor.c
>
> diff --git a/samples/Kconfig b/samples/Kconfig
> index b0503ef058d3..88353b8eac0b 100644
> --- a/samples/Kconfig
> +++ b/samples/Kconfig
> @@ -120,6 +120,15 @@ config SAMPLE_CONNECTOR
>           with it.
>           See also Documentation/driver-api/connector.rst
>
> +config SAMPLE_FANOTIFY_ERROR
> +       bool "Build fanotify error monitoring sample"
> +       depends on FANOTIFY
> +       help
> +         When enabled, this builds an example code that uses the
> +         FAN_FS_ERROR fanotify mechanism to monitor filesystem
> +         errors.
> +         See also Documentation/admin-guide/filesystem-monitoring.rst.
> +
>  config SAMPLE_HIDRAW
>         bool "hidraw sample"
>         depends on CC_CAN_LINK && HEADERS_INSTALL
> diff --git a/samples/Makefile b/samples/Makefile
> index 087e0988ccc5..931a81847c48 100644
> --- a/samples/Makefile
> +++ b/samples/Makefile
> @@ -5,6 +5,7 @@ subdir-$(CONFIG_SAMPLE_AUXDISPLAY)      += auxdisplay
>  subdir-$(CONFIG_SAMPLE_ANDROID_BINDERFS) += binderfs
>  obj-$(CONFIG_SAMPLE_CONFIGFS)          += configfs/
>  obj-$(CONFIG_SAMPLE_CONNECTOR)         += connector/
> +obj-$(CONFIG_SAMPLE_FANOTIFY_ERROR)    += fanotify/
>  subdir-$(CONFIG_SAMPLE_HIDRAW)         += hidraw
>  obj-$(CONFIG_SAMPLE_HW_BREAKPOINT)     += hw_breakpoint/
>  obj-$(CONFIG_SAMPLE_KDB)               += kdb/
> diff --git a/samples/fanotify/Makefile b/samples/fanotify/Makefile
> new file mode 100644
> index 000000000000..e20db1bdde3b
> --- /dev/null
> +++ b/samples/fanotify/Makefile
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +userprogs-always-y += fs-monitor
> +
> +userccflags += -I usr/include -Wall
> +
> diff --git a/samples/fanotify/fs-monitor.c b/samples/fanotify/fs-monitor.c
> new file mode 100644
> index 000000000000..ff74ba077f34
> --- /dev/null
> +++ b/samples/fanotify/fs-monitor.c
> @@ -0,0 +1,134 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2021, Collabora Ltd.
> + */
> +
> +#define _GNU_SOURCE
> +#include <errno.h>
> +#include <err.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <fcntl.h>
> +#include <sys/fanotify.h>
> +#include <sys/types.h>
> +#include <unistd.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +
> +#ifndef FAN_FS_ERROR
> +#define FAN_FS_ERROR           0x00008000
> +#define FAN_EVENT_INFO_TYPE_ERROR      4
> +
> +#define FILEID_INO32_GEN       1
> +#define        FILEID_INVALID          0xff

If you install the kernel uapi header and try to build this
sample it will fail because FAN_FS_ERROR will be
defined but FILEID_INO32_GEN and FILEID_INVALID
will not be defined.

Thanks,
Amir.

> +
> +struct fanotify_event_info_error {
> +       struct fanotify_event_info_header hdr;
> +       __s32 error;
> +       __u32 error_count;
> +};
> +#endif
> +
> +static void print_fh(struct file_handle *fh)
> +{
> +       int i;
> +       uint32_t *h = (uint32_t *) fh->f_handle;
> +
> +       printf("\tfh: ");
> +       for (i = 0; i < fh->handle_bytes; i++)
> +               printf("%hhx", fh->f_handle[i]);
> +       printf("\n");
> +
> +       printf("\tdecoded fh: ");
> +       if (fh->handle_type == FILEID_INO32_GEN)
> +               printf("inode=%u gen=%u\n", h[0], h[1]);
> +       else if (fh->handle_type == FILEID_INVALID && !h[0] && !h[1])
> +               printf("Type %d (Superblock error)\n", fh->handle_type);
> +       else
> +               printf("Type %d (Unknown)\n", fh->handle_type);
> +
> +}
> +
> +static void handle_notifications(char *buffer, int len)
> +{
> +       struct fanotify_event_metadata *metadata;
> +       struct fanotify_event_info_error *error;
> +       struct fanotify_event_info_fid *fid;
> +       char *next;
> +
> +       for (metadata = (struct fanotify_event_metadata *) buffer;
> +            FAN_EVENT_OK(metadata, len);
> +            metadata = FAN_EVENT_NEXT(metadata, len)) {
> +               next = (char *)metadata + metadata->event_len;
> +               if (metadata->mask != FAN_FS_ERROR) {
> +                       printf("unexpected FAN MARK: %llx\n", metadata->mask);
> +                       goto next_event;
> +               } else if (metadata->fd != FAN_NOFD) {
> +                       printf("Unexpected fd (!= FAN_NOFD)\n");
> +                       goto next_event;
> +               }
> +
> +               printf("FAN_FS_ERROR found len=%d\n", metadata->event_len);
> +
> +               error = (struct fanotify_event_info_error *) (metadata+1);
> +               if (error->hdr.info_type != FAN_EVENT_INFO_TYPE_ERROR) {
> +                       printf("unknown record: %d (Expecting TYPE_ERROR)\n",
> +                              error->hdr.info_type);
> +                       goto next_event;
> +               }
> +
> +               printf("\tGeneric Error Record: len=%d\n", error->hdr.len);
> +               printf("\terror: %d\n", error->error);
> +               printf("\terror_count: %d\n", error->error_count);
> +
> +               fid = (struct fanotify_event_info_fid *) (error + 1);
> +               if ((char *) fid >= next) {
> +                       printf("Event doesn't have FID\n");
> +                       goto next_event;
> +               }
> +               printf("FID record found\n");
> +
> +               if (fid->hdr.info_type != FAN_EVENT_INFO_TYPE_FID) {
> +                       printf("unknown record: %d (Expecting TYPE_FID)\n",
> +                              fid->hdr.info_type);
> +                       goto next_event;
> +               }
> +               printf("\tfsid: %x%x\n", fid->fsid.val[0], fid->fsid.val[1]);
> +               print_fh((struct file_handle *) &fid->handle);
> +
> +next_event:
> +               printf("---\n\n");
> +       }
> +}
> +
> +int main(int argc, char **argv)
> +{
> +       int fd;
> +
> +       char buffer[BUFSIZ];
> +
> +       if (argc < 2) {
> +               printf("Missing path argument\n");
> +               return 1;
> +       }
> +
> +       fd = fanotify_init(FAN_CLASS_NOTIF|FAN_REPORT_FID, O_RDONLY);
> +       if (fd < 0)
> +               errx(1, "fanotify_init");
> +
> +       if (fanotify_mark(fd, FAN_MARK_ADD|FAN_MARK_FILESYSTEM,
> +                         FAN_FS_ERROR, AT_FDCWD, argv[1])) {
> +               errx(1, "fanotify_mark");
> +       }
> +
> +       while (1) {
> +               int n = read(fd, buffer, BUFSIZ);
> +
> +               if (n < 0)
> +                       errx(1, "read");
> +
> +               handle_notifications(buffer, n);
> +       }
> +
> +       return 0;
> +}
> --
> 2.32.0
>



[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux