| .. | .. |
|---|
| 17 | 17 | #include <linux/slab.h> |
|---|
| 18 | 18 | #include <linux/bug.h> |
|---|
| 19 | 19 | |
|---|
| 20 | | -/* Notify this dentry's parent about a child's events. */ |
|---|
| 21 | | -static inline int fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask) |
|---|
| 20 | +/* |
|---|
| 21 | + * Notify this @dir inode about a change in a child directory entry. |
|---|
| 22 | + * The directory entry may have turned positive or negative or its inode may |
|---|
| 23 | + * have changed (i.e. renamed over). |
|---|
| 24 | + * |
|---|
| 25 | + * Unlike fsnotify_parent(), the event will be reported regardless of the |
|---|
| 26 | + * FS_EVENT_ON_CHILD mask on the parent inode and will not be reported if only |
|---|
| 27 | + * the child is interested and not the parent. |
|---|
| 28 | + */ |
|---|
| 29 | +static inline void fsnotify_name(struct inode *dir, __u32 mask, |
|---|
| 30 | + struct inode *child, |
|---|
| 31 | + const struct qstr *name, u32 cookie) |
|---|
| 22 | 32 | { |
|---|
| 23 | | - if (!dentry) |
|---|
| 24 | | - dentry = path->dentry; |
|---|
| 25 | | - |
|---|
| 26 | | - return __fsnotify_parent(path, dentry, mask); |
|---|
| 33 | + fsnotify(mask, child, FSNOTIFY_EVENT_INODE, dir, name, NULL, cookie); |
|---|
| 27 | 34 | } |
|---|
| 28 | 35 | |
|---|
| 29 | | -/* simple call site for access decisions */ |
|---|
| 30 | | -static inline int fsnotify_perm(struct file *file, int mask) |
|---|
| 36 | +static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry, |
|---|
| 37 | + __u32 mask) |
|---|
| 38 | +{ |
|---|
| 39 | + fsnotify_name(dir, mask, d_inode(dentry), &dentry->d_name, 0); |
|---|
| 40 | +} |
|---|
| 41 | + |
|---|
| 42 | +static inline void fsnotify_inode(struct inode *inode, __u32 mask) |
|---|
| 43 | +{ |
|---|
| 44 | + if (S_ISDIR(inode->i_mode)) |
|---|
| 45 | + mask |= FS_ISDIR; |
|---|
| 46 | + |
|---|
| 47 | + fsnotify(mask, inode, FSNOTIFY_EVENT_INODE, NULL, NULL, inode, 0); |
|---|
| 48 | +} |
|---|
| 49 | + |
|---|
| 50 | +/* Notify this dentry's parent about a child's events. */ |
|---|
| 51 | +static inline int fsnotify_parent(struct dentry *dentry, __u32 mask, |
|---|
| 52 | + const void *data, int data_type) |
|---|
| 53 | +{ |
|---|
| 54 | + struct inode *inode = d_inode(dentry); |
|---|
| 55 | + |
|---|
| 56 | + if (S_ISDIR(inode->i_mode)) { |
|---|
| 57 | + mask |= FS_ISDIR; |
|---|
| 58 | + |
|---|
| 59 | + /* sb/mount marks are not interested in name of directory */ |
|---|
| 60 | + if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) |
|---|
| 61 | + goto notify_child; |
|---|
| 62 | + } |
|---|
| 63 | + |
|---|
| 64 | + /* disconnected dentry cannot notify parent */ |
|---|
| 65 | + if (IS_ROOT(dentry)) |
|---|
| 66 | + goto notify_child; |
|---|
| 67 | + |
|---|
| 68 | + return __fsnotify_parent(dentry, mask, data, data_type); |
|---|
| 69 | + |
|---|
| 70 | +notify_child: |
|---|
| 71 | + return fsnotify(mask, data, data_type, NULL, NULL, inode, 0); |
|---|
| 72 | +} |
|---|
| 73 | + |
|---|
| 74 | +/* |
|---|
| 75 | + * Simple wrappers to consolidate calls to fsnotify_parent() when an event |
|---|
| 76 | + * is on a file/dentry. |
|---|
| 77 | + */ |
|---|
| 78 | +static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask) |
|---|
| 79 | +{ |
|---|
| 80 | + fsnotify_parent(dentry, mask, d_inode(dentry), FSNOTIFY_EVENT_INODE); |
|---|
| 81 | +} |
|---|
| 82 | + |
|---|
| 83 | +static inline int fsnotify_file(struct file *file, __u32 mask) |
|---|
| 31 | 84 | { |
|---|
| 32 | 85 | const struct path *path = &file->f_path; |
|---|
| 33 | | - struct inode *inode = file_inode(file); |
|---|
| 34 | | - __u32 fsnotify_mask = 0; |
|---|
| 35 | | - int ret; |
|---|
| 36 | 86 | |
|---|
| 37 | 87 | if (file->f_mode & FMODE_NONOTIFY) |
|---|
| 38 | 88 | return 0; |
|---|
| 89 | + |
|---|
| 90 | + return fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH); |
|---|
| 91 | +} |
|---|
| 92 | + |
|---|
| 93 | +/* Simple call site for access decisions */ |
|---|
| 94 | +static inline int fsnotify_perm(struct file *file, int mask) |
|---|
| 95 | +{ |
|---|
| 96 | + int ret; |
|---|
| 97 | + __u32 fsnotify_mask = 0; |
|---|
| 98 | + |
|---|
| 39 | 99 | if (!(mask & (MAY_READ | MAY_OPEN))) |
|---|
| 40 | 100 | return 0; |
|---|
| 41 | | - if (mask & MAY_OPEN) |
|---|
| 101 | + |
|---|
| 102 | + if (mask & MAY_OPEN) { |
|---|
| 42 | 103 | fsnotify_mask = FS_OPEN_PERM; |
|---|
| 43 | | - else if (mask & MAY_READ) |
|---|
| 104 | + |
|---|
| 105 | + if (file->f_flags & __FMODE_EXEC) { |
|---|
| 106 | + ret = fsnotify_file(file, FS_OPEN_EXEC_PERM); |
|---|
| 107 | + |
|---|
| 108 | + if (ret) |
|---|
| 109 | + return ret; |
|---|
| 110 | + } |
|---|
| 111 | + } else if (mask & MAY_READ) { |
|---|
| 44 | 112 | fsnotify_mask = FS_ACCESS_PERM; |
|---|
| 45 | | - else |
|---|
| 46 | | - BUG(); |
|---|
| 113 | + } |
|---|
| 47 | 114 | |
|---|
| 48 | | - ret = fsnotify_parent(path, NULL, fsnotify_mask); |
|---|
| 49 | | - if (ret) |
|---|
| 50 | | - return ret; |
|---|
| 51 | | - |
|---|
| 52 | | - return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); |
|---|
| 115 | + return fsnotify_file(file, fsnotify_mask); |
|---|
| 53 | 116 | } |
|---|
| 54 | 117 | |
|---|
| 55 | 118 | /* |
|---|
| .. | .. |
|---|
| 57 | 120 | */ |
|---|
| 58 | 121 | static inline void fsnotify_link_count(struct inode *inode) |
|---|
| 59 | 122 | { |
|---|
| 60 | | - fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
|---|
| 123 | + fsnotify_inode(inode, FS_ATTRIB); |
|---|
| 61 | 124 | } |
|---|
| 62 | 125 | |
|---|
| 63 | 126 | /* |
|---|
| 64 | 127 | * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir |
|---|
| 65 | 128 | */ |
|---|
| 66 | 129 | static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, |
|---|
| 67 | | - const unsigned char *old_name, |
|---|
| 68 | | - int isdir, struct inode *target, struct dentry *moved) |
|---|
| 130 | + const struct qstr *old_name, |
|---|
| 131 | + int isdir, struct inode *target, |
|---|
| 132 | + struct dentry *moved) |
|---|
| 69 | 133 | { |
|---|
| 70 | 134 | struct inode *source = moved->d_inode; |
|---|
| 71 | 135 | u32 fs_cookie = fsnotify_get_cookie(); |
|---|
| 72 | | - __u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM); |
|---|
| 73 | | - __u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO); |
|---|
| 74 | | - const unsigned char *new_name = moved->d_name.name; |
|---|
| 136 | + __u32 old_dir_mask = FS_MOVED_FROM; |
|---|
| 137 | + __u32 new_dir_mask = FS_MOVED_TO; |
|---|
| 138 | + const struct qstr *new_name = &moved->d_name; |
|---|
| 75 | 139 | |
|---|
| 76 | 140 | if (old_dir == new_dir) |
|---|
| 77 | 141 | old_dir_mask |= FS_DN_RENAME; |
|---|
| .. | .. |
|---|
| 81 | 145 | new_dir_mask |= FS_ISDIR; |
|---|
| 82 | 146 | } |
|---|
| 83 | 147 | |
|---|
| 84 | | - fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name, |
|---|
| 85 | | - fs_cookie); |
|---|
| 86 | | - fsnotify(new_dir, new_dir_mask, source, FSNOTIFY_EVENT_INODE, new_name, |
|---|
| 87 | | - fs_cookie); |
|---|
| 148 | + fsnotify_name(old_dir, old_dir_mask, source, old_name, fs_cookie); |
|---|
| 149 | + fsnotify_name(new_dir, new_dir_mask, source, new_name, fs_cookie); |
|---|
| 88 | 150 | |
|---|
| 89 | 151 | if (target) |
|---|
| 90 | 152 | fsnotify_link_count(target); |
|---|
| 91 | | - |
|---|
| 92 | | - if (source) |
|---|
| 93 | | - fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
|---|
| 153 | + fsnotify_inode(source, FS_MOVE_SELF); |
|---|
| 94 | 154 | audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE); |
|---|
| 95 | 155 | } |
|---|
| 96 | 156 | |
|---|
| .. | .. |
|---|
| 111 | 171 | } |
|---|
| 112 | 172 | |
|---|
| 113 | 173 | /* |
|---|
| 114 | | - * fsnotify_nameremove - a filename was removed from a directory |
|---|
| 115 | | - */ |
|---|
| 116 | | -static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) |
|---|
| 117 | | -{ |
|---|
| 118 | | - __u32 mask = FS_DELETE; |
|---|
| 119 | | - |
|---|
| 120 | | - if (isdir) |
|---|
| 121 | | - mask |= FS_ISDIR; |
|---|
| 122 | | - |
|---|
| 123 | | - fsnotify_parent(NULL, dentry, mask); |
|---|
| 124 | | -} |
|---|
| 125 | | - |
|---|
| 126 | | -/* |
|---|
| 127 | 174 | * fsnotify_inoderemove - an inode is going away |
|---|
| 128 | 175 | */ |
|---|
| 129 | 176 | static inline void fsnotify_inoderemove(struct inode *inode) |
|---|
| 130 | 177 | { |
|---|
| 131 | | - fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
|---|
| 178 | + fsnotify_inode(inode, FS_DELETE_SELF); |
|---|
| 132 | 179 | __fsnotify_inode_delete(inode); |
|---|
| 133 | 180 | } |
|---|
| 134 | 181 | |
|---|
| .. | .. |
|---|
| 139 | 186 | { |
|---|
| 140 | 187 | audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE); |
|---|
| 141 | 188 | |
|---|
| 142 | | - fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); |
|---|
| 189 | + fsnotify_dirent(inode, dentry, FS_CREATE); |
|---|
| 143 | 190 | } |
|---|
| 144 | 191 | |
|---|
| 145 | 192 | /* |
|---|
| .. | .. |
|---|
| 147 | 194 | * Note: We have to pass also the linked inode ptr as some filesystems leave |
|---|
| 148 | 195 | * new_dentry->d_inode NULL and instantiate inode pointer later |
|---|
| 149 | 196 | */ |
|---|
| 150 | | -static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry) |
|---|
| 197 | +static inline void fsnotify_link(struct inode *dir, struct inode *inode, |
|---|
| 198 | + struct dentry *new_dentry) |
|---|
| 151 | 199 | { |
|---|
| 152 | 200 | fsnotify_link_count(inode); |
|---|
| 153 | 201 | audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE); |
|---|
| 154 | 202 | |
|---|
| 155 | | - fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0); |
|---|
| 203 | + fsnotify_name(dir, FS_CREATE, inode, &new_dentry->d_name, 0); |
|---|
| 204 | +} |
|---|
| 205 | + |
|---|
| 206 | +/* |
|---|
| 207 | + * fsnotify_delete - @dentry was unlinked and unhashed |
|---|
| 208 | + * |
|---|
| 209 | + * Caller must make sure that dentry->d_name is stable. |
|---|
| 210 | + * |
|---|
| 211 | + * Note: unlike fsnotify_unlink(), we have to pass also the unlinked inode |
|---|
| 212 | + * as this may be called after d_delete() and old_dentry may be negative. |
|---|
| 213 | + */ |
|---|
| 214 | +static inline void fsnotify_delete(struct inode *dir, struct inode *inode, |
|---|
| 215 | + struct dentry *dentry) |
|---|
| 216 | +{ |
|---|
| 217 | + __u32 mask = FS_DELETE; |
|---|
| 218 | + |
|---|
| 219 | + if (S_ISDIR(inode->i_mode)) |
|---|
| 220 | + mask |= FS_ISDIR; |
|---|
| 221 | + |
|---|
| 222 | + fsnotify_name(dir, mask, inode, &dentry->d_name, 0); |
|---|
| 223 | +} |
|---|
| 224 | + |
|---|
| 225 | +/** |
|---|
| 226 | + * d_delete_notify - delete a dentry and call fsnotify_delete() |
|---|
| 227 | + * @dentry: The dentry to delete |
|---|
| 228 | + * |
|---|
| 229 | + * This helper is used to guaranty that the unlinked inode cannot be found |
|---|
| 230 | + * by lookup of this name after fsnotify_delete() event has been delivered. |
|---|
| 231 | + */ |
|---|
| 232 | +static inline void d_delete_notify(struct inode *dir, struct dentry *dentry) |
|---|
| 233 | +{ |
|---|
| 234 | + struct inode *inode = d_inode(dentry); |
|---|
| 235 | + |
|---|
| 236 | + ihold(inode); |
|---|
| 237 | + d_delete(dentry); |
|---|
| 238 | + fsnotify_delete(dir, inode, dentry); |
|---|
| 239 | + iput(inode); |
|---|
| 240 | +} |
|---|
| 241 | + |
|---|
| 242 | +/* |
|---|
| 243 | + * fsnotify_unlink - 'name' was unlinked |
|---|
| 244 | + * |
|---|
| 245 | + * Caller must make sure that dentry->d_name is stable. |
|---|
| 246 | + */ |
|---|
| 247 | +static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry) |
|---|
| 248 | +{ |
|---|
| 249 | + if (WARN_ON_ONCE(d_is_negative(dentry))) |
|---|
| 250 | + return; |
|---|
| 251 | + |
|---|
| 252 | + fsnotify_delete(dir, d_inode(dentry), dentry); |
|---|
| 156 | 253 | } |
|---|
| 157 | 254 | |
|---|
| 158 | 255 | /* |
|---|
| .. | .. |
|---|
| 160 | 257 | */ |
|---|
| 161 | 258 | static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) |
|---|
| 162 | 259 | { |
|---|
| 163 | | - __u32 mask = (FS_CREATE | FS_ISDIR); |
|---|
| 164 | | - struct inode *d_inode = dentry->d_inode; |
|---|
| 165 | | - |
|---|
| 166 | 260 | audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE); |
|---|
| 167 | 261 | |
|---|
| 168 | | - fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); |
|---|
| 262 | + fsnotify_dirent(inode, dentry, FS_CREATE | FS_ISDIR); |
|---|
| 263 | +} |
|---|
| 264 | + |
|---|
| 265 | +/* |
|---|
| 266 | + * fsnotify_rmdir - directory 'name' was removed |
|---|
| 267 | + * |
|---|
| 268 | + * Caller must make sure that dentry->d_name is stable. |
|---|
| 269 | + */ |
|---|
| 270 | +static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry) |
|---|
| 271 | +{ |
|---|
| 272 | + if (WARN_ON_ONCE(d_is_negative(dentry))) |
|---|
| 273 | + return; |
|---|
| 274 | + |
|---|
| 275 | + fsnotify_delete(dir, d_inode(dentry), dentry); |
|---|
| 169 | 276 | } |
|---|
| 170 | 277 | |
|---|
| 171 | 278 | /* |
|---|
| .. | .. |
|---|
| 173 | 280 | */ |
|---|
| 174 | 281 | static inline void fsnotify_access(struct file *file) |
|---|
| 175 | 282 | { |
|---|
| 176 | | - const struct path *path = &file->f_path; |
|---|
| 177 | | - struct inode *inode = file_inode(file); |
|---|
| 178 | | - __u32 mask = FS_ACCESS; |
|---|
| 179 | | - |
|---|
| 180 | | - if (S_ISDIR(inode->i_mode)) |
|---|
| 181 | | - mask |= FS_ISDIR; |
|---|
| 182 | | - |
|---|
| 183 | | - if (!(file->f_mode & FMODE_NONOTIFY)) { |
|---|
| 184 | | - fsnotify_parent(path, NULL, mask); |
|---|
| 185 | | - fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); |
|---|
| 186 | | - } |
|---|
| 283 | + fsnotify_file(file, FS_ACCESS); |
|---|
| 187 | 284 | } |
|---|
| 188 | 285 | |
|---|
| 189 | 286 | /* |
|---|
| .. | .. |
|---|
| 191 | 288 | */ |
|---|
| 192 | 289 | static inline void fsnotify_modify(struct file *file) |
|---|
| 193 | 290 | { |
|---|
| 194 | | - const struct path *path = &file->f_path; |
|---|
| 195 | | - struct inode *inode = file_inode(file); |
|---|
| 196 | | - __u32 mask = FS_MODIFY; |
|---|
| 197 | | - |
|---|
| 198 | | - if (S_ISDIR(inode->i_mode)) |
|---|
| 199 | | - mask |= FS_ISDIR; |
|---|
| 200 | | - |
|---|
| 201 | | - if (!(file->f_mode & FMODE_NONOTIFY)) { |
|---|
| 202 | | - fsnotify_parent(path, NULL, mask); |
|---|
| 203 | | - fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); |
|---|
| 204 | | - } |
|---|
| 291 | + fsnotify_file(file, FS_MODIFY); |
|---|
| 205 | 292 | } |
|---|
| 206 | 293 | |
|---|
| 207 | 294 | /* |
|---|
| .. | .. |
|---|
| 209 | 296 | */ |
|---|
| 210 | 297 | static inline void fsnotify_open(struct file *file) |
|---|
| 211 | 298 | { |
|---|
| 212 | | - const struct path *path = &file->f_path; |
|---|
| 213 | | - struct inode *inode = file_inode(file); |
|---|
| 214 | | - struct path lower_path; |
|---|
| 215 | 299 | __u32 mask = FS_OPEN; |
|---|
| 216 | 300 | |
|---|
| 217 | | - if (S_ISDIR(inode->i_mode)) |
|---|
| 218 | | - mask |= FS_ISDIR; |
|---|
| 301 | + if (file->f_flags & __FMODE_EXEC) |
|---|
| 302 | + mask |= FS_OPEN_EXEC; |
|---|
| 219 | 303 | |
|---|
| 220 | | - if (path->dentry->d_op && path->dentry->d_op->d_canonical_path) { |
|---|
| 221 | | - path->dentry->d_op->d_canonical_path(path, &lower_path); |
|---|
| 222 | | - fsnotify_parent(&lower_path, NULL, mask); |
|---|
| 223 | | - fsnotify(lower_path.dentry->d_inode, mask, &lower_path, |
|---|
| 224 | | - FSNOTIFY_EVENT_PATH, NULL, 0); |
|---|
| 225 | | - path_put(&lower_path); |
|---|
| 226 | | - } |
|---|
| 227 | | - |
|---|
| 228 | | - fsnotify_parent(path, NULL, mask); |
|---|
| 229 | | - fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); |
|---|
| 304 | + fsnotify_file(file, mask); |
|---|
| 230 | 305 | } |
|---|
| 231 | 306 | |
|---|
| 232 | 307 | /* |
|---|
| .. | .. |
|---|
| 234 | 309 | */ |
|---|
| 235 | 310 | static inline void fsnotify_close(struct file *file) |
|---|
| 236 | 311 | { |
|---|
| 237 | | - const struct path *path = &file->f_path; |
|---|
| 238 | | - struct inode *inode = file_inode(file); |
|---|
| 239 | | - fmode_t mode = file->f_mode; |
|---|
| 240 | | - __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; |
|---|
| 312 | + __u32 mask = (file->f_mode & FMODE_WRITE) ? FS_CLOSE_WRITE : |
|---|
| 313 | + FS_CLOSE_NOWRITE; |
|---|
| 241 | 314 | |
|---|
| 242 | | - if (S_ISDIR(inode->i_mode)) |
|---|
| 243 | | - mask |= FS_ISDIR; |
|---|
| 244 | | - |
|---|
| 245 | | - if (!(file->f_mode & FMODE_NONOTIFY)) { |
|---|
| 246 | | - fsnotify_parent(path, NULL, mask); |
|---|
| 247 | | - fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); |
|---|
| 248 | | - } |
|---|
| 315 | + fsnotify_file(file, mask); |
|---|
| 249 | 316 | } |
|---|
| 250 | 317 | |
|---|
| 251 | 318 | /* |
|---|
| .. | .. |
|---|
| 253 | 320 | */ |
|---|
| 254 | 321 | static inline void fsnotify_xattr(struct dentry *dentry) |
|---|
| 255 | 322 | { |
|---|
| 256 | | - struct inode *inode = dentry->d_inode; |
|---|
| 257 | | - __u32 mask = FS_ATTRIB; |
|---|
| 258 | | - |
|---|
| 259 | | - if (S_ISDIR(inode->i_mode)) |
|---|
| 260 | | - mask |= FS_ISDIR; |
|---|
| 261 | | - |
|---|
| 262 | | - fsnotify_parent(NULL, dentry, mask); |
|---|
| 263 | | - fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
|---|
| 323 | + fsnotify_dentry(dentry, FS_ATTRIB); |
|---|
| 264 | 324 | } |
|---|
| 265 | 325 | |
|---|
| 266 | 326 | /* |
|---|
| .. | .. |
|---|
| 269 | 329 | */ |
|---|
| 270 | 330 | static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) |
|---|
| 271 | 331 | { |
|---|
| 272 | | - struct inode *inode = dentry->d_inode; |
|---|
| 273 | 332 | __u32 mask = 0; |
|---|
| 274 | 333 | |
|---|
| 275 | 334 | if (ia_valid & ATTR_UID) |
|---|
| .. | .. |
|---|
| 290 | 349 | if (ia_valid & ATTR_MODE) |
|---|
| 291 | 350 | mask |= FS_ATTRIB; |
|---|
| 292 | 351 | |
|---|
| 293 | | - if (mask) { |
|---|
| 294 | | - if (S_ISDIR(inode->i_mode)) |
|---|
| 295 | | - mask |= FS_ISDIR; |
|---|
| 296 | | - |
|---|
| 297 | | - fsnotify_parent(NULL, dentry, mask); |
|---|
| 298 | | - fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
|---|
| 299 | | - } |
|---|
| 352 | + if (mask) |
|---|
| 353 | + fsnotify_dentry(dentry, mask); |
|---|
| 300 | 354 | } |
|---|
| 301 | 355 | |
|---|
| 302 | 356 | #endif /* _LINUX_FS_NOTIFY_H */ |
|---|