All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gabriel Krisman Bertazi <krisman@collabora.com>
To: amir73il@gmail.com, tytso@mit.edu, djwong@kernel.org
Cc: david@fromorbit.com, jack@suse.com, dhowells@redhat.com,
	khazhy@google.com, linux-fsdevel@vger.kernel.org,
	linux-ext4@vger.kernel.org,
	Gabriel Krisman Bertazi <krisman@collabora.com>,
	kernel@collabora.com
Subject: [PATCH RFC 12/15] fanotify: Introduce the FAN_ERROR mark
Date: Mon, 26 Apr 2021 14:41:58 -0400	[thread overview]
Message-ID: <20210426184201.4177978-13-krisman@collabora.com> (raw)
In-Reply-To: <20210426184201.4177978-1-krisman@collabora.com>

The FAN_ERROR mark is used by filesystem wide monitoring tools to
receive notifications of type FS_ERROR_EVENT, emited by filesystems when
a problem is detected.  The error notification includes a generic error
descriptor, an optional location record and a filesystem specific blob.

Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
---
 fs/notify/fanotify/fanotify.c      | 48 +++++++++++++++++++----
 fs/notify/fanotify/fanotify.h      |  8 ++++
 fs/notify/fanotify/fanotify_user.c | 63 ++++++++++++++++++++++++++++++
 include/linux/fanotify.h           |  9 ++++-
 include/uapi/linux/fanotify.h      |  2 +
 5 files changed, 120 insertions(+), 10 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 98591a8155a7..6bae23d42e5e 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -240,12 +240,14 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
 		 __func__, iter_info->report_mask, event_mask, data, data_type);
 
 	if (!fid_mode) {
-		/* Do we have path to open a file descriptor? */
-		if (!path)
-			return 0;
-		/* Path type events are only relevant for files and dirs */
-		if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry))
-			return 0;
+		if (!fanotify_is_error_event(event_mask)) {
+			/* Do we have path to open a file descriptor? */
+			if (!path)
+				return 0;
+			/* Path type events are only relevant for files and dirs */
+			if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry))
+				return 0;
+		}
 	} else if (!(fid_mode & FAN_REPORT_FID)) {
 		/* Do we have a directory inode to report? */
 		if (!dir && !(event_mask & FS_ISDIR))
@@ -458,6 +460,25 @@ static struct fanotify_event *fanotify_alloc_perm_event(const struct path *path,
 	return &pevent->fae;
 }
 
+static void fanotify_init_error_event(struct fanotify_event *fae,
+				      const struct fs_error_report *report,
+				      __kernel_fsid_t *fsid)
+{
+	struct fanotify_error_event *fee;
+
+	fae->type = FANOTIFY_EVENT_TYPE_ERROR;
+	fee = FANOTIFY_EE(fae);
+	fee->error = report->error;
+	fee->fsid = *fsid;
+
+	fee->loc.line = report->line;
+	fee->loc.function = report->function;
+
+	fee->fs_data_size = report->fs_data_size;
+
+	memcpy(&fee->fs_data, report->fs_data, report->fs_data_size);
+}
+
 static struct fanotify_event *fanotify_alloc_fid_event(struct inode *id,
 						       __kernel_fsid_t *fsid,
 						       gfp_t gfp)
@@ -618,6 +639,13 @@ static struct fanotify_event *fanotify_ring_get_slot(struct fsnotify_group *grou
 {
 	size_t size = 0;
 
+	if (fanotify_is_error_event(mask)) {
+		const struct fs_error_report *report = data;
+		size = sizeof(struct fanotify_error_event) + report->fs_data_size;
+	} else {
+		return ERR_PTR(-EINVAL);
+	}
+
 	pr_debug("%s: group=%p mask=%x size=%lu\n", __func__, group, mask, size);
 
 	return FANOTIFY_E(fsnotify_ring_alloc_event_slot(group, size));
@@ -629,6 +657,9 @@ static void fanotify_ring_write_event(struct fsnotify_group *group,
 {
 	fanotify_init_event(group, event, 0, mask);
 
+	if (fanotify_is_error_event(mask))
+		fanotify_init_error_event(event, data, fsid);
+
 	event->pid = get_pid(task_tgid(current));
 }
 
@@ -695,8 +726,9 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
 	BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
 	BUILD_BUG_ON(FAN_OPEN_EXEC != FS_OPEN_EXEC);
 	BUILD_BUG_ON(FAN_OPEN_EXEC_PERM != FS_OPEN_EXEC_PERM);
+	BUILD_BUG_ON(FAN_ERROR != FS_ERROR);
 
-	BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 19);
+	BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 20);
 
 	mask = fanotify_group_event_mask(group, iter_info, mask, data,
 					 data_type, dir);
@@ -714,7 +746,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
 			return 0;
 	}
 
-	if (FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS)) {
+	if (FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS) || mask == FAN_ERROR) {
 		fsid = fanotify_get_fsid(iter_info);
 		/* Racing with mark destruction or creation? */
 		if (!fsid.val[0] && !fsid.val[1])
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 0d1b4cb8b005..097667be9079 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -135,6 +135,7 @@ enum fanotify_event_type {
 	FANOTIFY_EVENT_TYPE_PATH,
 	FANOTIFY_EVENT_TYPE_PATH_PERM,
 	FANOTIFY_EVENT_TYPE_OVERFLOW, /* struct fanotify_event */
+	FANOTIFY_EVENT_TYPE_ERROR,
 };
 
 struct fanotify_event {
@@ -207,6 +208,8 @@ static inline __kernel_fsid_t *fanotify_event_fsid(struct fanotify_event *event)
 		return &FANOTIFY_FE(event)->fsid;
 	else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME)
 		return &FANOTIFY_NE(event)->fsid;
+	else if (event->type == FANOTIFY_EVENT_TYPE_ERROR)
+		return &FANOTIFY_EE(event)->fsid;
 	else
 		return NULL;
 }
@@ -292,6 +295,11 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
 	return container_of(fse, struct fanotify_event, fse);
 }
 
+static inline bool fanotify_is_error_event(u32 mask)
+{
+	return mask & FANOTIFY_ERROR_EVENTS;
+}
+
 static inline bool fanotify_event_has_path(struct fanotify_event *event)
 {
 	return event->type == FANOTIFY_EVENT_TYPE_PATH ||
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index e2f4599dfc25..6270083bee36 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -96,6 +96,24 @@ static size_t fanotify_event_len(struct fanotify_event *event,
 	int fh_len;
 	int dot_len = 0;
 
+	if (fanotify_is_error_event(event->mask)) {
+		struct fanotify_error_event *fee = FANOTIFY_EE(event);
+		/*
+		 *  Error events (FAN_ERROR) have a different format
+		 *  as follows:
+		 * [ event_metadata            ]
+		 * [ fs-generic error header   ]
+		 * [ error location (optional) ]
+		 * [ fs-specific blob          ]
+		 */
+		event_len = fanotify_error_info_len(fee);
+		if (fee->loc.function)
+			event_len += fanotify_location_info_len(&fee->loc);
+		if (fee->fs_data)
+			event_len += fanotify_error_fsdata_len(fee);
+		return event_len;
+	}
+
 	if (!fid_mode)
 		return event_len;
 
@@ -322,6 +340,38 @@ static ssize_t copy_error_fsdata_info_to_user(struct fanotify_error_event *fee,
 	return info.hdr.len;
 }
 
+static int copy_error_event_to_user(struct fanotify_event *event,
+				    char __user *buf, int count)
+{
+	struct fanotify_error_event *fee = FANOTIFY_EE(event);
+	ssize_t len;
+	int original_count = count;
+
+	len = copy_error_info_to_user(fee, buf, count);
+	if (len < 0)
+		return -EFAULT;
+	buf += len;
+	count -= len;
+
+	if (fee->loc.function) {
+		len = copy_location_info_to_user(&fee->loc, buf, count);
+		if (len < 0)
+			return len;
+		buf += len;
+		count -= len;
+	}
+
+	if (fee->fs_data_size) {
+		len = copy_error_fsdata_info_to_user(fee, buf, count);
+		if (len < 0)
+			return len;
+		buf += len;
+		count -= len;
+	}
+
+	return original_count - count;
+}
+
 static int copy_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh,
 			     int info_type, const char *name, size_t name_len,
 			     char __user *buf, size_t count)
@@ -528,6 +578,9 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 		count -= ret;
 	}
 
+	if (fanotify_is_error_event(event->mask))
+		ret = copy_error_event_to_user(event, buf, count);
+
 	return metadata.event_len;
 
 out_close_fd:
@@ -1328,6 +1381,10 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 	    (mask & ~FANOTIFY_SUBMISSION_BUFFER_EVENTS))
 		goto fput_and_out;
 
+	if (fanotify_is_error_event(mask) &&
+	    !(group->flags & FSN_SUBMISSION_RING_BUFFER))
+		goto fput_and_out;
+
 	ret = fanotify_find_path(dfd, pathname, &path, flags,
 			(mask & ALL_FSNOTIFY_EVENTS), obj_type);
 	if (ret)
@@ -1350,6 +1407,12 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 
 		fsid = &__fsid;
 	}
+	if (mask & FAN_ERROR) {
+		ret = fanotify_check_path_fsid(&path, &__fsid);
+		if (ret)
+			goto path_put_and_out;
+		fsid = &__fsid;
+	}
 
 	/* inode held in place by reference to path; group by fget on fd */
 	if (mark_type == FAN_MARK_INODE)
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index 5a4cefb4b1c3..e08be5fae14a 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -56,9 +56,13 @@
 #define FANOTIFY_INODE_EVENTS	(FANOTIFY_DIRENT_EVENTS | \
 				 FAN_ATTRIB | FAN_MOVE_SELF | FAN_DELETE_SELF)
 
+#define FANOTIFY_ERROR_EVENTS	(FAN_ERROR)
+
 /* Events that user can request to be notified on */
 #define FANOTIFY_EVENTS		(FANOTIFY_PATH_EVENTS | \
-				 FANOTIFY_INODE_EVENTS)
+				 FANOTIFY_INODE_EVENTS | \
+				 FANOTIFY_ERROR_EVENTS)
+
 
 /* Events that require a permission response from user */
 #define FANOTIFY_PERM_EVENTS	(FAN_OPEN_PERM | FAN_ACCESS_PERM | \
@@ -70,9 +74,10 @@
 /* Events that may be reported to user */
 #define FANOTIFY_OUTGOING_EVENTS	(FANOTIFY_EVENTS | \
 					 FANOTIFY_PERM_EVENTS | \
+					 FANOTIFY_ERROR_EVENTS | \
 					 FAN_Q_OVERFLOW | FAN_ONDIR)
 
-#define FANOTIFY_SUBMISSION_BUFFER_EVENTS 0
+#define FANOTIFY_SUBMISSION_BUFFER_EVENTS FANOTIFY_ERROR_EVENTS
 
 #define ALL_FANOTIFY_EVENT_BITS		(FANOTIFY_OUTGOING_EVENTS | \
 					 FANOTIFY_EVENT_FLAGS)
diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h
index 49808c857ee1..ee0ae8b1e20b 100644
--- a/include/uapi/linux/fanotify.h
+++ b/include/uapi/linux/fanotify.h
@@ -25,6 +25,8 @@
 #define FAN_ACCESS_PERM		0x00020000	/* File accessed in perm check */
 #define FAN_OPEN_EXEC_PERM	0x00040000	/* File open/exec in perm check */
 
+#define FAN_ERROR		0x00100000	/* Filesystem error */
+
 #define FAN_EVENT_ON_CHILD	0x08000000	/* Interested in child events */
 
 #define FAN_ONDIR		0x40000000	/* Event occurred against dir */
-- 
2.31.0


  parent reply	other threads:[~2021-04-26 18:45 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-26 18:41 [PATCH RFC 00/15] File system wide monitoring Gabriel Krisman Bertazi
2021-04-26 18:41 ` [PATCH RFC 01/15] fanotify: Fold event size calculation to its own function Gabriel Krisman Bertazi
2021-04-27  4:42   ` Amir Goldstein
2021-04-26 18:41 ` [PATCH RFC 02/15] fanotify: Split fsid check from other fid mode checks Gabriel Krisman Bertazi
2021-04-27  4:53   ` Amir Goldstein
2021-04-26 18:41 ` [PATCH RFC 03/15] fsnotify: Wire flags field on group allocation Gabriel Krisman Bertazi
2021-04-27  5:03   ` Amir Goldstein
2021-04-26 18:41 ` [PATCH RFC 04/15] fsnotify: Wire up group information on event initialization Gabriel Krisman Bertazi
2021-04-26 18:41 ` [PATCH RFC 05/15] fsnotify: Support event submission through ring buffer Gabriel Krisman Bertazi
2021-04-26 22:00   ` kernel test robot
2021-04-26 22:43   ` kernel test robot
2021-04-27  5:39   ` Amir Goldstein
2021-04-29 18:33     ` Gabriel Krisman Bertazi
2021-04-26 18:41 ` [PATCH RFC 06/15] fanotify: Support " Gabriel Krisman Bertazi
2021-04-27  6:02   ` Amir Goldstein
2021-04-29 18:36     ` Gabriel Krisman Bertazi
2021-04-26 18:41 ` [PATCH RFC 07/15] fsnotify: Support FS_ERROR event type Gabriel Krisman Bertazi
2021-04-27  8:39   ` Amir Goldstein
2021-04-26 18:41 ` [PATCH RFC 08/15] fsnotify: Introduce helpers to send error_events Gabriel Krisman Bertazi
2021-04-27  6:49   ` Amir Goldstein
2021-04-26 18:41 ` [PATCH RFC 09/15] fanotify: Introduce generic error record Gabriel Krisman Bertazi
2021-04-27  7:01   ` Amir Goldstein
2021-04-26 18:41 ` [PATCH RFC 10/15] fanotify: Introduce code location record Gabriel Krisman Bertazi
2021-04-27  7:11   ` Amir Goldstein
2021-04-29 18:40     ` Gabriel Krisman Bertazi
2021-05-11  5:35       ` Khazhy Kumykov
2021-04-26 18:41 ` [PATCH RFC 11/15] fanotify: Introduce filesystem specific data record Gabriel Krisman Bertazi
2021-04-27  7:12   ` Amir Goldstein
2021-04-26 18:41 ` Gabriel Krisman Bertazi [this message]
2021-04-26 22:45   ` [PATCH RFC 12/15] fanotify: Introduce the FAN_ERROR mark kernel test robot
2021-04-27  7:25   ` Amir Goldstein
2021-04-26 18:41 ` [PATCH RFC 13/15] ext4: Send notifications on error Gabriel Krisman Bertazi
2021-04-26 23:10   ` kernel test robot
2021-04-27  4:32   ` Amir Goldstein
2021-04-29  0:57   ` Darrick J. Wong
2021-04-26 18:42 ` [PATCH RFC 14/15] samples: Add fs error monitoring example Gabriel Krisman Bertazi
2021-04-26 23:10   ` kernel test robot
2021-04-26 18:42 ` [PATCH RFC 15/15] Documentation: Document the FAN_ERROR framework Gabriel Krisman Bertazi
2021-04-27  4:11 ` [PATCH RFC 00/15] File system wide monitoring Amir Goldstein
2021-04-27 15:44   ` Gabriel Krisman Bertazi
2021-05-11  4:45     ` Khazhy Kumykov
2021-05-11 10:43   ` Jan Kara
2021-04-27  4:33 [PATCH RFC 12/15] fanotify: Introduce the FAN_ERROR mark kernel test robot
2021-04-29 11:31 ` Dan Carpenter
2021-04-27  8:36 [PATCH RFC 13/15] ext4: Send notifications on error kernel test robot
2021-04-29 13:19 ` Dan Carpenter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210426184201.4177978-13-krisman@collabora.com \
    --to=krisman@collabora.com \
    --cc=amir73il@gmail.com \
    --cc=david@fromorbit.com \
    --cc=dhowells@redhat.com \
    --cc=djwong@kernel.org \
    --cc=jack@suse.com \
    --cc=kernel@collabora.com \
    --cc=khazhy@google.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.