at v2.6.17 6.8 kB view raw
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#ifdef __KERNEL__ 15 16#include <linux/dnotify.h> 17#include <linux/inotify.h> 18#include <linux/audit.h> 19 20/* 21 * fsnotify_d_instantiate - instantiate a dentry for inode 22 * Called with dcache_lock held. 23 */ 24static inline void fsnotify_d_instantiate(struct dentry *entry, 25 struct inode *inode) 26{ 27 inotify_d_instantiate(entry, inode); 28} 29 30/* 31 * fsnotify_d_move - entry has been moved 32 * Called with dcache_lock and entry->d_lock held. 33 */ 34static inline void fsnotify_d_move(struct dentry *entry) 35{ 36 inotify_d_move(entry); 37} 38 39/* 40 * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir 41 */ 42static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, 43 const char *old_name, const char *new_name, 44 int isdir, struct inode *target, struct inode *source) 45{ 46 u32 cookie = inotify_get_cookie(); 47 48 if (old_dir == new_dir) 49 inode_dir_notify(old_dir, DN_RENAME); 50 else { 51 inode_dir_notify(old_dir, DN_DELETE); 52 inode_dir_notify(new_dir, DN_CREATE); 53 } 54 55 if (isdir) 56 isdir = IN_ISDIR; 57 inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name); 58 inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name); 59 60 if (target) { 61 inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL); 62 inotify_inode_is_dead(target); 63 } 64 65 if (source) { 66 inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL); 67 } 68 audit_inode_child(old_name, source, old_dir->i_ino); 69 audit_inode_child(new_name, target, new_dir->i_ino); 70} 71 72/* 73 * fsnotify_nameremove - a filename was removed from a directory 74 */ 75static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) 76{ 77 if (isdir) 78 isdir = IN_ISDIR; 79 dnotify_parent(dentry, DN_DELETE); 80 inotify_dentry_parent_queue_event(dentry, IN_DELETE|isdir, 0, dentry->d_name.name); 81} 82 83/* 84 * fsnotify_inoderemove - an inode is going away 85 */ 86static inline void fsnotify_inoderemove(struct inode *inode) 87{ 88 inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL); 89 inotify_inode_is_dead(inode); 90} 91 92/* 93 * fsnotify_create - 'name' was linked in 94 */ 95static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) 96{ 97 inode_dir_notify(inode, DN_CREATE); 98 inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name); 99 audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino); 100} 101 102/* 103 * fsnotify_mkdir - directory 'name' was created 104 */ 105static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) 106{ 107 inode_dir_notify(inode, DN_CREATE); 108 inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, 109 dentry->d_name.name); 110 audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino); 111} 112 113/* 114 * fsnotify_access - file was read 115 */ 116static inline void fsnotify_access(struct dentry *dentry) 117{ 118 struct inode *inode = dentry->d_inode; 119 u32 mask = IN_ACCESS; 120 121 if (S_ISDIR(inode->i_mode)) 122 mask |= IN_ISDIR; 123 124 dnotify_parent(dentry, DN_ACCESS); 125 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); 126 inotify_inode_queue_event(inode, mask, 0, NULL); 127} 128 129/* 130 * fsnotify_modify - file was modified 131 */ 132static inline void fsnotify_modify(struct dentry *dentry) 133{ 134 struct inode *inode = dentry->d_inode; 135 u32 mask = IN_MODIFY; 136 137 if (S_ISDIR(inode->i_mode)) 138 mask |= IN_ISDIR; 139 140 dnotify_parent(dentry, DN_MODIFY); 141 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); 142 inotify_inode_queue_event(inode, mask, 0, NULL); 143} 144 145/* 146 * fsnotify_open - file was opened 147 */ 148static inline void fsnotify_open(struct dentry *dentry) 149{ 150 struct inode *inode = dentry->d_inode; 151 u32 mask = IN_OPEN; 152 153 if (S_ISDIR(inode->i_mode)) 154 mask |= IN_ISDIR; 155 156 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); 157 inotify_inode_queue_event(inode, mask, 0, NULL); 158} 159 160/* 161 * fsnotify_close - file was closed 162 */ 163static inline void fsnotify_close(struct file *file) 164{ 165 struct dentry *dentry = file->f_dentry; 166 struct inode *inode = dentry->d_inode; 167 const char *name = dentry->d_name.name; 168 mode_t mode = file->f_mode; 169 u32 mask = (mode & FMODE_WRITE) ? IN_CLOSE_WRITE : IN_CLOSE_NOWRITE; 170 171 if (S_ISDIR(inode->i_mode)) 172 mask |= IN_ISDIR; 173 174 inotify_dentry_parent_queue_event(dentry, mask, 0, name); 175 inotify_inode_queue_event(inode, mask, 0, NULL); 176} 177 178/* 179 * fsnotify_xattr - extended attributes were changed 180 */ 181static inline void fsnotify_xattr(struct dentry *dentry) 182{ 183 struct inode *inode = dentry->d_inode; 184 u32 mask = IN_ATTRIB; 185 186 if (S_ISDIR(inode->i_mode)) 187 mask |= IN_ISDIR; 188 189 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name); 190 inotify_inode_queue_event(inode, mask, 0, NULL); 191} 192 193/* 194 * fsnotify_change - notify_change event. file was modified and/or metadata 195 * was changed. 196 */ 197static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) 198{ 199 struct inode *inode = dentry->d_inode; 200 int dn_mask = 0; 201 u32 in_mask = 0; 202 203 if (ia_valid & ATTR_UID) { 204 in_mask |= IN_ATTRIB; 205 dn_mask |= DN_ATTRIB; 206 } 207 if (ia_valid & ATTR_GID) { 208 in_mask |= IN_ATTRIB; 209 dn_mask |= DN_ATTRIB; 210 } 211 if (ia_valid & ATTR_SIZE) { 212 in_mask |= IN_MODIFY; 213 dn_mask |= DN_MODIFY; 214 } 215 /* both times implies a utime(s) call */ 216 if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) 217 { 218 in_mask |= IN_ATTRIB; 219 dn_mask |= DN_ATTRIB; 220 } else if (ia_valid & ATTR_ATIME) { 221 in_mask |= IN_ACCESS; 222 dn_mask |= DN_ACCESS; 223 } else if (ia_valid & ATTR_MTIME) { 224 in_mask |= IN_MODIFY; 225 dn_mask |= DN_MODIFY; 226 } 227 if (ia_valid & ATTR_MODE) { 228 in_mask |= IN_ATTRIB; 229 dn_mask |= DN_ATTRIB; 230 } 231 232 if (dn_mask) 233 dnotify_parent(dentry, dn_mask); 234 if (in_mask) { 235 if (S_ISDIR(inode->i_mode)) 236 in_mask |= IN_ISDIR; 237 inotify_inode_queue_event(inode, in_mask, 0, NULL); 238 inotify_dentry_parent_queue_event(dentry, in_mask, 0, 239 dentry->d_name.name); 240 } 241} 242 243#ifdef CONFIG_INOTIFY /* inotify helpers */ 244 245/* 246 * fsnotify_oldname_init - save off the old filename before we change it 247 */ 248static inline const char *fsnotify_oldname_init(const char *name) 249{ 250 return kstrdup(name, GFP_KERNEL); 251} 252 253/* 254 * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init 255 */ 256static inline void fsnotify_oldname_free(const char *old_name) 257{ 258 kfree(old_name); 259} 260 261#else /* CONFIG_INOTIFY */ 262 263static inline const char *fsnotify_oldname_init(const char *name) 264{ 265 return NULL; 266} 267 268static inline void fsnotify_oldname_free(const char *old_name) 269{ 270} 271 272#endif /* ! CONFIG_INOTIFY */ 273 274#endif /* __KERNEL__ */ 275 276#endif /* _LINUX_FS_NOTIFY_H */