fsnotify: Support FS_ERROR event type
authorGabriel Krisman Bertazi <krisman@collabora.com>
Mon, 25 Oct 2021 19:27:32 +0000 (16:27 -0300)
committerJan Kara <jack@suse.cz>
Wed, 27 Oct 2021 10:34:49 +0000 (12:34 +0200)
Expose a new type of fsnotify event for filesystems to report errors for
userspace monitoring tools.  fanotify will send this type of
notification for FAN_FS_ERROR events.  This also introduce a helper for
generating the new event.

Link: https://lore.kernel.org/r/20211025192746.66445-18-krisman@collabora.com
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
Signed-off-by: Jan Kara <jack@suse.cz>
include/linux/fsnotify.h
include/linux/fsnotify_backend.h

index 1e5f743..787545e 100644 (file)
@@ -339,4 +339,17 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
                fsnotify_dentry(dentry, mask);
 }
 
+static inline int fsnotify_sb_error(struct super_block *sb, struct inode *inode,
+                                   int error)
+{
+       struct fs_error_report report = {
+               .error = error,
+               .inode = inode,
+               .sb = sb,
+       };
+
+       return fsnotify(FS_ERROR, &report, FSNOTIFY_EVENT_ERROR,
+                       NULL, NULL, NULL, 0);
+}
+
 #endif /* _LINUX_FS_NOTIFY_H */
index 3a7c314..00dbaaf 100644 (file)
 
 #define FS_UNMOUNT             0x00002000      /* inode on umount fs */
 #define FS_Q_OVERFLOW          0x00004000      /* Event queued overflowed */
+#define FS_ERROR               0x00008000      /* Filesystem Error (fanotify) */
+
+/*
+ * FS_IN_IGNORED overloads FS_ERROR.  It is only used internally by inotify
+ * which does not support FS_ERROR.
+ */
 #define FS_IN_IGNORED          0x00008000      /* last inotify event here */
 
 #define FS_OPEN_PERM           0x00010000      /* open event in an permission hook */
 #define ALL_FSNOTIFY_EVENTS (ALL_FSNOTIFY_DIRENT_EVENTS | \
                             FS_EVENTS_POSS_ON_CHILD | \
                             FS_DELETE_SELF | FS_MOVE_SELF | FS_DN_RENAME | \
-                            FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED)
+                            FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \
+                            FS_ERROR)
 
 /* Extra flags that may be reported with event or control handling of events */
 #define ALL_FSNOTIFY_FLAGS  (FS_EXCL_UNLINK | FS_ISDIR | FS_IN_ONESHOT | \
@@ -250,6 +257,13 @@ enum fsnotify_data_type {
        FSNOTIFY_EVENT_PATH,
        FSNOTIFY_EVENT_INODE,
        FSNOTIFY_EVENT_DENTRY,
+       FSNOTIFY_EVENT_ERROR,
+};
+
+struct fs_error_report {
+       int error;
+       struct inode *inode;
+       struct super_block *sb;
 };
 
 static inline struct inode *fsnotify_data_inode(const void *data, int data_type)
@@ -261,6 +275,8 @@ static inline struct inode *fsnotify_data_inode(const void *data, int data_type)
                return d_inode(data);
        case FSNOTIFY_EVENT_PATH:
                return d_inode(((const struct path *)data)->dentry);
+       case FSNOTIFY_EVENT_ERROR:
+               return ((struct fs_error_report *)data)->inode;
        default:
                return NULL;
        }
@@ -300,6 +316,20 @@ static inline struct super_block *fsnotify_data_sb(const void *data,
                return ((struct dentry *)data)->d_sb;
        case FSNOTIFY_EVENT_PATH:
                return ((const struct path *)data)->dentry->d_sb;
+       case FSNOTIFY_EVENT_ERROR:
+               return ((struct fs_error_report *) data)->sb;
+       default:
+               return NULL;
+       }
+}
+
+static inline struct fs_error_report *fsnotify_data_error_report(
+                                                       const void *data,
+                                                       int data_type)
+{
+       switch (data_type) {
+       case FSNOTIFY_EVENT_ERROR:
+               return (struct fs_error_report *) data;
        default:
                return NULL;
        }