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