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 inode_test_mask = 0;
 196        __u32 vfsmount_test_mask = 0;
 197
 198        if (unlikely(!inode_mark && !vfsmount_mark)) {
 199                BUG();
 200                return 0;
 201        }
 202
 203        /* clear ignored on inode modification */
 204        if (mask & FS_MODIFY) {
 205                if (inode_mark &&
 206                    !(inode_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
 207                        inode_mark->ignored_mask = 0;
 208                if (vfsmount_mark &&
 209                    !(vfsmount_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
 210                        vfsmount_mark->ignored_mask = 0;
 211        }
 212
 213        /* does the inode mark tell us to do something? */
 214        if (inode_mark) {
 215                group = inode_mark->group;
 216                inode_test_mask = (mask & ~FS_EVENT_ON_CHILD);
 217                inode_test_mask &= inode_mark->mask;
 218                inode_test_mask &= ~inode_mark->ignored_mask;
 219        }
 220
 221        /* does the vfsmount_mark tell us to do something? */
 222        if (vfsmount_mark) {
 223                vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD);
 224                group = vfsmount_mark->group;
 225                vfsmount_test_mask &= vfsmount_mark->mask;
 226                vfsmount_test_mask &= ~vfsmount_mark->ignored_mask;
 227                if (inode_mark)
 228                        vfsmount_test_mask &= ~inode_mark->ignored_mask;
 229        }
 230
 231        pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p"
 232                 " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x"
 233                 " data=%p data_is=%d cookie=%d\n",
 234                 __func__, group, to_tell, mask, inode_mark,
 235                 inode_test_mask, vfsmount_mark, vfsmount_test_mask, data,
 236                 data_is, cookie);
 237
 238        if (!inode_test_mask && !vfsmount_test_mask)
 239                return 0;
 240
 241        return group->ops->handle_event(group, to_tell, inode_mark,
 242                                        vfsmount_mark, mask, data, data_is,
 243                                        file_name, cookie, iter_info);
 244}
 245
 246static struct fsnotify_mark *fsnotify_first_mark(struct fsnotify_mark_connector **connp)
 247{
 248        struct fsnotify_mark_connector *conn;
 249        struct hlist_node *node = NULL;
 250
 251        conn = srcu_dereference(*connp, &fsnotify_mark_srcu);
 252        if (conn)
 253                node = srcu_dereference(conn->list.first, &fsnotify_mark_srcu);
 254
 255        return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
 256}
 257
 258static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
 259{
 260        struct hlist_node *node = NULL;
 261
 262        if (mark)
 263                node = srcu_dereference(mark->obj_list.next,
 264                                        &fsnotify_mark_srcu);
 265
 266        return hlist_entry_safe(node, struct fsnotify_mark, obj_list);
 267}
 268
 269/*
 270 * This is the main call to fsnotify.  The VFS calls into hook specific functions
 271 * in linux/fsnotify.h.  Those functions then in turn call here.  Here will call
 272 * out to all of the registered fsnotify_group.  Those groups can then use the
 273 * notification event in whatever means they feel necessary.
 274 */
 275int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 276             const unsigned char *file_name, u32 cookie)
 277{
 278        struct fsnotify_iter_info iter_info = {};
 279        struct mount *mnt;
 280        int ret = 0;
 281        /* global tests shouldn't care about events on child only the specific event */
 282        __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
 283
 284        if (data_is == FSNOTIFY_EVENT_PATH)
 285                mnt = real_mount(((const struct path *)data)->mnt);
 286        else
 287                mnt = NULL;
 288
 289        /*
 290         * Optimization: srcu_read_lock() has a memory barrier which can
 291         * be expensive.  It protects walking the *_fsnotify_marks lists.
 292         * However, if we do not walk the lists, we do not have to do
 293         * SRCU because we have no references to any objects and do not
 294         * need SRCU to keep them "alive".
 295         */
 296        if (!to_tell->i_fsnotify_marks &&
 297            (!mnt || !mnt->mnt_fsnotify_marks))
 298                return 0;
 299        /*
 300         * if this is a modify event we may need to clear the ignored masks
 301         * otherwise return if neither the inode nor the vfsmount care about
 302         * this type of event.
 303         */
 304        if (!(mask & FS_MODIFY) &&
 305            !(test_mask & to_tell->i_fsnotify_mask) &&
 306            !(mnt && test_mask & mnt->mnt_fsnotify_mask))
 307                return 0;
 308
 309        iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
 310
 311        if ((mask & FS_MODIFY) ||
 312            (test_mask & to_tell->i_fsnotify_mask)) {
 313                iter_info.inode_mark =
 314                        fsnotify_first_mark(&to_tell->i_fsnotify_marks);
 315        }
 316
 317        if (mnt && ((mask & FS_MODIFY) ||
 318                    (test_mask & mnt->mnt_fsnotify_mask))) {
 319                iter_info.inode_mark =
 320                        fsnotify_first_mark(&to_tell->i_fsnotify_marks);
 321                iter_info.vfsmount_mark =
 322                        fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
 323        }
 324
 325        /*
 326         * We need to merge inode & vfsmount mark lists so that inode mark
 327         * ignore masks are properly reflected for mount mark notifications.
 328         * That's why this traversal is so complicated...
 329         */
 330        while (iter_info.inode_mark || iter_info.vfsmount_mark) {
 331                struct fsnotify_mark *inode_mark = iter_info.inode_mark;
 332                struct fsnotify_mark *vfsmount_mark = iter_info.vfsmount_mark;
 333
 334                if (inode_mark && vfsmount_mark) {
 335                        int cmp = fsnotify_compare_groups(inode_mark->group,
 336                                                          vfsmount_mark->group);
 337                        if (cmp > 0)
 338                                inode_mark = NULL;
 339                        else if (cmp < 0)
 340                                vfsmount_mark = NULL;
 341                }
 342
 343                ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
 344                                    data, data_is, cookie, file_name,
 345                                    &iter_info);
 346
 347                if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
 348                        goto out;
 349
 350                if (inode_mark)
 351                        iter_info.inode_mark =
 352                                fsnotify_next_mark(iter_info.inode_mark);
 353                if (vfsmount_mark)
 354                        iter_info.vfsmount_mark =
 355                                fsnotify_next_mark(iter_info.vfsmount_mark);
 356        }
 357        ret = 0;
 358out:
 359        srcu_read_unlock(&fsnotify_mark_srcu, iter_info.srcu_idx);
 360
 361        return ret;
 362}
 363EXPORT_SYMBOL_GPL(fsnotify);
 364
 365extern struct kmem_cache *fsnotify_mark_connector_cachep;
 366
 367static __init int fsnotify_init(void)
 368{
 369        int ret;
 370
 371        BUG_ON(hweight32(ALL_FSNOTIFY_EVENTS) != 23);
 372
 373        ret = init_srcu_struct(&fsnotify_mark_srcu);
 374        if (ret)
 375                panic("initializing fsnotify_mark_srcu");
 376
 377        fsnotify_mark_connector_cachep = KMEM_CACHE(fsnotify_mark_connector,
 378                                                    SLAB_PANIC);
 379
 380        return 0;
 381}
 382core_initcall(fsnotify_init);
 383