linux/fs/notify/vfsmount_mark.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/fs.h>
  20#include <linux/init.h>
  21#include <linux/kernel.h>
  22#include <linux/module.h>
  23#include <linux/mount.h>
  24#include <linux/mutex.h>
  25#include <linux/spinlock.h>
  26
  27#include <linux/atomic.h>
  28
  29#include <linux/fsnotify_backend.h>
  30#include "fsnotify.h"
  31#include "../mount.h"
  32
  33void fsnotify_clear_marks_by_mount(struct vfsmount *mnt)
  34{
  35        struct fsnotify_mark *mark;
  36        struct hlist_node *n;
  37        struct mount *m = real_mount(mnt);
  38        LIST_HEAD(free_list);
  39
  40        spin_lock(&mnt->mnt_root->d_lock);
  41        hlist_for_each_entry_safe(mark, n, &m->mnt_fsnotify_marks, obj_list) {
  42                list_add(&mark->free_list, &free_list);
  43                hlist_del_init_rcu(&mark->obj_list);
  44                fsnotify_get_mark(mark);
  45        }
  46        spin_unlock(&mnt->mnt_root->d_lock);
  47
  48        fsnotify_destroy_marks(&free_list);
  49}
  50
  51void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group)
  52{
  53        fsnotify_clear_marks_by_group_flags(group, FSNOTIFY_MARK_FLAG_VFSMOUNT);
  54}
  55
  56/*
  57 * Recalculate the mnt->mnt_fsnotify_mask, or the mask of all FS_* event types
  58 * any notifier is interested in hearing for this mount point
  59 */
  60void fsnotify_recalc_vfsmount_mask(struct vfsmount *mnt)
  61{
  62        struct mount *m = real_mount(mnt);
  63
  64        spin_lock(&mnt->mnt_root->d_lock);
  65        m->mnt_fsnotify_mask = fsnotify_recalc_mask(&m->mnt_fsnotify_marks);
  66        spin_unlock(&mnt->mnt_root->d_lock);
  67}
  68
  69void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark)
  70{
  71        struct vfsmount *mnt = mark->mnt;
  72        struct mount *m = real_mount(mnt);
  73
  74        BUG_ON(!mutex_is_locked(&mark->group->mark_mutex));
  75        assert_spin_locked(&mark->lock);
  76
  77        spin_lock(&mnt->mnt_root->d_lock);
  78
  79        hlist_del_init_rcu(&mark->obj_list);
  80        mark->mnt = NULL;
  81
  82        m->mnt_fsnotify_mask = fsnotify_recalc_mask(&m->mnt_fsnotify_marks);
  83        spin_unlock(&mnt->mnt_root->d_lock);
  84}
  85
  86/*
  87 * given a group and vfsmount, find the mark associated with that combination.
  88 * if found take a reference to that mark and return it, else return NULL
  89 */
  90struct fsnotify_mark *fsnotify_find_vfsmount_mark(struct fsnotify_group *group,
  91                                                  struct vfsmount *mnt)
  92{
  93        struct mount *m = real_mount(mnt);
  94        struct fsnotify_mark *mark;
  95
  96        spin_lock(&mnt->mnt_root->d_lock);
  97        mark = fsnotify_find_mark(&m->mnt_fsnotify_marks, group);
  98        spin_unlock(&mnt->mnt_root->d_lock);
  99
 100        return mark;
 101}
 102
 103/*
 104 * Attach an initialized mark to a given group and vfsmount.
 105 * These marks may be used for the fsnotify backend to determine which
 106 * event types should be delivered to which groups.
 107 */
 108int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
 109                               struct fsnotify_group *group, struct vfsmount *mnt,
 110                               int allow_dups)
 111{
 112        struct mount *m = real_mount(mnt);
 113        int ret;
 114
 115        mark->flags |= FSNOTIFY_MARK_FLAG_VFSMOUNT;
 116
 117        BUG_ON(!mutex_is_locked(&group->mark_mutex));
 118        assert_spin_locked(&mark->lock);
 119
 120        spin_lock(&mnt->mnt_root->d_lock);
 121        mark->mnt = mnt;
 122        ret = fsnotify_add_mark_list(&m->mnt_fsnotify_marks, mark, allow_dups);
 123        m->mnt_fsnotify_mask = fsnotify_recalc_mask(&m->mnt_fsnotify_marks);
 124        spin_unlock(&mnt->mnt_root->d_lock);
 125
 126        return ret;
 127}
 128