]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
fanotify: add API to attach/detach super block mark
authorAmir Goldstein <amir73il@gmail.com>
Sat, 1 Sep 2018 07:41:13 +0000 (10:41 +0300)
committerJan Kara <jack@suse.cz>
Mon, 3 Sep 2018 13:16:11 +0000 (15:16 +0200)
Add another mark type flag FAN_MARK_FILESYSTEM for add/remove/flush
of super block mark type.

A super block watch gets all events on the filesystem, regardless of
the mount from which the mark was added, unless an ignore mask exists
on either the inode or the mount where the event was generated.

Only one of FAN_MARK_MOUNT and FAN_MARK_FILESYSTEM mark type flags
may be provided to fanotify_mark() or no mark type flag for inode mark.

Cc: <linux-api@vger.kernel.org>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
fs/notify/fanotify/fanotify_user.c
include/uapi/linux/fanotify.h

index 69054886915b6bd2964393089af00037114966ae..1347c588f778ab3545735d136206841b41067007 100644 (file)
@@ -563,6 +563,13 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
                                    mask, flags);
 }
 
+static int fanotify_remove_sb_mark(struct fsnotify_group *group,
+                                     struct super_block *sb, __u32 mask,
+                                     unsigned int flags)
+{
+       return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask, flags);
+}
+
 static int fanotify_remove_inode_mark(struct fsnotify_group *group,
                                      struct inode *inode, __u32 mask,
                                      unsigned int flags)
@@ -658,6 +665,14 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
                                 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags);
 }
 
+static int fanotify_add_sb_mark(struct fsnotify_group *group,
+                                     struct super_block *sb, __u32 mask,
+                                     unsigned int flags)
+{
+       return fanotify_add_mark(group, &sb->s_fsnotify_marks,
+                                FSNOTIFY_OBJ_TYPE_SB, mask, flags);
+}
+
 static int fanotify_add_inode_mark(struct fsnotify_group *group,
                                   struct inode *inode, __u32 mask,
                                   unsigned int flags)
@@ -806,6 +821,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
        struct fd f;
        struct path path;
        u32 valid_mask = FAN_ALL_EVENTS | FAN_EVENT_ON_CHILD;
+       unsigned int mark_type = flags & FAN_MARK_TYPE_MASK;
        int ret;
 
        pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n",
@@ -817,6 +833,16 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 
        if (flags & ~FAN_ALL_MARK_FLAGS)
                return -EINVAL;
+
+       switch (mark_type) {
+       case FAN_MARK_INODE:
+       case FAN_MARK_MOUNT:
+       case FAN_MARK_FILESYSTEM:
+               break;
+       default:
+               return -EINVAL;
+       }
+
        switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
        case FAN_MARK_ADD:              /* fallthrough */
        case FAN_MARK_REMOVE:
@@ -824,7 +850,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
                        return -EINVAL;
                break;
        case FAN_MARK_FLUSH:
-               if (flags & ~(FAN_MARK_MOUNT | FAN_MARK_FLUSH))
+               if (flags & ~(FAN_MARK_TYPE_MASK | FAN_MARK_FLUSH))
                        return -EINVAL;
                break;
        default:
@@ -863,8 +889,10 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 
        if (flags & FAN_MARK_FLUSH) {
                ret = 0;
-               if (flags & FAN_MARK_MOUNT)
+               if (mark_type == FAN_MARK_MOUNT)
                        fsnotify_clear_vfsmount_marks_by_group(group);
+               else if (mark_type == FAN_MARK_FILESYSTEM)
+                       fsnotify_clear_sb_marks_by_group(group);
                else
                        fsnotify_clear_inode_marks_by_group(group);
                goto fput_and_out;
@@ -875,7 +903,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
                goto fput_and_out;
 
        /* inode held in place by reference to path; group by fget on fd */
-       if (!(flags & FAN_MARK_MOUNT))
+       if (mark_type == FAN_MARK_INODE)
                inode = path.dentry->d_inode;
        else
                mnt = path.mnt;
@@ -883,14 +911,18 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
        /* create/update an inode mark */
        switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
        case FAN_MARK_ADD:
-               if (flags & FAN_MARK_MOUNT)
+               if (mark_type == FAN_MARK_MOUNT)
                        ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags);
+               else if (mark_type == FAN_MARK_FILESYSTEM)
+                       ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask, flags);
                else
                        ret = fanotify_add_inode_mark(group, inode, mask, flags);
                break;
        case FAN_MARK_REMOVE:
-               if (flags & FAN_MARK_MOUNT)
+               if (mark_type == FAN_MARK_MOUNT)
                        ret = fanotify_remove_vfsmount_mark(group, mnt, mask, flags);
+               else if (mark_type == FAN_MARK_FILESYSTEM)
+                       ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask, flags);
                else
                        ret = fanotify_remove_inode_mark(group, inode, mask, flags);
                break;
index 74247917de044db54b10ae16584139d85a4db207..ad81234d19199dc8bf57e73e946e4b9c15a3d140 100644 (file)
@@ -27,7 +27,7 @@
 #define FAN_CLOEXEC            0x00000001
 #define FAN_NONBLOCK           0x00000002
 
-/* These are NOT bitwise flags.  Both bits are used togther.  */
+/* These are NOT bitwise flags.  Both bits are used together.  */
 #define FAN_CLASS_NOTIF                0x00000000
 #define FAN_CLASS_CONTENT      0x00000004
 #define FAN_CLASS_PRE_CONTENT  0x00000008
 #define FAN_MARK_REMOVE                0x00000002
 #define FAN_MARK_DONT_FOLLOW   0x00000004
 #define FAN_MARK_ONLYDIR       0x00000008
-#define FAN_MARK_MOUNT         0x00000010
+/* FAN_MARK_MOUNT is           0x00000010 */
 #define FAN_MARK_IGNORED_MASK  0x00000020
 #define FAN_MARK_IGNORED_SURV_MODIFY   0x00000040
 #define FAN_MARK_FLUSH         0x00000080
+/* FAN_MARK_FILESYSTEM is      0x00000100 */
+
+/* These are NOT bitwise flags.  Both bits can be used togther.  */
+#define FAN_MARK_INODE         0x00000000
+#define FAN_MARK_MOUNT         0x00000010
+#define FAN_MARK_FILESYSTEM    0x00000100
+#define FAN_MARK_TYPE_MASK     (FAN_MARK_INODE | FAN_MARK_MOUNT | \
+                                FAN_MARK_FILESYSTEM)
 
 #define FAN_ALL_MARK_FLAGS     (FAN_MARK_ADD |\
                                 FAN_MARK_REMOVE |\
                                 FAN_MARK_DONT_FOLLOW |\
                                 FAN_MARK_ONLYDIR |\
-                                FAN_MARK_MOUNT |\
                                 FAN_MARK_IGNORED_MASK |\
                                 FAN_MARK_IGNORED_SURV_MODIFY |\
-                                FAN_MARK_FLUSH)
+                                FAN_MARK_FLUSH|\
+                                FAN_MARK_TYPE_MASK)
 
 /*
  * All of the events - we build the list by hand so that we can add flags in