linux/include/linux/fsnotify.h
<<
>>
Prefs
   1#ifndef _LINUX_FS_NOTIFY_H
   2#define _LINUX_FS_NOTIFY_H
   3
   4/*
   5 * include/linux/fsnotify.h - generic hooks for filesystem notification, to
   6 * reduce in-source duplication from both dnotify and inotify.
   7 *
   8 * We don't compile any of this away in some complicated menagerie of ifdefs.
   9 * Instead, we rely on the code inside to optimize away as needed.
  10 *
  11 * (C) Copyright 2005 Robert Love
  12 */
  13
  14#include <linux/fsnotify_backend.h>
  15#include <linux/audit.h>
  16#include <linux/slab.h>
  17#include <linux/bug.h>
  18
  19/* Notify this dentry's parent about a child's events. */
  20static inline int fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
  21{
  22        if (!dentry)
  23                dentry = path->dentry;
  24
  25        return __fsnotify_parent(path, dentry, mask);
  26}
  27
  28/* simple call site for access decisions */
  29static inline int fsnotify_perm(struct file *file, int mask)
  30{
  31        struct path *path = &file->f_path;
  32        struct inode *inode = file_inode(file);
  33        __u32 fsnotify_mask = 0;
  34        int ret;
  35
  36        if (file->f_mode & FMODE_NONOTIFY)
  37                return 0;
  38        if (!(mask & (MAY_READ | MAY_OPEN)))
  39                return 0;
  40        if (mask & MAY_OPEN)
  41                fsnotify_mask = FS_OPEN_PERM;
  42        else if (mask & MAY_READ)
  43                fsnotify_mask = FS_ACCESS_PERM;
  44        else
  45                BUG();
  46
  47        ret = fsnotify_parent(path, NULL, fsnotify_mask);
  48        if (ret)
  49                return ret;
  50
  51        return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
  52}
  53
  54/*
  55 * fsnotify_link_count - inode's link count changed
  56 */
  57static inline void fsnotify_link_count(struct inode *inode)
  58{
  59        fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
  60}
  61
  62/*
  63 * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
  64 */
  65static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
  66                                 const unsigned char *old_name,
  67                                 int isdir, struct inode *target, struct dentry *moved)
  68{
  69        struct inode *source = moved->d_inode;
  70        u32 fs_cookie = fsnotify_get_cookie();
  71        __u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM);
  72        __u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO);
  73        const unsigned char *new_name = moved->d_name.name;
  74
  75        if (old_dir == new_dir)
  76                old_dir_mask |= FS_DN_RENAME;
  77
  78        if (isdir) {
  79                old_dir_mask |= FS_ISDIR;
  80                new_dir_mask |= FS_ISDIR;
  81        }
  82
  83        fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name,
  84                 fs_cookie);
  85        fsnotify(new_dir, new_dir_mask, source, FSNOTIFY_EVENT_INODE, new_name,
  86                 fs_cookie);
  87
  88        if (target)
  89                fsnotify_link_count(target);
  90
  91        if (source)
  92                fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
  93        audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
  94}
  95
  96/*
  97 * fsnotify_inode_delete - and inode is being evicted from cache, clean up is needed
  98 */
  99static inline void fsnotify_inode_delete(struct inode *inode)
 100{
 101        __fsnotify_inode_delete(inode);
 102}
 103
 104/*
 105 * fsnotify_vfsmount_delete - a vfsmount is being destroyed, clean up is needed
 106 */
 107static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt)
 108{
 109        __fsnotify_vfsmount_delete(mnt);
 110}
 111
 112/*
 113 * fsnotify_nameremove - a filename was removed from a directory
 114 */
 115static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
 116{
 117        __u32 mask = FS_DELETE;
 118
 119        if (isdir)
 120                mask |= FS_ISDIR;
 121
 122        fsnotify_parent(NULL, dentry, mask);
 123}
 124
 125/*
 126 * fsnotify_inoderemove - an inode is going away
 127 */
 128static inline void fsnotify_inoderemove(struct inode *inode)
 129{
 130        fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
 131        __fsnotify_inode_delete(inode);
 132}
 133
 134/*
 135 * fsnotify_create - 'name' was linked in
 136 */
 137static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
 138{
 139        audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
 140
 141        fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 142}
 143
 144/*
 145 * fsnotify_link - new hardlink in 'inode' directory
 146 * Note: We have to pass also the linked inode ptr as some filesystems leave
 147 *   new_dentry->d_inode NULL and instantiate inode pointer later
 148 */
 149static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
 150{
 151        fsnotify_link_count(inode);
 152        audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE);
 153
 154        fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
 155}
 156
 157/*
 158 * fsnotify_mkdir - directory 'name' was created
 159 */
 160static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
 161{
 162        __u32 mask = (FS_CREATE | FS_ISDIR);
 163        struct inode *d_inode = dentry->d_inode;
 164
 165        audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
 166
 167        fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 168}
 169
 170/*
 171 * fsnotify_access - file was read
 172 */
 173static inline void fsnotify_access(struct file *file)
 174{
 175        struct path *path = &file->f_path;
 176        struct inode *inode = file_inode(file);
 177        __u32 mask = FS_ACCESS;
 178
 179        if (S_ISDIR(inode->i_mode))
 180                mask |= FS_ISDIR;
 181
 182        if (!(file->f_mode & FMODE_NONOTIFY)) {
 183                fsnotify_parent(path, NULL, mask);
 184                fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
 185        }
 186}
 187
 188/*
 189 * fsnotify_modify - file was modified
 190 */
 191static inline void fsnotify_modify(struct file *file)
 192{
 193        struct path *path = &file->f_path;
 194        struct inode *inode = file_inode(file);
 195        __u32 mask = FS_MODIFY;
 196
 197        if (S_ISDIR(inode->i_mode))
 198                mask |= FS_ISDIR;
 199
 200        if (!(file->f_mode & FMODE_NONOTIFY)) {
 201                fsnotify_parent(path, NULL, mask);
 202                fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
 203        }
 204}
 205
 206/*
 207 * fsnotify_open - file was opened
 208 */
 209static inline void fsnotify_open(struct file *file)
 210{
 211        struct path *path = &file->f_path;
 212        struct inode *inode = file_inode(file);
 213        __u32 mask = FS_OPEN;
 214
 215        if (S_ISDIR(inode->i_mode))
 216                mask |= FS_ISDIR;
 217
 218        fsnotify_parent(path, NULL, mask);
 219        fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
 220}
 221
 222/*
 223 * fsnotify_close - file was closed
 224 */
 225static inline void fsnotify_close(struct file *file)
 226{
 227        struct path *path = &file->f_path;
 228        struct inode *inode = file_inode(file);
 229        fmode_t mode = file->f_mode;
 230        __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE;
 231
 232        if (S_ISDIR(inode->i_mode))
 233                mask |= FS_ISDIR;
 234
 235        if (!(file->f_mode & FMODE_NONOTIFY)) {
 236                fsnotify_parent(path, NULL, mask);
 237                fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
 238        }
 239}
 240
 241/*
 242 * fsnotify_xattr - extended attributes were changed
 243 */
 244static inline void fsnotify_xattr(struct dentry *dentry)
 245{
 246        struct inode *inode = dentry->d_inode;
 247        __u32 mask = FS_ATTRIB;
 248
 249        if (S_ISDIR(inode->i_mode))
 250                mask |= FS_ISDIR;
 251
 252        fsnotify_parent(NULL, dentry, mask);
 253        fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
 254}
 255
 256/*
 257 * fsnotify_change - notify_change event.  file was modified and/or metadata
 258 * was changed.
 259 */
 260static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
 261{
 262        struct inode *inode = dentry->d_inode;
 263        __u32 mask = 0;
 264
 265        if (ia_valid & ATTR_UID)
 266                mask |= FS_ATTRIB;
 267        if (ia_valid & ATTR_GID)
 268                mask |= FS_ATTRIB;
 269        if (ia_valid & ATTR_SIZE)
 270                mask |= FS_MODIFY;
 271
 272        /* both times implies a utime(s) call */
 273        if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
 274                mask |= FS_ATTRIB;
 275        else if (ia_valid & ATTR_ATIME)
 276                mask |= FS_ACCESS;
 277        else if (ia_valid & ATTR_MTIME)
 278                mask |= FS_MODIFY;
 279
 280        if (ia_valid & ATTR_MODE)
 281                mask |= FS_ATTRIB;
 282
 283        if (mask) {
 284                if (S_ISDIR(inode->i_mode))
 285                        mask |= FS_ISDIR;
 286
 287                fsnotify_parent(NULL, dentry, mask);
 288                fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
 289        }
 290}
 291
 292#if defined(CONFIG_FSNOTIFY)    /* notify helpers */
 293
 294/*
 295 * fsnotify_oldname_init - save off the old filename before we change it
 296 */
 297static inline const unsigned char *fsnotify_oldname_init(const unsigned char *name)
 298{
 299        return kstrdup(name, GFP_KERNEL);
 300}
 301
 302/*
 303 * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init
 304 */
 305static inline void fsnotify_oldname_free(const unsigned char *old_name)
 306{
 307        kfree(old_name);
 308}
 309
 310#else   /* CONFIG_FSNOTIFY */
 311
 312static inline const char *fsnotify_oldname_init(const unsigned char *name)
 313{
 314        return NULL;
 315}
 316
 317static inline void fsnotify_oldname_free(const unsigned char *old_name)
 318{
 319}
 320
 321#endif  /*  CONFIG_FSNOTIFY */
 322
 323#endif  /* _LINUX_FS_NOTIFY_H */
 324