LCOV - code coverage report
Current view: top level - fs/notify - fsnotify.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 226 245 92.2 %
Date: 2021-04-22 12:43:58 Functions: 16 16 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  *  Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
       4             :  */
       5             : 
       6             : #include <linux/dcache.h>
       7             : #include <linux/fs.h>
       8             : #include <linux/gfp.h>
       9             : #include <linux/init.h>
      10             : #include <linux/module.h>
      11             : #include <linux/mount.h>
      12             : #include <linux/srcu.h>
      13             : 
      14             : #include <linux/fsnotify_backend.h>
      15             : #include "fsnotify.h"
      16             : 
      17             : /*
      18             :  * Clear all of the marks on an inode when it is being evicted from core
      19             :  */
      20        6618 : void __fsnotify_inode_delete(struct inode *inode)
      21             : {
      22        6618 :         fsnotify_clear_marks_by_inode(inode);
      23        6523 : }
      24             : EXPORT_SYMBOL_GPL(__fsnotify_inode_delete);
      25             : 
      26        1069 : void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
      27             : {
      28        1069 :         fsnotify_clear_marks_by_mount(mnt);
      29        1069 : }
      30             : 
      31             : /**
      32             :  * fsnotify_unmount_inodes - an sb is unmounting.  handle any watched inodes.
      33             :  * @sb: superblock being unmounted.
      34             :  *
      35             :  * Called during unmount with no locks held, so needs to be safe against
      36             :  * concurrent modifiers. We temporarily drop sb->s_inode_list_lock and CAN block.
      37             :  */
      38          98 : static void fsnotify_unmount_inodes(struct super_block *sb)
      39             : {
      40          98 :         struct inode *inode, *iput_inode = NULL;
      41             : 
      42          98 :         spin_lock(&sb->s_inode_list_lock);
      43         193 :         list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
      44             :                 /*
      45             :                  * We cannot __iget() an inode in state I_FREEING,
      46             :                  * I_WILL_FREE, or I_NEW which is fine because by that point
      47             :                  * the inode cannot have any associated watches.
      48             :                  */
      49          95 :                 spin_lock(&inode->i_lock);
      50          95 :                 if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) {
      51           0 :                         spin_unlock(&inode->i_lock);
      52           0 :                         continue;
      53             :                 }
      54             : 
      55             :                 /*
      56             :                  * If i_count is zero, the inode cannot have any watches and
      57             :                  * doing an __iget/iput with SB_ACTIVE clear would actually
      58             :                  * evict all inodes with zero i_count from icache which is
      59             :                  * unnecessarily violent and may in fact be illegal to do.
      60             :                  * However, we should have been called /after/ evict_inodes
      61             :                  * removed all zero refcount inodes, in any case.  Test to
      62             :                  * be sure.
      63             :                  */
      64          95 :                 if (!atomic_read(&inode->i_count)) {
      65           0 :                         spin_unlock(&inode->i_lock);
      66           0 :                         continue;
      67             :                 }
      68             : 
      69          95 :                 __iget(inode);
      70          95 :                 spin_unlock(&inode->i_lock);
      71          95 :                 spin_unlock(&sb->s_inode_list_lock);
      72             : 
      73          95 :                 if (iput_inode)
      74          52 :                         iput(iput_inode);
      75             : 
      76             :                 /* for each watch, send FS_UNMOUNT and then remove it */
      77          95 :                 fsnotify_inode(inode, FS_UNMOUNT);
      78             : 
      79          95 :                 fsnotify_inode_delete(inode);
      80             : 
      81          95 :                 iput_inode = inode;
      82             : 
      83          95 :                 cond_resched();
      84         190 :                 spin_lock(&sb->s_inode_list_lock);
      85             :         }
      86          98 :         spin_unlock(&sb->s_inode_list_lock);
      87             : 
      88          98 :         if (iput_inode)
      89          43 :                 iput(iput_inode);
      90             :         /* Wait for outstanding inode references from connectors */
      91          98 :         wait_var_event(&sb->s_fsnotify_inode_refs,
      92             :                        !atomic_long_read(&sb->s_fsnotify_inode_refs));
      93          98 : }
      94             : 
      95          98 : void fsnotify_sb_delete(struct super_block *sb)
      96             : {
      97          98 :         fsnotify_unmount_inodes(sb);
      98          98 :         fsnotify_clear_marks_by_sb(sb);
      99          98 : }
     100             : 
     101             : /*
     102             :  * Given an inode, first check if we care what happens to our children.  Inotify
     103             :  * and dnotify both tell their parents about events.  If we care about any event
     104             :  * on a child we run all of our children and set a dentry flag saying that the
     105             :  * parent cares.  Thus when an event happens on a child it can quickly tell if
     106             :  * if there is a need to find a parent and send the event to the parent.
     107             :  */
     108          94 : void __fsnotify_update_child_dentry_flags(struct inode *inode)
     109             : {
     110          94 :         struct dentry *alias;
     111          94 :         int watched;
     112             : 
     113          94 :         if (!S_ISDIR(inode->i_mode))
     114             :                 return;
     115             : 
     116             :         /* determine if the children should tell inode about their events */
     117          29 :         watched = fsnotify_inode_watches_children(inode);
     118             : 
     119          29 :         spin_lock(&inode->i_lock);
     120             :         /* run all of the dentries associated with this inode.  Since this is a
     121             :          * directory, there damn well better only be one item on this list */
     122          58 :         hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
     123          29 :                 struct dentry *child;
     124             : 
     125             :                 /* run all of the children of the original inode and fix their
     126             :                  * d_flags to indicate parental interest (their parent is the
     127             :                  * original inode) */
     128          29 :                 spin_lock(&alias->d_lock);
     129         234 :                 list_for_each_entry(child, &alias->d_subdirs, d_child) {
     130         205 :                         if (!child->d_inode)
     131          13 :                                 continue;
     132             : 
     133         192 :                         spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
     134         192 :                         if (watched)
     135          88 :                                 child->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
     136             :                         else
     137         104 :                                 child->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED;
     138         397 :                         spin_unlock(&child->d_lock);
     139             :                 }
     140          29 :                 spin_unlock(&alias->d_lock);
     141             :         }
     142          29 :         spin_unlock(&inode->i_lock);
     143             : }
     144             : 
     145             : /* Are inode/sb/mount interested in parent and name info with this event? */
     146         536 : static bool fsnotify_event_needs_parent(struct inode *inode, struct mount *mnt,
     147             :                                         __u32 mask)
     148             : {
     149         536 :         __u32 marks_mask = 0;
     150             : 
     151             :         /* We only send parent/name to inode/sb/mount for events on non-dir */
     152         536 :         if (mask & FS_ISDIR)
     153             :                 return false;
     154             : 
     155             :         /*
     156             :          * All events that are possible on child can also may be reported with
     157             :          * parent/name info to inode/sb/mount.  Otherwise, a watching parent
     158             :          * could result in events reported with unexpected name info to sb/mount.
     159             :          */
     160         533 :         BUILD_BUG_ON(FS_EVENTS_POSS_ON_CHILD & ~FS_EVENTS_POSS_TO_PARENT);
     161             : 
     162             :         /* Did either inode/sb/mount subscribe for events with parent/name? */
     163         533 :         marks_mask |= fsnotify_parent_needed_mask(inode->i_fsnotify_mask);
     164         533 :         marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask);
     165         533 :         if (mnt)
     166         532 :                 marks_mask |= fsnotify_parent_needed_mask(mnt->mnt_fsnotify_mask);
     167             : 
     168             :         /* Did they subscribe for this event with parent/name info? */
     169         533 :         return mask & marks_mask;
     170             : }
     171             : 
     172             : /*
     173             :  * Notify this dentry's parent about a child's events with child name info
     174             :  * if parent is watching or if inode/sb/mount are interested in events with
     175             :  * parent and name info.
     176             :  *
     177             :  * Notify only the child without name info if parent is not watching and
     178             :  * inode/sb/mount are not interested in events with parent and name info.
     179             :  */
     180       86433 : int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
     181             :                       int data_type)
     182             : {
     183       86433 :         const struct path *path = fsnotify_data_path(data, data_type);
     184       85363 :         struct mount *mnt = path ? real_mount(path->mnt) : NULL;
     185       86433 :         struct inode *inode = d_inode(dentry);
     186       86433 :         struct dentry *parent;
     187       86433 :         bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED;
     188       86433 :         bool parent_needed, parent_interested;
     189       86433 :         __u32 p_mask;
     190       86433 :         struct inode *p_inode = NULL;
     191       86433 :         struct name_snapshot name;
     192       86433 :         struct qstr *file_name = NULL;
     193       86433 :         int ret = 0;
     194             : 
     195             :         /*
     196             :          * Do inode/sb/mount care about parent and name info on non-dir?
     197             :          * Do they care about any event at all?
     198             :          */
     199       86433 :         if (!inode->i_fsnotify_marks && !inode->i_sb->s_fsnotify_marks &&
     200       85899 :             (!mnt || !mnt->mnt_fsnotify_marks) && !parent_watched)
     201             :                 return 0;
     202             : 
     203         536 :         parent = NULL;
     204         536 :         parent_needed = fsnotify_event_needs_parent(inode, mnt, mask);
     205         536 :         if (!parent_watched && !parent_needed)
     206         531 :                 goto notify;
     207             : 
     208             :         /* Does parent inode care about events on children? */
     209           5 :         parent = dget_parent(dentry);
     210           5 :         p_inode = parent->d_inode;
     211           5 :         p_mask = fsnotify_inode_watches_children(p_inode);
     212           5 :         if (unlikely(parent_watched && !p_mask))
     213           2 :                 __fsnotify_update_child_dentry_flags(p_inode);
     214             : 
     215             :         /*
     216             :          * Include parent/name in notification either if some notification
     217             :          * groups require parent info or the parent is interested in this event.
     218             :          */
     219           5 :         parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS;
     220           5 :         if (parent_needed || parent_interested) {
     221             :                 /* When notifying parent, child should be passed as data */
     222           0 :                 WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type));
     223             : 
     224             :                 /* Notify both parent and child with child name info */
     225           0 :                 take_dentry_name_snapshot(&name, dentry);
     226           0 :                 file_name = &name.name;
     227           0 :                 if (parent_interested)
     228           0 :                         mask |= FS_EVENT_ON_CHILD;
     229             :         }
     230             : 
     231           5 : notify:
     232         536 :         ret = fsnotify(mask, data, data_type, p_inode, file_name, inode, 0);
     233             : 
     234         536 :         if (file_name)
     235           0 :                 release_dentry_name_snapshot(&name);
     236         536 :         dput(parent);
     237             : 
     238         536 :         return ret;
     239             : }
     240             : EXPORT_SYMBOL_GPL(__fsnotify_parent);
     241             : 
     242         107 : static int fsnotify_handle_inode_event(struct fsnotify_group *group,
     243             :                                        struct fsnotify_mark *inode_mark,
     244             :                                        u32 mask, const void *data, int data_type,
     245             :                                        struct inode *dir, const struct qstr *name,
     246             :                                        u32 cookie)
     247             : {
     248         107 :         const struct path *path = fsnotify_data_path(data, data_type);
     249         107 :         struct inode *inode = fsnotify_data_inode(data, data_type);
     250         107 :         const struct fsnotify_ops *ops = group->ops;
     251             : 
     252         107 :         if (WARN_ON_ONCE(!ops->handle_inode_event))
     253             :                 return 0;
     254             : 
     255         107 :         if ((inode_mark->mask & FS_EXCL_UNLINK) &&
     256           0 :             path && d_unlinked(path->dentry))
     257             :                 return 0;
     258             : 
     259             :         /* Check interest of this mark in case event was sent with two marks */
     260         107 :         if (!(mask & inode_mark->mask & ALL_FSNOTIFY_EVENTS))
     261             :                 return 0;
     262             : 
     263         107 :         return ops->handle_inode_event(inode_mark, mask, inode, dir, name, cookie);
     264             : }
     265             : 
     266         107 : static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
     267             :                                  const void *data, int data_type,
     268             :                                  struct inode *dir, const struct qstr *name,
     269             :                                  u32 cookie, struct fsnotify_iter_info *iter_info)
     270             : {
     271         107 :         struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
     272         107 :         struct fsnotify_mark *parent_mark = fsnotify_iter_parent_mark(iter_info);
     273         107 :         int ret;
     274             : 
     275         107 :         if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) ||
     276         107 :             WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info)))
     277             :                 return 0;
     278             : 
     279         107 :         if (parent_mark) {
     280             :                 /*
     281             :                  * parent_mark indicates that the parent inode is watching
     282             :                  * children and interested in this event, which is an event
     283             :                  * possible on child. But is *this mark* watching children and
     284             :                  * interested in this event?
     285             :                  */
     286           0 :                 if (parent_mark->mask & FS_EVENT_ON_CHILD) {
     287           0 :                         ret = fsnotify_handle_inode_event(group, parent_mark, mask,
     288             :                                                           data, data_type, dir, name, 0);
     289           0 :                         if (ret)
     290             :                                 return ret;
     291             :                 }
     292           0 :                 if (!inode_mark)
     293             :                         return 0;
     294             :         }
     295             : 
     296         107 :         if (mask & FS_EVENT_ON_CHILD) {
     297             :                 /*
     298             :                  * Some events can be sent on both parent dir and child marks
     299             :                  * (e.g. FS_ATTRIB).  If both parent dir and child are
     300             :                  * watching, report the event once to parent dir with name (if
     301             :                  * interested) and once to child without name (if interested).
     302             :                  * The child watcher is expecting an event without a file name
     303             :                  * and without the FS_EVENT_ON_CHILD flag.
     304             :                  */
     305          95 :                 mask &= ~FS_EVENT_ON_CHILD;
     306          95 :                 dir = NULL;
     307          95 :                 name = NULL;
     308             :         }
     309             : 
     310         107 :         return fsnotify_handle_inode_event(group, inode_mark, mask, data, data_type,
     311             :                                            dir, name, cookie);
     312             : }
     313             : 
     314         114 : static int send_to_group(__u32 mask, const void *data, int data_type,
     315             :                          struct inode *dir, const struct qstr *file_name,
     316             :                          u32 cookie, struct fsnotify_iter_info *iter_info)
     317             : {
     318         114 :         struct fsnotify_group *group = NULL;
     319         114 :         __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS);
     320         114 :         __u32 marks_mask = 0;
     321         114 :         __u32 marks_ignored_mask = 0;
     322         114 :         struct fsnotify_mark *mark;
     323         114 :         int type;
     324             : 
     325         114 :         if (WARN_ON(!iter_info->report_mask))
     326             :                 return 0;
     327             : 
     328             :         /* clear ignored on inode modification */
     329         114 :         if (mask & FS_MODIFY) {
     330         490 :                 fsnotify_foreach_obj_type(type) {
     331         392 :                         if (!fsnotify_iter_should_report_type(iter_info, type))
     332         294 :                                 continue;
     333          98 :                         mark = iter_info->marks[type];
     334          98 :                         if (mark &&
     335          98 :                             !(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
     336          98 :                                 mark->ignored_mask = 0;
     337             :                 }
     338             :         }
     339             : 
     340         570 :         fsnotify_foreach_obj_type(type) {
     341         456 :                 if (!fsnotify_iter_should_report_type(iter_info, type))
     342         342 :                         continue;
     343         114 :                 mark = iter_info->marks[type];
     344             :                 /* does the object mark tell us to do something? */
     345         114 :                 if (mark) {
     346         114 :                         group = mark->group;
     347         114 :                         marks_mask |= mark->mask;
     348         114 :                         marks_ignored_mask |= mark->ignored_mask;
     349             :                 }
     350             :         }
     351             : 
     352         114 :         pr_debug("%s: group=%p mask=%x marks_mask=%x marks_ignored_mask=%x data=%p data_type=%d dir=%p cookie=%d\n",
     353             :                  __func__, group, mask, marks_mask, marks_ignored_mask,
     354             :                  data, data_type, dir, cookie);
     355             : 
     356         114 :         if (!(test_mask & marks_mask & ~marks_ignored_mask))
     357             :                 return 0;
     358             : 
     359         107 :         if (group->ops->handle_event) {
     360           0 :                 return group->ops->handle_event(group, mask, data, data_type, dir,
     361             :                                                 file_name, cookie, iter_info);
     362             :         }
     363             : 
     364         107 :         return fsnotify_handle_event(group, mask, data, data_type, dir,
     365             :                                      file_name, cookie, iter_info);
     366             : }
     367             : 
     368         312 : static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector **connp)
     369             : {
     370         312 :         struct fsnotify_mark_connector *conn;
     371         312 :         struct hlist_node *node = NULL;
     372             : 
     373         312 :         conn = srcu_dereference(*connp, &fsnotify_mark_srcu);
     374         312 :         if (conn)
     375         107 :                 node = srcu_dereference(conn->list.first, &fsnotify_mark_srcu);
     376             : 
     377         107 :         return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
     378             : }
     379             : 
     380         114 : static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
     381             : {
     382         114 :         struct hlist_node *node = NULL;
     383             : 
     384         114 :         if (mark)
     385         114 :                 node = srcu_dereference(mark->obj_list.next,
     386             :                                         &fsnotify_mark_srcu);
     387             : 
     388         114 :         return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
     389             : }
     390             : 
     391             : /*
     392             :  * iter_info is a multi head priority queue of marks.
     393             :  * Pick a subset of marks from queue heads, all with the
     394             :  * same group and set the report_mask for selected subset.
     395             :  * Returns the report_mask of the selected subset.
     396             :  */
     397         221 : static unsigned int fsnotify_iter_select_report_types(
     398             :                 struct fsnotify_iter_info *iter_info)
     399             : {
     400         221 :         struct fsnotify_group *max_prio_group = NULL;
     401         221 :         struct fsnotify_mark *mark;
     402         221 :         int type;
     403             : 
     404             :         /* Choose max prio group among groups of all queue heads */
     405        1105 :         fsnotify_foreach_obj_type(type) {
     406         884 :                 mark = iter_info->marks[type];
     407         998 :                 if (mark &&
     408         114 :                     fsnotify_compare_groups(max_prio_group, mark->group) > 0)
     409         114 :                         max_prio_group = mark->group;
     410             :         }
     411             : 
     412         221 :         if (!max_prio_group)
     413             :                 return 0;
     414             : 
     415             :         /* Set the report mask for marks from same group as max prio group */
     416         114 :         iter_info->report_mask = 0;
     417         570 :         fsnotify_foreach_obj_type(type) {
     418         456 :                 mark = iter_info->marks[type];
     419         570 :                 if (mark &&
     420         114 :                     fsnotify_compare_groups(max_prio_group, mark->group) == 0)
     421         456 :                         fsnotify_iter_set_report_type(iter_info, type);
     422             :         }
     423             : 
     424         114 :         return iter_info->report_mask;
     425             : }
     426             : 
     427             : /*
     428             :  * Pop from iter_info multi head queue, the marks that were iterated in the
     429             :  * current iteration step.
     430             :  */
     431         114 : static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
     432             : {
     433         114 :         int type;
     434             : 
     435         570 :         fsnotify_foreach_obj_type(type) {
     436         456 :                 if (fsnotify_iter_should_report_type(iter_info, type))
     437         114 :                         iter_info->marks[type] =
     438         114 :                                 fsnotify_next_mark(iter_info->marks[type]);
     439             :         }
     440         114 : }
     441             : 
     442             : /*
     443             :  * fsnotify - This is the main call to fsnotify.
     444             :  *
     445             :  * The VFS calls into hook specific functions in linux/fsnotify.h.
     446             :  * Those functions then in turn call here.  Here will call out to all of the
     447             :  * registered fsnotify_group.  Those groups can then use the notification event
     448             :  * in whatever means they feel necessary.
     449             :  *
     450             :  * @mask:       event type and flags
     451             :  * @data:       object that event happened on
     452             :  * @data_type:  type of object for fanotify_data_XXX() accessors
     453             :  * @dir:        optional directory associated with event -
     454             :  *              if @file_name is not NULL, this is the directory that
     455             :  *              @file_name is relative to
     456             :  * @file_name:  optional file name associated with event
     457             :  * @inode:      optional inode associated with event -
     458             :  *              either @dir or @inode must be non-NULL.
     459             :  *              if both are non-NULL event may be reported to both.
     460             :  * @cookie:     inotify rename cookie
     461             :  */
     462      110031 : int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,
     463             :              const struct qstr *file_name, struct inode *inode, u32 cookie)
     464             : {
     465      110031 :         const struct path *path = fsnotify_data_path(data, data_type);
     466      110031 :         struct fsnotify_iter_info iter_info = {};
     467      110031 :         struct super_block *sb;
     468      110031 :         struct mount *mnt = NULL;
     469      110031 :         struct inode *parent = NULL;
     470      110031 :         int ret = 0;
     471      110031 :         __u32 test_mask, marks_mask;
     472             : 
     473      110031 :         if (path)
     474       98486 :                 mnt = real_mount(path->mnt);
     475             : 
     476      110031 :         if (!inode) {
     477             :                 /* Dirent event - report on TYPE_INODE to dir */
     478             :                 inode = dir;
     479      101165 :         } else if (mask & FS_EVENT_ON_CHILD) {
     480             :                 /*
     481             :                  * Event on child - report on TYPE_PARENT to dir if it is
     482             :                  * watching children and on TYPE_INODE to child.
     483             :                  */
     484          95 :                 parent = dir;
     485             :         }
     486      110031 :         sb = inode->i_sb;
     487             : 
     488             :         /*
     489             :          * Optimization: srcu_read_lock() has a memory barrier which can
     490             :          * be expensive.  It protects walking the *_fsnotify_marks lists.
     491             :          * However, if we do not walk the lists, we do not have to do
     492             :          * SRCU because we have no references to any objects and do not
     493             :          * need SRCU to keep them "alive".
     494             :          */
     495      110031 :         if (!sb->s_fsnotify_marks &&
     496      110006 :             (!mnt || !mnt->mnt_fsnotify_marks) &&
     497      110031 :             (!inode || !inode->i_fsnotify_marks) &&
     498           0 :             (!parent || !parent->i_fsnotify_marks))
     499             :                 return 0;
     500             : 
     501       26531 :         marks_mask = sb->s_fsnotify_mask;
     502       26531 :         if (mnt)
     503       26383 :                 marks_mask |= mnt->mnt_fsnotify_mask;
     504       26531 :         if (inode)
     505       26531 :                 marks_mask |= inode->i_fsnotify_mask;
     506       26531 :         if (parent)
     507          95 :                 marks_mask |= parent->i_fsnotify_mask;
     508             : 
     509             : 
     510             :         /*
     511             :          * if this is a modify event we may need to clear the ignored masks
     512             :          * otherwise return if none of the marks care about this type of event.
     513             :          */
     514       26531 :         test_mask = (mask & ALL_FSNOTIFY_EVENTS);
     515       26531 :         if (!(mask & FS_MODIFY) && !(test_mask & marks_mask))
     516             :                 return 0;
     517             : 
     518         107 :         iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
     519             : 
     520         214 :         iter_info.marks[FSNOTIFY_OBJ_TYPE_SB] =
     521         107 :                 fsnotify_first_mark(&sb->s_fsnotify_marks);
     522         107 :         if (mnt) {
     523           3 :                 iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] =
     524           3 :                         fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
     525             :         }
     526         107 :         if (inode) {
     527         107 :                 iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
     528         107 :                         fsnotify_first_mark(&inode->i_fsnotify_marks);
     529             :         }
     530         107 :         if (parent) {
     531          95 :                 iter_info.marks[FSNOTIFY_OBJ_TYPE_PARENT] =
     532          95 :                         fsnotify_first_mark(&parent->i_fsnotify_marks);
     533             :         }
     534             : 
     535             :         /*
     536             :          * We need to merge inode/vfsmount/sb mark lists so that e.g. inode mark
     537             :          * ignore masks are properly reflected for mount/sb mark notifications.
     538             :          * That's why this traversal is so complicated...
     539             :          */
     540         221 :         while (fsnotify_iter_select_report_types(&iter_info)) {
     541         114 :                 ret = send_to_group(mask, data, data_type, dir, file_name,
     542             :                                     cookie, &iter_info);
     543             : 
     544         114 :                 if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
     545           0 :                         goto out;
     546             : 
     547         114 :                 fsnotify_iter_next(&iter_info);
     548             :         }
     549             :         ret = 0;
     550         107 : out:
     551         107 :         srcu_read_unlock(&fsnotify_mark_srcu, iter_info.srcu_idx);
     552             : 
     553         107 :         return ret;
     554             : }
     555             : EXPORT_SYMBOL_GPL(fsnotify);
     556             : 
     557           1 : static __init int fsnotify_init(void)
     558             : {
     559           1 :         int ret;
     560             : 
     561           1 :         BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 25);
     562             : 
     563           1 :         ret = init_srcu_struct(&fsnotify_mark_srcu);
     564           1 :         if (ret)
     565           0 :                 panic("initializing fsnotify_mark_srcu");
     566             : 
     567           1 :         fsnotify_mark_connector_cachep = KMEM_CACHE(fsnotify_mark_connector,
     568             :                                                     SLAB_PANIC);
     569             : 
     570           1 :         return 0;
     571             : }
     572             : core_initcall(fsnotify_init);

Generated by: LCOV version 1.14