at v4.8 8.0 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#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 */