linux/fs/notify/fsnotify.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
   3 *
   4 *  This program is free software; you can redistribute it and/or modify
   5 *  it under the terms of the GNU General Public License as published by
   6 *  the Free Software Foundation; either version 2, or (at your option)
   7 *  any later version.
   8 *
   9 *  This program is distributed in the hope that it will be useful,
  10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 *  GNU General Public License for more details.
  13 *
  14 *  You should have received a copy of the GNU General Public License
  15 *  along with this program; see the file COPYING.  If not, write to
  16 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17 */
  18
  19#include <linux/dcache.h>
  20#include <linux/fs.h>
  21#include <linux/gfp.h>
  22#include <linux/init.h>
  23#include <linux/module.h>
  24#include <linux/mount.h>
  25#include <linux/srcu.h>
  26
  27#include <linux/fsnotify_backend.h>
  28#include "fsnotify.h"
  29
  30/*
  31 * Clear all of the marks on an inode when it is being evicted from core
  32 */
  33void __fsnotify_inode_delete(struct inode *inode)
  34{
  35        fsnotify_clear_marks_by_inode(inode);
  36}
  37EXPORT_SYMBOL_GPL(__fsnotify_inode_delete);
  38
  39void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
  40{
  41        fsnotify_clear_marks_by_mount(mnt);
  42}
  43
  44/**
  45 * fsnotify_unmount_inodes - an sb is unmounting.  handle any watched inodes.
  46 * @sb: superblock being unmounted.
  47 *
  48 * Called during unmount with no locks held, so needs to be safe against
  49 * concurrent modifiers. We temporarily drop sb->s_inode_list_lock and CAN block.
  50 */
  51void fsnotify_unmount_inodes(struct super_block *sb)
  52{
  53        struct inode *inode, *iput_inode = NULL;
  54
  55        spin_lock(&sb->s_inode_list_lock);
  56        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
  57                /*
  58                 * We cannot __iget() an inode in state I_FREEING,
  59                 * I_WILL_FREE, or I_NEW which is fine because by that point
  60                 * the inode cannot have any associated watches.
  61                 */
  62                spin_lock(&inode->i_lock);
  63                if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) {
  64                        spin_unlock(&inode->i_lock);
  65                        continue;
  66                }
  67
  68                /*
  69                 * If i_count is zero, the inode cannot have any watches and
  70                 * doing an __iget/iput with SB_ACTIVE clear would actually
  71                 * evict all inodes with zero i_count from icache which is
  72                 * unnecessarily violent and may in fact be illegal to do.
  73                 */
  74                if (!atomic_read(&inode->i_count)) {
  75                        spin_unlock(&inode->i_lock);
  76                        continue;
  77                }
  78
  79                __iget(inode);
  80                spin_unlock(&inode->i_lock);
  81                spin_unlock(&sb->s_inode_list_lock);
  82
  83                if (iput_inode)
  84                        iput(iput_inode);
  85
  86                /* for each watch, send FS_UNMOUNT and then remove it */
  87                fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
  88
  89                fsnotify_inode_delete(inode);
  90
  91                iput_inode = inode;
  92
  93                spin_lock(&sb->s_inode_list_lock);
  94        }
  95        spin_unlock(&sb->s_inode_list_lock);
  96
  97        if (iput_inode)
  98                iput(iput_inode);
  99}
 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 */
 108void __fsnotify_update_child_dentry_flags(struct inode *inode)
 109{
 110        struct dentry *alias;
 111        int watched;
 112
 113        if (!S_ISDIR(inode->i_mode))
 114                return;
 115
 116        /* determine if the children should tell inode about their events */
 117        watched = fsnotify_inode_watches_children(inode);
 118
 119        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        hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
 123                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                spin_lock(&alias->d_lock);
 129                list_for_each_entry(child, &alias->d_subdirs, d_child) {
 130                        if (!child->d_inode)
 131                                continue;
 132
 133                        spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
 134                        if (watched)
 135                                child->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
 136                        else
 137                                child->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED;
 138                        spin_unlock(&child->d_lock);
 139                }
 140                spin_unlock(&alias->d_lock);
 141        }
 142        spin_unlock(&inode->i_lock);
 143}
 144
 145/* Notify this dentry's parent about a child's events. */
 146int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask)
 147{
 148        struct dentry *parent;
 149        struct inode *p_inode;
 150        int ret = 0;
 151
 152        if (!dentry)
 153                dentry = path->dentry;
 154
 155        if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
 156                return 0;
 157
 158        parent = dget_parent(dentry);
 159        p_inode = parent->d_inode;
 160
 161        if (unlikely(!fsnotify_inode_watches_children(p_inode)))
 162                __fsnotify_update_child_dentry_flags(p_inode);
 163        else if (p_inode->i_fsnotify_mask & mask) {
 164                struct name_snapshot name;
 165
 166                /* we are notifying a parent so come up with the new mask which
 167                 * specifies these are events which came from a child. */
 168                mask |= FS_EVENT_ON_CHILD;
 169
 170                take_dentry_name_snapshot(&name, dentry);
 171                if (path)
 172                        ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
 173                                       name.name, 0);
 174                else
 175                        ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
 176                                       name.name, 0);
 177                release_dentry_name_snapshot(&name);
 178        }
 179
 180        dput(parent);
 181
 182        return ret;
 183}
 184EXPORT_SYMBOL_GPL(__fsnotify_parent);
 185
 186static int send_to_group(struct inode *to_tell,
 187                         struct fsnotify_mark *inode_mark,
 188                         struct fsnotify_mark *vfsmount_mark,
 189                         __u32 mask, const void *data,
 190                         int data_is, u32 cookie,
 191                         const unsigned char *file_name,
 192                         struct fsnotify_iter_info *iter_info)
 193{
 194        struct fsnotify_group *group = NULL;
 195        __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
 196        __u32 marks_mask = 0;
 197        __u32 marks_ignored_mask = 0;
 198
 199        if (unlikely(!inode_mark && !vfsmount_mark)) {
 200                BUG();
 201                return 0;
 202        }
 203
 204        /* clear ignored on inode modification */
 205        if (mask & FS_MODIFY) {
 206                if (inode_mark &&
 207                    !(inode_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
 208                        inode_mark->ignored_mask = 0;
 209                if (vfsmount_mark &&
 210                    !(vfsmount_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
 211                        vfsmount_mark->ignored_mask = 0;
 212        }
 213
 214        /* does the inode mark tell us to do something? */
 215        if (inode_mark) {
 216                group = inode_mark->group;
 217                marks_mask |= inode_mark->mask;
 218                marks_ignored_mask |= inode_mark->ignored_mask;
 219        }
 220
 221        /* does the vfsmount_mark tell us to do something? */
 222        if (vfsmount_mark) {
 223                group = vfsmount_mark->group;
 224                marks_mask |= vfsmount_mark->mask;
 225                marks_ignored_mask |= vfsmount_mark->ignored_mask;
 226        }
 227
 228        pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p"
 229                 " vfsmount_mark=%p marks_mask=%x marks_ignored_mask=%x"
 230                 " data=%p data_is=%d cookie=%d\n",
 231                 __func__, group, to_tell, mask, inode_mark, vfsmount_mark,
 232                 marks_mask, marks_ignored_mask, data,
 233                 data_is, cookie);
 234
 235        if (!(test_mask & marks_mask & ~marks_ignored_mask))
 236                return 0;
 237
 238        return group->ops->handle_event(group, to_tell, inode_mark,
 239                                        vfsmount_mark, mask, data, data_is,
 240                                        file_name, cookie, iter_info);
 241}
 242
 243static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector **connp)
 244{
 245        struct fsnotify_mark_connector *conn;
 246        struct hlist_node *node = NULL;
 247
 248        conn = srcu_dereference(*connp, &fsnotify_mark_srcu);
 249        if (conn)
 250                node = srcu_dereference(conn->list.first, &fsnotify_mark_srcu);
 251
 252        return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
 253}
 254
 255static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
 256{
 257        struct hlist_node *node = NULL;
 258
 259        if (mark)
 260                node = srcu_dereference(mark->obj_list.next,
 261                                        &fsnotify_mark_srcu);
 262
 263        return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
 264}
 265
 266/*
 267 * This is the main call to fsnotify.  The VFS calls into hook specific functions
 268 * in linux/fsnotify.h.  Those functions then in turn call here.  Here will call
 269 * out to all of the registered fsnotify_group.  Those groups can then use the
 270 * notification event in whatever means they feel necessary.
 271 */
 272int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 273             const unsigned char *file_name, u32 cookie)
 274{
 275        struct fsnotify_iter_info iter_info = {};
 276        struct mount *mnt;
 277        int ret = 0;
 278        /* global tests shouldn't care about events on child only the specific event */
 279        __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
 280
 281        if (data_is == FSNOTIFY_EVENT_PATH)
 282                mnt = real_mount(((const struct path *)data)->mnt);
 283        else
 284                mnt = NULL;
 285
 286        /*
 287         * Optimization: srcu_read_lock() has a memory barrier which can
 288         * be expensive.  It protects walking the *_fsnotify_marks lists.
 289         * However, if we do not walk the lists, we do not have to do
 290         * SRCU because we have no references to any objects and do not
 291         * need SRCU to keep them "alive".
 292         */
 293        if (!to_tell->i_fsnotify_marks &&
 294            (!mnt || !mnt->mnt_fsnotify_marks))
 295                return 0;
 296        /*
 297         * if this is a modify event we may need to clear the ignored masks
 298         * otherwise return if neither the inode nor the vfsmount care about
 299         * this type of event.
 300         */
 301        if (!(mask & FS_MODIFY) &&
 302            !(test_mask & to_tell->i_fsnotify_mask) &&
 303            !(mnt && test_mask & mnt->mnt_fsnotify_mask))
 304                return 0;
 305
 306        iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
 307
 308        if ((mask & FS_MODIFY) ||
 309            (test_mask & to_tell->i_fsnotify_mask)) {
 310                iter_info.inode_mark =
 311                        fsnotify_first_mark(&to_tell->i_fsnotify_marks);
 312        }
 313
 314        if (mnt && ((mask & FS_MODIFY) ||
 315                    (test_mask & mnt->mnt_fsnotify_mask))) {
 316                iter_info.inode_mark =
 317                        fsnotify_first_mark(&to_tell->i_fsnotify_marks);
 318                iter_info.vfsmount_mark =
 319                        fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
 320        }
 321
 322        /*
 323         * We need to merge inode & vfsmount mark lists so that inode mark
 324         * ignore masks are properly reflected for mount mark notifications.
 325         * That's why this traversal is so complicated...
 326         */
 327        while (iter_info.inode_mark || iter_info.vfsmount_mark) {
 328                struct fsnotify_mark *inode_mark = iter_info.inode_mark;
 329                struct fsnotify_mark *vfsmount_mark = iter_info.vfsmount_mark;
 330
 331                if (inode_mark && vfsmount_mark) {
 332                        int cmp = fsnotify_compare_groups(inode_mark->group,
 333                                                          vfsmount_mark->group);
 334                        if (cmp > 0)
 335                                inode_mark = NULL;
 336                        else if (cmp < 0)
 337                                vfsmount_mark = NULL;
 338                }
 339
 340                ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
 341                                    data, data_is, cookie, file_name,
 342                                    &iter_info);
 343
 344                if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
 345                        goto out;
 346
 347                if (inode_mark)
 348                        iter_info.inode_mark =
 349                                fsnotify_next_mark(iter_info.inode_mark);
 350                if (vfsmount_mark)
 351                        iter_info.vfsmount_mark =
 352                                fsnotify_next_mark(iter_info.vfsmount_mark);
 353        }
 354        ret = 0;
 355out:
 356        srcu_read_unlock(&fsnotify_mark_srcu, iter_info.srcu_idx);
 357
 358        return ret;
 359}
 360EXPORT_SYMBOL_GPL(fsnotify);
 361
 362extern struct kmem_cache *fsnotify_mark_connector_cachep;
 363
 364static __init int fsnotify_init(void)
 365{
 366        int ret;
 367
 368        BUG_ON(hweight32(ALL_FSNOTIFY_EVENTS) != 23);
 369
 370        ret = init_srcu_struct(&fsnotify_mark_srcu);
 371        if (ret)
 372                panic("initializing fsnotify_mark_srcu");
 373
 374        fsnotify_mark_connector_cachep = KMEM_CACHE(fsnotify_mark_connector,
 375                                                    SLAB_PANIC);
 376
 377        return 0;
 378}
 379core_initcall(fsnotify_init);
 380