fanotify: clear all fanotify marks
[deliverable/linux.git] / fs / notify / fanotify / fanotify_user.c
index 84155841a0256fb6481d91557c67187e3f6c200a..9fe760baf69fcd35c9bd1e2cbc70d5045fad8815 100644 (file)
@@ -296,13 +296,20 @@ out:
        return ret;
 }
 
-static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, __u32 mask)
+static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
+                                           __u32 mask,
+                                           unsigned int flags)
 {
        __u32 oldmask;
 
        spin_lock(&fsn_mark->lock);
-       oldmask = fsn_mark->mask;
-       fsn_mark->mask = oldmask & ~mask;
+       if (!(flags & FAN_MARK_IGNORED_MASK)) {
+               oldmask = fsn_mark->mask;
+               fsnotify_set_mark_mask_locked(fsn_mark, (oldmask & ~mask));
+       } else {
+               oldmask = fsn_mark->ignored_mask;
+               fsnotify_set_mark_ignored_mask_locked(fsn_mark, (oldmask & ~mask));
+       }
        spin_unlock(&fsn_mark->lock);
 
        if (!(oldmask & ~mask))
@@ -312,7 +319,8 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, __u3
 }
 
 static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
-                                        struct vfsmount *mnt, __u32 mask)
+                                        struct vfsmount *mnt, __u32 mask,
+                                        unsigned int flags)
 {
        struct fsnotify_mark *fsn_mark = NULL;
        __u32 removed;
@@ -321,7 +329,7 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
        if (!fsn_mark)
                return -ENOENT;
 
-       removed = fanotify_mark_remove_from_mask(fsn_mark, mask);
+       removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
        fsnotify_put_mark(fsn_mark);
        if (removed & group->mask)
                fsnotify_recalc_group_mask(group);
@@ -332,7 +340,8 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
 }
 
 static int fanotify_remove_inode_mark(struct fsnotify_group *group,
-                                     struct inode *inode, __u32 mask)
+                                     struct inode *inode, __u32 mask,
+                                     unsigned int flags)
 {
        struct fsnotify_mark *fsn_mark = NULL;
        __u32 removed;
@@ -341,7 +350,7 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
        if (!fsn_mark)
                return -ENOENT;
 
-       removed = fanotify_mark_remove_from_mask(fsn_mark, mask);
+       removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
        /* matches the fsnotify_find_inode_mark() */
        fsnotify_put_mark(fsn_mark);
 
@@ -353,20 +362,30 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
        return 0;
 }
 
-static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, __u32 mask)
+static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
+                                      __u32 mask,
+                                      unsigned int flags)
 {
        __u32 oldmask;
 
        spin_lock(&fsn_mark->lock);
-       oldmask = fsn_mark->mask;
-       fsn_mark->mask = oldmask | mask;
+       if (!(flags & FAN_MARK_IGNORED_MASK)) {
+               oldmask = fsn_mark->mask;
+               fsnotify_set_mark_mask_locked(fsn_mark, (oldmask | mask));
+       } else {
+               oldmask = fsn_mark->ignored_mask;
+               fsnotify_set_mark_ignored_mask_locked(fsn_mark, (oldmask | mask));
+               if (flags & FAN_MARK_IGNORED_SURV_MODIFY)
+                       fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
+       }
        spin_unlock(&fsn_mark->lock);
 
        return mask & ~oldmask;
 }
 
 static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
-                                     struct vfsmount *mnt, __u32 mask)
+                                     struct vfsmount *mnt, __u32 mask,
+                                     unsigned int flags)
 {
        struct fsnotify_mark *fsn_mark;
        __u32 added;
@@ -386,7 +405,7 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
                        return ret;
                }
        }
-       added = fanotify_mark_add_to_mask(fsn_mark, mask);
+       added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
        fsnotify_put_mark(fsn_mark);
        if (added) {
                if (added & ~group->mask)
@@ -398,7 +417,8 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 }
 
 static int fanotify_add_inode_mark(struct fsnotify_group *group,
-                                  struct inode *inode, __u32 mask)
+                                  struct inode *inode, __u32 mask,
+                                  unsigned int flags)
 {
        struct fsnotify_mark *fsn_mark;
        __u32 added;
@@ -420,7 +440,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
                        return ret;
                }
        }
-       added = fanotify_mark_add_to_mask(fsn_mark, mask);
+       added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
        fsnotify_put_mark(fsn_mark);
        if (added) {
                if (added & ~group->mask)
@@ -494,9 +514,10 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
 
        if (flags & ~FAN_ALL_MARK_FLAGS)
                return -EINVAL;
-       switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
+       switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
        case FAN_MARK_ADD:
        case FAN_MARK_REMOVE:
+       case FAN_MARK_FLUSH:
                break;
        default:
                return -EINVAL;
@@ -525,18 +546,25 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
        group = filp->private_data;
 
        /* create/update an inode mark */
-       switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
+       switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
        case FAN_MARK_ADD:
                if (flags & FAN_MARK_MOUNT)
-                       ret = fanotify_add_vfsmount_mark(group, mnt, mask);
+                       ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags);
                else
-                       ret = fanotify_add_inode_mark(group, inode, mask);
+                       ret = fanotify_add_inode_mark(group, inode, mask, flags);
                break;
        case FAN_MARK_REMOVE:
                if (flags & FAN_MARK_MOUNT)
-                       ret = fanotify_remove_vfsmount_mark(group, mnt, mask);
+                       ret = fanotify_remove_vfsmount_mark(group, mnt, mask, flags);
                else
-                       ret = fanotify_remove_inode_mark(group, inode, mask);
+                       ret = fanotify_remove_inode_mark(group, inode, mask, flags);
+               break;
+       case FAN_MARK_FLUSH:
+               if (flags & FAN_MARK_MOUNT)
+                       fsnotify_clear_vfsmount_marks_by_group(group);
+               else
+                       fsnotify_clear_inode_marks_by_group(group);
+               fsnotify_recalc_group_mask(group);
                break;
        default:
                ret = -EINVAL;
This page took 0.025677 seconds and 5 git commands to generate.