Skip to content

Commit 5451093

Browse files
krisman-at-collaborajankara
authored andcommitted
samples: Add fs error monitoring example
Introduce an example of a FAN_FS_ERROR fanotify user to track filesystem errors. Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Amir Goldstein <[email protected]> Reviewed-by: Jan Kara <[email protected]> Signed-off-by: Gabriel Krisman Bertazi <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 9a089b2 commit 5451093

File tree

4 files changed

+157
-0
lines changed

4 files changed

+157
-0
lines changed

samples/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,15 @@ config SAMPLE_CONNECTOR
120120
with it.
121121
See also Documentation/driver-api/connector.rst
122122

123+
config SAMPLE_FANOTIFY_ERROR
124+
bool "Build fanotify error monitoring sample"
125+
depends on FANOTIFY
126+
help
127+
When enabled, this builds an example code that uses the
128+
FAN_FS_ERROR fanotify mechanism to monitor filesystem
129+
errors.
130+
See also Documentation/admin-guide/filesystem-monitoring.rst.
131+
123132
config SAMPLE_HIDRAW
124133
bool "hidraw sample"
125134
depends on CC_CAN_LINK && HEADERS_INSTALL

samples/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ subdir-$(CONFIG_SAMPLE_AUXDISPLAY) += auxdisplay
55
subdir-$(CONFIG_SAMPLE_ANDROID_BINDERFS) += binderfs
66
obj-$(CONFIG_SAMPLE_CONFIGFS) += configfs/
77
obj-$(CONFIG_SAMPLE_CONNECTOR) += connector/
8+
obj-$(CONFIG_SAMPLE_FANOTIFY_ERROR) += fanotify/
89
subdir-$(CONFIG_SAMPLE_HIDRAW) += hidraw
910
obj-$(CONFIG_SAMPLE_HW_BREAKPOINT) += hw_breakpoint/
1011
obj-$(CONFIG_SAMPLE_KDB) += kdb/

samples/fanotify/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
userprogs-always-y += fs-monitor
3+
4+
userccflags += -I usr/include -Wall
5+

samples/fanotify/fs-monitor.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright 2021, Collabora Ltd.
4+
*/
5+
6+
#define _GNU_SOURCE
7+
#include <errno.h>
8+
#include <err.h>
9+
#include <stdlib.h>
10+
#include <stdio.h>
11+
#include <fcntl.h>
12+
#include <sys/fanotify.h>
13+
#include <sys/types.h>
14+
#include <unistd.h>
15+
#include <sys/types.h>
16+
17+
#ifndef FAN_FS_ERROR
18+
#define FAN_FS_ERROR 0x00008000
19+
#define FAN_EVENT_INFO_TYPE_ERROR 5
20+
21+
struct fanotify_event_info_error {
22+
struct fanotify_event_info_header hdr;
23+
__s32 error;
24+
__u32 error_count;
25+
};
26+
#endif
27+
28+
#ifndef FILEID_INO32_GEN
29+
#define FILEID_INO32_GEN 1
30+
#endif
31+
32+
#ifndef FILEID_INVALID
33+
#define FILEID_INVALID 0xff
34+
#endif
35+
36+
static void print_fh(struct file_handle *fh)
37+
{
38+
int i;
39+
uint32_t *h = (uint32_t *) fh->f_handle;
40+
41+
printf("\tfh: ");
42+
for (i = 0; i < fh->handle_bytes; i++)
43+
printf("%hhx", fh->f_handle[i]);
44+
printf("\n");
45+
46+
printf("\tdecoded fh: ");
47+
if (fh->handle_type == FILEID_INO32_GEN)
48+
printf("inode=%u gen=%u\n", h[0], h[1]);
49+
else if (fh->handle_type == FILEID_INVALID && !fh->handle_bytes)
50+
printf("Type %d (Superblock error)\n", fh->handle_type);
51+
else
52+
printf("Type %d (Unknown)\n", fh->handle_type);
53+
54+
}
55+
56+
static void handle_notifications(char *buffer, int len)
57+
{
58+
struct fanotify_event_metadata *event =
59+
(struct fanotify_event_metadata *) buffer;
60+
struct fanotify_event_info_header *info;
61+
struct fanotify_event_info_error *err;
62+
struct fanotify_event_info_fid *fid;
63+
int off;
64+
65+
for (; FAN_EVENT_OK(event, len); event = FAN_EVENT_NEXT(event, len)) {
66+
67+
if (event->mask != FAN_FS_ERROR) {
68+
printf("unexpected FAN MARK: %llx\n", event->mask);
69+
goto next_event;
70+
}
71+
72+
if (event->fd != FAN_NOFD) {
73+
printf("Unexpected fd (!= FAN_NOFD)\n");
74+
goto next_event;
75+
}
76+
77+
printf("FAN_FS_ERROR (len=%d)\n", event->event_len);
78+
79+
for (off = sizeof(*event) ; off < event->event_len;
80+
off += info->len) {
81+
info = (struct fanotify_event_info_header *)
82+
((char *) event + off);
83+
84+
switch (info->info_type) {
85+
case FAN_EVENT_INFO_TYPE_ERROR:
86+
err = (struct fanotify_event_info_error *) info;
87+
88+
printf("\tGeneric Error Record: len=%d\n",
89+
err->hdr.len);
90+
printf("\terror: %d\n", err->error);
91+
printf("\terror_count: %d\n", err->error_count);
92+
break;
93+
94+
case FAN_EVENT_INFO_TYPE_FID:
95+
fid = (struct fanotify_event_info_fid *) info;
96+
97+
printf("\tfsid: %x%x\n",
98+
fid->fsid.val[0], fid->fsid.val[1]);
99+
print_fh((struct file_handle *) &fid->handle);
100+
break;
101+
102+
default:
103+
printf("\tUnknown info type=%d len=%d:\n",
104+
info->info_type, info->len);
105+
}
106+
}
107+
next_event:
108+
printf("---\n\n");
109+
}
110+
}
111+
112+
int main(int argc, char **argv)
113+
{
114+
int fd;
115+
116+
char buffer[BUFSIZ];
117+
118+
if (argc < 2) {
119+
printf("Missing path argument\n");
120+
return 1;
121+
}
122+
123+
fd = fanotify_init(FAN_CLASS_NOTIF|FAN_REPORT_FID, O_RDONLY);
124+
if (fd < 0)
125+
errx(1, "fanotify_init");
126+
127+
if (fanotify_mark(fd, FAN_MARK_ADD|FAN_MARK_FILESYSTEM,
128+
FAN_FS_ERROR, AT_FDCWD, argv[1])) {
129+
errx(1, "fanotify_mark");
130+
}
131+
132+
while (1) {
133+
int n = read(fd, buffer, BUFSIZ);
134+
135+
if (n < 0)
136+
errx(1, "read");
137+
138+
handle_notifications(buffer, n);
139+
}
140+
141+
return 0;
142+
}

0 commit comments

Comments
 (0)