diff options
| -rw-r--r-- | fs/notify/dnotify/dnotify.c | 8 | ||||
| -rw-r--r-- | fs/notify/fanotify/fanotify.c | 46 | ||||
| -rw-r--r-- | fs/notify/fdinfo.c | 6 | ||||
| -rw-r--r-- | fs/notify/fsnotify.c | 138 | ||||
| -rw-r--r-- | fs/notify/fsnotify.h | 6 | ||||
| -rw-r--r-- | fs/notify/group.c | 2 | ||||
| -rw-r--r-- | fs/notify/inotify/inotify.h | 2 | ||||
| -rw-r--r-- | fs/notify/inotify/inotify_fsnotify.c | 6 | ||||
| -rw-r--r-- | fs/notify/inotify/inotify_user.c | 10 | ||||
| -rw-r--r-- | fs/notify/mark.c | 52 | ||||
| -rw-r--r-- | include/linux/fsnotify_backend.h | 79 | ||||
| -rw-r--r-- | kernel/audit_fsnotify.c | 5 | ||||
| -rw-r--r-- | kernel/audit_tree.c | 12 | ||||
| -rw-r--r-- | kernel/audit_watch.c | 5 |
14 files changed, 230 insertions, 147 deletions
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 63a1ca4b9dee..e2bea2ac5dfb 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c | |||
| @@ -79,12 +79,11 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) | |||
| 79 | */ | 79 | */ |
| 80 | static int dnotify_handle_event(struct fsnotify_group *group, | 80 | static int dnotify_handle_event(struct fsnotify_group *group, |
| 81 | struct inode *inode, | 81 | struct inode *inode, |
| 82 | struct fsnotify_mark *inode_mark, | ||
| 83 | struct fsnotify_mark *vfsmount_mark, | ||
| 84 | u32 mask, const void *data, int data_type, | 82 | u32 mask, const void *data, int data_type, |
| 85 | const unsigned char *file_name, u32 cookie, | 83 | const unsigned char *file_name, u32 cookie, |
| 86 | struct fsnotify_iter_info *iter_info) | 84 | struct fsnotify_iter_info *iter_info) |
| 87 | { | 85 | { |
| 86 | struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); | ||
| 88 | struct dnotify_mark *dn_mark; | 87 | struct dnotify_mark *dn_mark; |
| 89 | struct dnotify_struct *dn; | 88 | struct dnotify_struct *dn; |
| 90 | struct dnotify_struct **prev; | 89 | struct dnotify_struct **prev; |
| @@ -95,7 +94,8 @@ static int dnotify_handle_event(struct fsnotify_group *group, | |||
| 95 | if (!S_ISDIR(inode->i_mode)) | 94 | if (!S_ISDIR(inode->i_mode)) |
| 96 | return 0; | 95 | return 0; |
| 97 | 96 | ||
| 98 | BUG_ON(vfsmount_mark); | 97 | if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info))) |
| 98 | return 0; | ||
| 99 | 99 | ||
| 100 | dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark); | 100 | dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark); |
| 101 | 101 | ||
| @@ -319,7 +319,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) | |||
| 319 | dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark); | 319 | dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark); |
| 320 | spin_lock(&fsn_mark->lock); | 320 | spin_lock(&fsn_mark->lock); |
| 321 | } else { | 321 | } else { |
| 322 | error = fsnotify_add_mark_locked(new_fsn_mark, inode, NULL, 0); | 322 | error = fsnotify_add_inode_mark_locked(new_fsn_mark, inode, 0); |
| 323 | if (error) { | 323 | if (error) { |
| 324 | mutex_unlock(&dnotify_group->mark_mutex); | 324 | mutex_unlock(&dnotify_group->mark_mutex); |
| 325 | goto out_err; | 325 | goto out_err; |
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index d94e8031fe5f..f90842efea13 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
| @@ -87,17 +87,17 @@ static int fanotify_get_response(struct fsnotify_group *group, | |||
| 87 | return ret; | 87 | return ret; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark, | 90 | static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info, |
| 91 | struct fsnotify_mark *vfsmnt_mark, | 91 | u32 event_mask, const void *data, |
| 92 | u32 event_mask, | 92 | int data_type) |
| 93 | const void *data, int data_type) | ||
| 94 | { | 93 | { |
| 95 | __u32 marks_mask = 0, marks_ignored_mask = 0; | 94 | __u32 marks_mask = 0, marks_ignored_mask = 0; |
| 96 | const struct path *path = data; | 95 | const struct path *path = data; |
| 96 | struct fsnotify_mark *mark; | ||
| 97 | int type; | ||
| 97 | 98 | ||
| 98 | pr_debug("%s: inode_mark=%p vfsmnt_mark=%p mask=%x data=%p" | 99 | pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n", |
| 99 | " data_type=%d\n", __func__, inode_mark, vfsmnt_mark, | 100 | __func__, iter_info->report_mask, event_mask, data, data_type); |
| 100 | event_mask, data, data_type); | ||
| 101 | 101 | ||
| 102 | /* if we don't have enough info to send an event to userspace say no */ | 102 | /* if we don't have enough info to send an event to userspace say no */ |
| 103 | if (data_type != FSNOTIFY_EVENT_PATH) | 103 | if (data_type != FSNOTIFY_EVENT_PATH) |
| @@ -108,20 +108,21 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark, | |||
| 108 | !d_can_lookup(path->dentry)) | 108 | !d_can_lookup(path->dentry)) |
| 109 | return false; | 109 | return false; |
| 110 | 110 | ||
| 111 | /* | 111 | fsnotify_foreach_obj_type(type) { |
| 112 | * if the event is for a child and this inode doesn't care about | 112 | if (!fsnotify_iter_should_report_type(iter_info, type)) |
| 113 | * events on the child, don't send it! | 113 | continue; |
| 114 | */ | 114 | mark = iter_info->marks[type]; |
| 115 | if (inode_mark && | 115 | /* |
| 116 | (!(event_mask & FS_EVENT_ON_CHILD) || | 116 | * if the event is for a child and this inode doesn't care about |
| 117 | (inode_mark->mask & FS_EVENT_ON_CHILD))) { | 117 | * events on the child, don't send it! |
| 118 | marks_mask |= inode_mark->mask; | 118 | */ |
| 119 | marks_ignored_mask |= inode_mark->ignored_mask; | 119 | if (type == FSNOTIFY_OBJ_TYPE_INODE && |
| 120 | } | 120 | (event_mask & FS_EVENT_ON_CHILD) && |
| 121 | !(mark->mask & FS_EVENT_ON_CHILD)) | ||
| 122 | continue; | ||
| 121 | 123 | ||
| 122 | if (vfsmnt_mark) { | 124 | marks_mask |= mark->mask; |
| 123 | marks_mask |= vfsmnt_mark->mask; | 125 | marks_ignored_mask |= mark->ignored_mask; |
| 124 | marks_ignored_mask |= vfsmnt_mark->ignored_mask; | ||
| 125 | } | 126 | } |
| 126 | 127 | ||
| 127 | if (d_is_dir(path->dentry) && | 128 | if (d_is_dir(path->dentry) && |
| @@ -178,8 +179,6 @@ init: __maybe_unused | |||
| 178 | 179 | ||
| 179 | static int fanotify_handle_event(struct fsnotify_group *group, | 180 | static int fanotify_handle_event(struct fsnotify_group *group, |
| 180 | struct inode *inode, | 181 | struct inode *inode, |
| 181 | struct fsnotify_mark *inode_mark, | ||
| 182 | struct fsnotify_mark *fanotify_mark, | ||
| 183 | u32 mask, const void *data, int data_type, | 182 | u32 mask, const void *data, int data_type, |
| 184 | const unsigned char *file_name, u32 cookie, | 183 | const unsigned char *file_name, u32 cookie, |
| 185 | struct fsnotify_iter_info *iter_info) | 184 | struct fsnotify_iter_info *iter_info) |
| @@ -199,8 +198,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, | |||
| 199 | BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM); | 198 | BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM); |
| 200 | BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR); | 199 | BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR); |
| 201 | 200 | ||
| 202 | if (!fanotify_should_send_event(inode_mark, fanotify_mark, mask, data, | 201 | if (!fanotify_should_send_event(iter_info, mask, data, data_type)) |
| 203 | data_type)) | ||
| 204 | return 0; | 202 | return 0; |
| 205 | 203 | ||
| 206 | pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode, | 204 | pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode, |
diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c index d478629c728b..10aac1942c9f 100644 --- a/fs/notify/fdinfo.c +++ b/fs/notify/fdinfo.c | |||
| @@ -77,7 +77,7 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) | |||
| 77 | struct inotify_inode_mark *inode_mark; | 77 | struct inotify_inode_mark *inode_mark; |
| 78 | struct inode *inode; | 78 | struct inode *inode; |
| 79 | 79 | ||
| 80 | if (!(mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE)) | 80 | if (mark->connector->type != FSNOTIFY_OBJ_TYPE_INODE) |
| 81 | return; | 81 | return; |
| 82 | 82 | ||
| 83 | inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark); | 83 | inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark); |
| @@ -116,7 +116,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) | |||
| 116 | if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY) | 116 | if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY) |
| 117 | mflags |= FAN_MARK_IGNORED_SURV_MODIFY; | 117 | mflags |= FAN_MARK_IGNORED_SURV_MODIFY; |
| 118 | 118 | ||
| 119 | if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE) { | 119 | if (mark->connector->type == FSNOTIFY_OBJ_TYPE_INODE) { |
| 120 | inode = igrab(mark->connector->inode); | 120 | inode = igrab(mark->connector->inode); |
| 121 | if (!inode) | 121 | if (!inode) |
| 122 | return; | 122 | return; |
| @@ -126,7 +126,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) | |||
| 126 | show_mark_fhandle(m, inode); | 126 | show_mark_fhandle(m, inode); |
| 127 | seq_putc(m, '\n'); | 127 | seq_putc(m, '\n'); |
| 128 | iput(inode); | 128 | iput(inode); |
| 129 | } else if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) { | 129 | } else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) { |
| 130 | struct mount *mnt = real_mount(mark->connector->mnt); | 130 | struct mount *mnt = real_mount(mark->connector->mnt); |
| 131 | 131 | ||
| 132 | seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n", | 132 | seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n", |
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 613ec7e5a465..f174397b63a0 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
| @@ -184,8 +184,6 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask | |||
| 184 | EXPORT_SYMBOL_GPL(__fsnotify_parent); | 184 | EXPORT_SYMBOL_GPL(__fsnotify_parent); |
| 185 | 185 | ||
| 186 | static int send_to_group(struct inode *to_tell, | 186 | static int send_to_group(struct inode *to_tell, |
| 187 | struct fsnotify_mark *inode_mark, | ||
| 188 | struct fsnotify_mark *vfsmount_mark, | ||
| 189 | __u32 mask, const void *data, | 187 | __u32 mask, const void *data, |
| 190 | int data_is, u32 cookie, | 188 | int data_is, u32 cookie, |
| 191 | const unsigned char *file_name, | 189 | const unsigned char *file_name, |
| @@ -195,48 +193,45 @@ static int send_to_group(struct inode *to_tell, | |||
| 195 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); | 193 | __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); |
| 196 | __u32 marks_mask = 0; | 194 | __u32 marks_mask = 0; |
| 197 | __u32 marks_ignored_mask = 0; | 195 | __u32 marks_ignored_mask = 0; |
| 196 | struct fsnotify_mark *mark; | ||
| 197 | int type; | ||
| 198 | 198 | ||
| 199 | if (unlikely(!inode_mark && !vfsmount_mark)) { | 199 | if (WARN_ON(!iter_info->report_mask)) |
| 200 | BUG(); | ||
| 201 | return 0; | 200 | return 0; |
| 202 | } | ||
| 203 | 201 | ||
| 204 | /* clear ignored on inode modification */ | 202 | /* clear ignored on inode modification */ |
| 205 | if (mask & FS_MODIFY) { | 203 | if (mask & FS_MODIFY) { |
| 206 | if (inode_mark && | 204 | fsnotify_foreach_obj_type(type) { |
| 207 | !(inode_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) | 205 | if (!fsnotify_iter_should_report_type(iter_info, type)) |
| 208 | inode_mark->ignored_mask = 0; | 206 | continue; |
| 209 | if (vfsmount_mark && | 207 | mark = iter_info->marks[type]; |
| 210 | !(vfsmount_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) | 208 | if (mark && |
| 211 | vfsmount_mark->ignored_mask = 0; | 209 | !(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) |
| 212 | } | 210 | mark->ignored_mask = 0; |
| 213 | 211 | } | |
| 214 | /* does the inode mark tell us to do something? */ | ||
| 215 | if (inode_mark) { | ||
| 216 | group = inode_mark->group; | ||
| 217 | marks_mask |= inode_mark->mask; | ||
| 218 | marks_ignored_mask |= inode_mark->ignored_mask; | ||
| 219 | } | 212 | } |
| 220 | 213 | ||
| 221 | /* does the vfsmount_mark tell us to do something? */ | 214 | fsnotify_foreach_obj_type(type) { |
| 222 | if (vfsmount_mark) { | 215 | if (!fsnotify_iter_should_report_type(iter_info, type)) |
| 223 | group = vfsmount_mark->group; | 216 | continue; |
| 224 | marks_mask |= vfsmount_mark->mask; | 217 | mark = iter_info->marks[type]; |
| 225 | marks_ignored_mask |= vfsmount_mark->ignored_mask; | 218 | /* does the object mark tell us to do something? */ |
| 219 | if (mark) { | ||
| 220 | group = mark->group; | ||
| 221 | marks_mask |= mark->mask; | ||
| 222 | marks_ignored_mask |= mark->ignored_mask; | ||
| 223 | } | ||
| 226 | } | 224 | } |
| 227 | 225 | ||
| 228 | pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p" | 226 | pr_debug("%s: group=%p to_tell=%p mask=%x marks_mask=%x marks_ignored_mask=%x" |
| 229 | " vfsmount_mark=%p marks_mask=%x marks_ignored_mask=%x" | ||
| 230 | " data=%p data_is=%d cookie=%d\n", | 227 | " data=%p data_is=%d cookie=%d\n", |
| 231 | __func__, group, to_tell, mask, inode_mark, vfsmount_mark, | 228 | __func__, group, to_tell, mask, marks_mask, marks_ignored_mask, |
| 232 | marks_mask, marks_ignored_mask, data, | 229 | data, data_is, cookie); |
| 233 | data_is, cookie); | ||
| 234 | 230 | ||
| 235 | if (!(test_mask & marks_mask & ~marks_ignored_mask)) | 231 | if (!(test_mask & marks_mask & ~marks_ignored_mask)) |
| 236 | return 0; | 232 | return 0; |
| 237 | 233 | ||
| 238 | return group->ops->handle_event(group, to_tell, inode_mark, | 234 | return group->ops->handle_event(group, to_tell, mask, data, data_is, |
| 239 | vfsmount_mark, mask, data, data_is, | ||
| 240 | file_name, cookie, iter_info); | 235 | file_name, cookie, iter_info); |
| 241 | } | 236 | } |
| 242 | 237 | ||
| @@ -264,6 +259,57 @@ static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark) | |||
| 264 | } | 259 | } |
| 265 | 260 | ||
| 266 | /* | 261 | /* |
| 262 | * iter_info is a multi head priority queue of marks. | ||
| 263 | * Pick a subset of marks from queue heads, all with the | ||
| 264 | * same group and set the report_mask for selected subset. | ||
| 265 | * Returns the report_mask of the selected subset. | ||
| 266 | */ | ||
| 267 | static unsigned int fsnotify_iter_select_report_types( | ||
| 268 | struct fsnotify_iter_info *iter_info) | ||
| 269 | { | ||
| 270 | struct fsnotify_group *max_prio_group = NULL; | ||
| 271 | struct fsnotify_mark *mark; | ||
| 272 | int type; | ||
| 273 | |||
| 274 | /* Choose max prio group among groups of all queue heads */ | ||
| 275 | fsnotify_foreach_obj_type(type) { | ||
| 276 | mark = iter_info->marks[type]; | ||
| 277 | if (mark && | ||
| 278 | fsnotify_compare_groups(max_prio_group, mark->group) > 0) | ||
| 279 | max_prio_group = mark->group; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (!max_prio_group) | ||
| 283 | return 0; | ||
| 284 | |||
| 285 | /* Set the report mask for marks from same group as max prio group */ | ||
| 286 | iter_info->report_mask = 0; | ||
| 287 | fsnotify_foreach_obj_type(type) { | ||
| 288 | mark = iter_info->marks[type]; | ||
| 289 | if (mark && | ||
| 290 | fsnotify_compare_groups(max_prio_group, mark->group) == 0) | ||
| 291 | fsnotify_iter_set_report_type(iter_info, type); | ||
| 292 | } | ||
| 293 | |||
| 294 | return iter_info->report_mask; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* | ||
| 298 | * Pop from iter_info multi head queue, the marks that were iterated in the | ||
| 299 | * current iteration step. | ||
| 300 | */ | ||
| 301 | static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info) | ||
| 302 | { | ||
| 303 | int type; | ||
| 304 | |||
| 305 | fsnotify_foreach_obj_type(type) { | ||
| 306 | if (fsnotify_iter_should_report_type(iter_info, type)) | ||
| 307 | iter_info->marks[type] = | ||
| 308 | fsnotify_next_mark(iter_info->marks[type]); | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | /* | ||
| 267 | * This is the main call to fsnotify. The VFS calls into hook specific functions | 313 | * This is the main call to fsnotify. The VFS calls into hook specific functions |
| 268 | * in linux/fsnotify.h. Those functions then in turn call here. Here will call | 314 | * in linux/fsnotify.h. Those functions then in turn call here. Here will call |
| 269 | * out to all of the registered fsnotify_group. Those groups can then use the | 315 | * out to all of the registered fsnotify_group. Those groups can then use the |
| @@ -307,15 +353,15 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, | |||
| 307 | 353 | ||
| 308 | if ((mask & FS_MODIFY) || | 354 | if ((mask & FS_MODIFY) || |
| 309 | (test_mask & to_tell->i_fsnotify_mask)) { | 355 | (test_mask & to_tell->i_fsnotify_mask)) { |
| 310 | iter_info.inode_mark = | 356 | iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] = |
| 311 | fsnotify_first_mark(&to_tell->i_fsnotify_marks); | 357 | fsnotify_first_mark(&to_tell->i_fsnotify_marks); |
| 312 | } | 358 | } |
| 313 | 359 | ||
| 314 | if (mnt && ((mask & FS_MODIFY) || | 360 | if (mnt && ((mask & FS_MODIFY) || |
| 315 | (test_mask & mnt->mnt_fsnotify_mask))) { | 361 | (test_mask & mnt->mnt_fsnotify_mask))) { |
| 316 | iter_info.inode_mark = | 362 | iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] = |
| 317 | fsnotify_first_mark(&to_tell->i_fsnotify_marks); | 363 | fsnotify_first_mark(&to_tell->i_fsnotify_marks); |
| 318 | iter_info.vfsmount_mark = | 364 | iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] = |
| 319 | fsnotify_first_mark(&mnt->mnt_fsnotify_marks); | 365 | fsnotify_first_mark(&mnt->mnt_fsnotify_marks); |
| 320 | } | 366 | } |
| 321 | 367 | ||
| @@ -324,32 +370,14 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, | |||
| 324 | * ignore masks are properly reflected for mount mark notifications. | 370 | * ignore masks are properly reflected for mount mark notifications. |
| 325 | * That's why this traversal is so complicated... | 371 | * That's why this traversal is so complicated... |
| 326 | */ | 372 | */ |
| 327 | while (iter_info.inode_mark || iter_info.vfsmount_mark) { | 373 | while (fsnotify_iter_select_report_types(&iter_info)) { |
| 328 | struct fsnotify_mark *inode_mark = iter_info.inode_mark; | 374 | ret = send_to_group(to_tell, mask, data, data_is, cookie, |
| 329 | struct fsnotify_mark *vfsmount_mark = iter_info.vfsmount_mark; | 375 | file_name, &iter_info); |
| 330 | |||
| 331 | if (inode_mark && vfsmount_mark) { | ||
| 332 | int cmp = fsnotify_compare_groups(inode_mark->group, | ||
| 333 | vfsmount_mark->group); | ||
| 334 | if (cmp > 0) | ||
| 335 | inode_mark = NULL; | ||
| 336 | else if (cmp < 0) | ||
| 337 | vfsmount_mark = NULL; | ||
| 338 | } | ||
| 339 | |||
| 340 | ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask, | ||
| 341 | data, data_is, cookie, file_name, | ||
| 342 | &iter_info); | ||
| 343 | 376 | ||
| 344 | if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS)) | 377 | if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS)) |
| 345 | goto out; | 378 | goto out; |
| 346 | 379 | ||
| 347 | if (inode_mark) | 380 | fsnotify_iter_next(&iter_info); |
| 348 | iter_info.inode_mark = | ||
| 349 | fsnotify_next_mark(iter_info.inode_mark); | ||
| 350 | if (vfsmount_mark) | ||
| 351 | iter_info.vfsmount_mark = | ||
| 352 | fsnotify_next_mark(iter_info.vfsmount_mark); | ||
| 353 | } | 381 | } |
| 354 | ret = 0; | 382 | ret = 0; |
| 355 | out: | 383 | out: |
diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h index 60f365dc1408..34515d2c4ba3 100644 --- a/fs/notify/fsnotify.h +++ b/fs/notify/fsnotify.h | |||
| @@ -9,12 +9,6 @@ | |||
| 9 | 9 | ||
| 10 | #include "../mount.h" | 10 | #include "../mount.h" |
| 11 | 11 | ||
| 12 | struct fsnotify_iter_info { | ||
| 13 | struct fsnotify_mark *inode_mark; | ||
| 14 | struct fsnotify_mark *vfsmount_mark; | ||
| 15 | int srcu_idx; | ||
| 16 | }; | ||
| 17 | |||
| 18 | /* destroy all events sitting in this groups notification queue */ | 12 | /* destroy all events sitting in this groups notification queue */ |
| 19 | extern void fsnotify_flush_notify(struct fsnotify_group *group); | 13 | extern void fsnotify_flush_notify(struct fsnotify_group *group); |
| 20 | 14 | ||
diff --git a/fs/notify/group.c b/fs/notify/group.c index b7a4b6a69efa..aa5468f23e45 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c | |||
| @@ -67,7 +67,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group) | |||
| 67 | fsnotify_group_stop_queueing(group); | 67 | fsnotify_group_stop_queueing(group); |
| 68 | 68 | ||
| 69 | /* Clear all marks for this group and queue them for destruction */ | 69 | /* Clear all marks for this group and queue them for destruction */ |
| 70 | fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_ALL_TYPES); | 70 | fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_ALL_TYPES_MASK); |
| 71 | 71 | ||
| 72 | /* | 72 | /* |
| 73 | * Some marks can still be pinned when waiting for response from | 73 | * Some marks can still be pinned when waiting for response from |
diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h index c00d2caca894..7e4578d35b61 100644 --- a/fs/notify/inotify/inotify.h +++ b/fs/notify/inotify/inotify.h | |||
| @@ -25,8 +25,6 @@ extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, | |||
| 25 | struct fsnotify_group *group); | 25 | struct fsnotify_group *group); |
| 26 | extern int inotify_handle_event(struct fsnotify_group *group, | 26 | extern int inotify_handle_event(struct fsnotify_group *group, |
| 27 | struct inode *inode, | 27 | struct inode *inode, |
| 28 | struct fsnotify_mark *inode_mark, | ||
| 29 | struct fsnotify_mark *vfsmount_mark, | ||
| 30 | u32 mask, const void *data, int data_type, | 28 | u32 mask, const void *data, int data_type, |
| 31 | const unsigned char *file_name, u32 cookie, | 29 | const unsigned char *file_name, u32 cookie, |
| 32 | struct fsnotify_iter_info *iter_info); | 30 | struct fsnotify_iter_info *iter_info); |
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 40dedb37a1f3..9ab6dde38a14 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c | |||
| @@ -65,12 +65,11 @@ static int inotify_merge(struct list_head *list, | |||
| 65 | 65 | ||
| 66 | int inotify_handle_event(struct fsnotify_group *group, | 66 | int inotify_handle_event(struct fsnotify_group *group, |
| 67 | struct inode *inode, | 67 | struct inode *inode, |
| 68 | struct fsnotify_mark *inode_mark, | ||
| 69 | struct fsnotify_mark *vfsmount_mark, | ||
| 70 | u32 mask, const void *data, int data_type, | 68 | u32 mask, const void *data, int data_type, |
| 71 | const unsigned char *file_name, u32 cookie, | 69 | const unsigned char *file_name, u32 cookie, |
| 72 | struct fsnotify_iter_info *iter_info) | 70 | struct fsnotify_iter_info *iter_info) |
| 73 | { | 71 | { |
| 72 | struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); | ||
| 74 | struct inotify_inode_mark *i_mark; | 73 | struct inotify_inode_mark *i_mark; |
| 75 | struct inotify_event_info *event; | 74 | struct inotify_event_info *event; |
| 76 | struct fsnotify_event *fsn_event; | 75 | struct fsnotify_event *fsn_event; |
| @@ -78,7 +77,8 @@ int inotify_handle_event(struct fsnotify_group *group, | |||
| 78 | int len = 0; | 77 | int len = 0; |
| 79 | int alloc_len = sizeof(struct inotify_event_info); | 78 | int alloc_len = sizeof(struct inotify_event_info); |
| 80 | 79 | ||
| 81 | BUG_ON(vfsmount_mark); | 80 | if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info))) |
| 81 | return 0; | ||
| 82 | 82 | ||
| 83 | if ((inode_mark->mask & FS_EXCL_UNLINK) && | 83 | if ((inode_mark->mask & FS_EXCL_UNLINK) && |
| 84 | (data_type == FSNOTIFY_EVENT_PATH)) { | 84 | (data_type == FSNOTIFY_EVENT_PATH)) { |
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index ef32f3657958..1cf5b779d862 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
| @@ -485,10 +485,14 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, | |||
| 485 | struct fsnotify_group *group) | 485 | struct fsnotify_group *group) |
| 486 | { | 486 | { |
| 487 | struct inotify_inode_mark *i_mark; | 487 | struct inotify_inode_mark *i_mark; |
| 488 | struct fsnotify_iter_info iter_info = { }; | ||
| 489 | |||
| 490 | fsnotify_iter_set_report_type_mark(&iter_info, FSNOTIFY_OBJ_TYPE_INODE, | ||
| 491 | fsn_mark); | ||
| 488 | 492 | ||
| 489 | /* Queue ignore event for the watch */ | 493 | /* Queue ignore event for the watch */ |
| 490 | inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED, | 494 | inotify_handle_event(group, NULL, FS_IN_IGNORED, NULL, |
| 491 | NULL, FSNOTIFY_EVENT_NONE, NULL, 0, NULL); | 495 | FSNOTIFY_EVENT_NONE, NULL, 0, &iter_info); |
| 492 | 496 | ||
| 493 | i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); | 497 | i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); |
| 494 | /* remove this mark from the idr */ | 498 | /* remove this mark from the idr */ |
| @@ -578,7 +582,7 @@ static int inotify_new_watch(struct fsnotify_group *group, | |||
| 578 | } | 582 | } |
| 579 | 583 | ||
| 580 | /* we are on the idr, now get on the inode */ | 584 | /* we are on the idr, now get on the inode */ |
| 581 | ret = fsnotify_add_mark_locked(&tmp_i_mark->fsn_mark, inode, NULL, 0); | 585 | ret = fsnotify_add_inode_mark_locked(&tmp_i_mark->fsn_mark, inode, 0); |
| 582 | if (ret) { | 586 | if (ret) { |
| 583 | /* we failed to get on the inode, get off the idr */ | 587 | /* we failed to get on the inode, get off the idr */ |
| 584 | inotify_remove_from_idr(group, tmp_i_mark); | 588 | inotify_remove_from_idr(group, tmp_i_mark); |
diff --git a/fs/notify/mark.c b/fs/notify/mark.c index e9191b416434..61f4c5fa34c7 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c | |||
| @@ -119,9 +119,9 @@ static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) | |||
| 119 | if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) | 119 | if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) |
| 120 | new_mask |= mark->mask; | 120 | new_mask |= mark->mask; |
| 121 | } | 121 | } |
| 122 | if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) | 122 | if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) |
| 123 | conn->inode->i_fsnotify_mask = new_mask; | 123 | conn->inode->i_fsnotify_mask = new_mask; |
| 124 | else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) | 124 | else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) |
| 125 | real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask; | 125 | real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| @@ -139,7 +139,7 @@ void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) | |||
| 139 | spin_lock(&conn->lock); | 139 | spin_lock(&conn->lock); |
| 140 | __fsnotify_recalc_mask(conn); | 140 | __fsnotify_recalc_mask(conn); |
| 141 | spin_unlock(&conn->lock); | 141 | spin_unlock(&conn->lock); |
| 142 | if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) | 142 | if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) |
| 143 | __fsnotify_update_child_dentry_flags(conn->inode); | 143 | __fsnotify_update_child_dentry_flags(conn->inode); |
| 144 | } | 144 | } |
| 145 | 145 | ||
| @@ -166,18 +166,18 @@ static struct inode *fsnotify_detach_connector_from_object( | |||
| 166 | { | 166 | { |
| 167 | struct inode *inode = NULL; | 167 | struct inode *inode = NULL; |
| 168 | 168 | ||
| 169 | if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) { | 169 | if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) { |
| 170 | inode = conn->inode; | 170 | inode = conn->inode; |
| 171 | rcu_assign_pointer(inode->i_fsnotify_marks, NULL); | 171 | rcu_assign_pointer(inode->i_fsnotify_marks, NULL); |
| 172 | inode->i_fsnotify_mask = 0; | 172 | inode->i_fsnotify_mask = 0; |
| 173 | conn->inode = NULL; | 173 | conn->inode = NULL; |
| 174 | conn->flags &= ~FSNOTIFY_OBJ_TYPE_INODE; | 174 | conn->type = FSNOTIFY_OBJ_TYPE_DETACHED; |
| 175 | } else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) { | 175 | } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) { |
| 176 | rcu_assign_pointer(real_mount(conn->mnt)->mnt_fsnotify_marks, | 176 | rcu_assign_pointer(real_mount(conn->mnt)->mnt_fsnotify_marks, |
| 177 | NULL); | 177 | NULL); |
| 178 | real_mount(conn->mnt)->mnt_fsnotify_mask = 0; | 178 | real_mount(conn->mnt)->mnt_fsnotify_mask = 0; |
| 179 | conn->mnt = NULL; | 179 | conn->mnt = NULL; |
| 180 | conn->flags &= ~FSNOTIFY_OBJ_TYPE_VFSMOUNT; | 180 | conn->type = FSNOTIFY_OBJ_TYPE_DETACHED; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | return inode; | 183 | return inode; |
| @@ -294,12 +294,12 @@ static void fsnotify_put_mark_wake(struct fsnotify_mark *mark) | |||
| 294 | 294 | ||
| 295 | bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) | 295 | bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) |
| 296 | { | 296 | { |
| 297 | /* This can fail if mark is being removed */ | 297 | int type; |
| 298 | if (!fsnotify_get_mark_safe(iter_info->inode_mark)) | 298 | |
| 299 | return false; | 299 | fsnotify_foreach_obj_type(type) { |
| 300 | if (!fsnotify_get_mark_safe(iter_info->vfsmount_mark)) { | 300 | /* This can fail if mark is being removed */ |
| 301 | fsnotify_put_mark_wake(iter_info->inode_mark); | 301 | if (!fsnotify_get_mark_safe(iter_info->marks[type])) |
| 302 | return false; | 302 | goto fail; |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | /* | 305 | /* |
| @@ -310,13 +310,20 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) | |||
| 310 | srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx); | 310 | srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx); |
| 311 | 311 | ||
| 312 | return true; | 312 | return true; |
| 313 | |||
| 314 | fail: | ||
| 315 | for (type--; type >= 0; type--) | ||
| 316 | fsnotify_put_mark_wake(iter_info->marks[type]); | ||
| 317 | return false; | ||
| 313 | } | 318 | } |
| 314 | 319 | ||
| 315 | void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info) | 320 | void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info) |
| 316 | { | 321 | { |
| 322 | int type; | ||
| 323 | |||
| 317 | iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); | 324 | iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); |
| 318 | fsnotify_put_mark_wake(iter_info->inode_mark); | 325 | fsnotify_foreach_obj_type(type) |
| 319 | fsnotify_put_mark_wake(iter_info->vfsmount_mark); | 326 | fsnotify_put_mark_wake(iter_info->marks[type]); |
| 320 | } | 327 | } |
| 321 | 328 | ||
| 322 | /* | 329 | /* |
| @@ -442,10 +449,10 @@ static int fsnotify_attach_connector_to_object( | |||
| 442 | spin_lock_init(&conn->lock); | 449 | spin_lock_init(&conn->lock); |
| 443 | INIT_HLIST_HEAD(&conn->list); | 450 | INIT_HLIST_HEAD(&conn->list); |
| 444 | if (inode) { | 451 | if (inode) { |
| 445 | conn->flags = FSNOTIFY_OBJ_TYPE_INODE; | 452 | conn->type = FSNOTIFY_OBJ_TYPE_INODE; |
| 446 | conn->inode = igrab(inode); | 453 | conn->inode = igrab(inode); |
| 447 | } else { | 454 | } else { |
| 448 | conn->flags = FSNOTIFY_OBJ_TYPE_VFSMOUNT; | 455 | conn->type = FSNOTIFY_OBJ_TYPE_VFSMOUNT; |
| 449 | conn->mnt = mnt; | 456 | conn->mnt = mnt; |
| 450 | } | 457 | } |
| 451 | /* | 458 | /* |
| @@ -479,8 +486,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector( | |||
| 479 | if (!conn) | 486 | if (!conn) |
| 480 | goto out; | 487 | goto out; |
| 481 | spin_lock(&conn->lock); | 488 | spin_lock(&conn->lock); |
| 482 | if (!(conn->flags & (FSNOTIFY_OBJ_TYPE_INODE | | 489 | if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) { |
| 483 | FSNOTIFY_OBJ_TYPE_VFSMOUNT))) { | ||
| 484 | spin_unlock(&conn->lock); | 490 | spin_unlock(&conn->lock); |
| 485 | srcu_read_unlock(&fsnotify_mark_srcu, idx); | 491 | srcu_read_unlock(&fsnotify_mark_srcu, idx); |
| 486 | return NULL; | 492 | return NULL; |
| @@ -646,16 +652,16 @@ struct fsnotify_mark *fsnotify_find_mark( | |||
| 646 | return NULL; | 652 | return NULL; |
| 647 | } | 653 | } |
| 648 | 654 | ||
| 649 | /* Clear any marks in a group with given type */ | 655 | /* Clear any marks in a group with given type mask */ |
| 650 | void fsnotify_clear_marks_by_group(struct fsnotify_group *group, | 656 | void fsnotify_clear_marks_by_group(struct fsnotify_group *group, |
| 651 | unsigned int type) | 657 | unsigned int type_mask) |
| 652 | { | 658 | { |
| 653 | struct fsnotify_mark *lmark, *mark; | 659 | struct fsnotify_mark *lmark, *mark; |
| 654 | LIST_HEAD(to_free); | 660 | LIST_HEAD(to_free); |
| 655 | struct list_head *head = &to_free; | 661 | struct list_head *head = &to_free; |
| 656 | 662 | ||
| 657 | /* Skip selection step if we want to clear all marks. */ | 663 | /* Skip selection step if we want to clear all marks. */ |
| 658 | if (type == FSNOTIFY_OBJ_ALL_TYPES) { | 664 | if (type_mask == FSNOTIFY_OBJ_ALL_TYPES_MASK) { |
| 659 | head = &group->marks_list; | 665 | head = &group->marks_list; |
| 660 | goto clear; | 666 | goto clear; |
| 661 | } | 667 | } |
| @@ -670,7 +676,7 @@ void fsnotify_clear_marks_by_group(struct fsnotify_group *group, | |||
| 670 | */ | 676 | */ |
| 671 | mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); | 677 | mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); |
| 672 | list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { | 678 | list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { |
| 673 | if (mark->connector->flags & type) | 679 | if ((1U << mark->connector->type) & type_mask) |
| 674 | list_move(&mark->g_list, &to_free); | 680 | list_move(&mark->g_list, &to_free); |
| 675 | } | 681 | } |
| 676 | mutex_unlock(&group->mark_mutex); | 682 | mutex_unlock(&group->mark_mutex); |
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index e64c0294f50b..b38964a7a521 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
| @@ -98,8 +98,6 @@ struct fsnotify_iter_info; | |||
| 98 | struct fsnotify_ops { | 98 | struct fsnotify_ops { |
| 99 | int (*handle_event)(struct fsnotify_group *group, | 99 | int (*handle_event)(struct fsnotify_group *group, |
| 100 | struct inode *inode, | 100 | struct inode *inode, |
| 101 | struct fsnotify_mark *inode_mark, | ||
| 102 | struct fsnotify_mark *vfsmount_mark, | ||
| 103 | u32 mask, const void *data, int data_type, | 101 | u32 mask, const void *data, int data_type, |
| 104 | const unsigned char *file_name, u32 cookie, | 102 | const unsigned char *file_name, u32 cookie, |
| 105 | struct fsnotify_iter_info *iter_info); | 103 | struct fsnotify_iter_info *iter_info); |
| @@ -201,6 +199,57 @@ struct fsnotify_group { | |||
| 201 | #define FSNOTIFY_EVENT_PATH 1 | 199 | #define FSNOTIFY_EVENT_PATH 1 |
| 202 | #define FSNOTIFY_EVENT_INODE 2 | 200 | #define FSNOTIFY_EVENT_INODE 2 |
| 203 | 201 | ||
| 202 | enum fsnotify_obj_type { | ||
| 203 | FSNOTIFY_OBJ_TYPE_INODE, | ||
| 204 | FSNOTIFY_OBJ_TYPE_VFSMOUNT, | ||
| 205 | FSNOTIFY_OBJ_TYPE_COUNT, | ||
| 206 | FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT | ||
| 207 | }; | ||
| 208 | |||
| 209 | #define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) | ||
| 210 | #define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) | ||
| 211 | #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) | ||
| 212 | |||
| 213 | struct fsnotify_iter_info { | ||
| 214 | struct fsnotify_mark *marks[FSNOTIFY_OBJ_TYPE_COUNT]; | ||
| 215 | unsigned int report_mask; | ||
| 216 | int srcu_idx; | ||
| 217 | }; | ||
| 218 | |||
| 219 | static inline bool fsnotify_iter_should_report_type( | ||
| 220 | struct fsnotify_iter_info *iter_info, int type) | ||
| 221 | { | ||
| 222 | return (iter_info->report_mask & (1U << type)); | ||
| 223 | } | ||
| 224 | |||
| 225 | static inline void fsnotify_iter_set_report_type( | ||
| 226 | struct fsnotify_iter_info *iter_info, int type) | ||
| 227 | { | ||
| 228 | iter_info->report_mask |= (1U << type); | ||
| 229 | } | ||
| 230 | |||
| 231 | static inline void fsnotify_iter_set_report_type_mark( | ||
| 232 | struct fsnotify_iter_info *iter_info, int type, | ||
| 233 | struct fsnotify_mark *mark) | ||
| 234 | { | ||
| 235 | iter_info->marks[type] = mark; | ||
| 236 | iter_info->report_mask |= (1U << type); | ||
| 237 | } | ||
| 238 | |||
| 239 | #define FSNOTIFY_ITER_FUNCS(name, NAME) \ | ||
| 240 | static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ | ||
| 241 | struct fsnotify_iter_info *iter_info) \ | ||
| 242 | { \ | ||
| 243 | return (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_##NAME##_FL) ? \ | ||
| 244 | iter_info->marks[FSNOTIFY_OBJ_TYPE_##NAME] : NULL; \ | ||
| 245 | } | ||
| 246 | |||
| 247 | FSNOTIFY_ITER_FUNCS(inode, INODE) | ||
| 248 | FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) | ||
| 249 | |||
| 250 | #define fsnotify_foreach_obj_type(type) \ | ||
| 251 | for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++) | ||
| 252 | |||
| 204 | /* | 253 | /* |
| 205 | * Inode / vfsmount point to this structure which tracks all marks attached to | 254 | * Inode / vfsmount point to this structure which tracks all marks attached to |
| 206 | * the inode / vfsmount. The reference to inode / vfsmount is held by this | 255 | * the inode / vfsmount. The reference to inode / vfsmount is held by this |
| @@ -209,11 +258,7 @@ struct fsnotify_group { | |||
| 209 | */ | 258 | */ |
| 210 | struct fsnotify_mark_connector { | 259 | struct fsnotify_mark_connector { |
| 211 | spinlock_t lock; | 260 | spinlock_t lock; |
| 212 | #define FSNOTIFY_OBJ_TYPE_INODE 0x01 | 261 | unsigned int type; /* Type of object [lock] */ |
| 213 | #define FSNOTIFY_OBJ_TYPE_VFSMOUNT 0x02 | ||
| 214 | #define FSNOTIFY_OBJ_ALL_TYPES (FSNOTIFY_OBJ_TYPE_INODE | \ | ||
| 215 | FSNOTIFY_OBJ_TYPE_VFSMOUNT) | ||
| 216 | unsigned int flags; /* Type of object [lock] */ | ||
| 217 | union { /* Object pointer [lock] */ | 262 | union { /* Object pointer [lock] */ |
| 218 | struct inode *inode; | 263 | struct inode *inode; |
| 219 | struct vfsmount *mnt; | 264 | struct vfsmount *mnt; |
| @@ -356,7 +401,21 @@ extern struct fsnotify_mark *fsnotify_find_mark( | |||
| 356 | extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct inode *inode, | 401 | extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct inode *inode, |
| 357 | struct vfsmount *mnt, int allow_dups); | 402 | struct vfsmount *mnt, int allow_dups); |
| 358 | extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark, | 403 | extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark, |
| 359 | struct inode *inode, struct vfsmount *mnt, int allow_dups); | 404 | struct inode *inode, struct vfsmount *mnt, |
| 405 | int allow_dups); | ||
| 406 | /* attach the mark to the inode */ | ||
| 407 | static inline int fsnotify_add_inode_mark(struct fsnotify_mark *mark, | ||
| 408 | struct inode *inode, | ||
| 409 | int allow_dups) | ||
| 410 | { | ||
| 411 | return fsnotify_add_mark(mark, inode, NULL, allow_dups); | ||
| 412 | } | ||
| 413 | static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark, | ||
| 414 | struct inode *inode, | ||
| 415 | int allow_dups) | ||
| 416 | { | ||
| 417 | return fsnotify_add_mark_locked(mark, inode, NULL, allow_dups); | ||
| 418 | } | ||
| 360 | /* given a group and a mark, flag mark to be freed when all references are dropped */ | 419 | /* given a group and a mark, flag mark to be freed when all references are dropped */ |
| 361 | extern void fsnotify_destroy_mark(struct fsnotify_mark *mark, | 420 | extern void fsnotify_destroy_mark(struct fsnotify_mark *mark, |
| 362 | struct fsnotify_group *group); | 421 | struct fsnotify_group *group); |
| @@ -369,12 +428,12 @@ extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group, unsigned | |||
| 369 | /* run all the marks in a group, and clear all of the vfsmount marks */ | 428 | /* run all the marks in a group, and clear all of the vfsmount marks */ |
| 370 | static inline void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group) | 429 | static inline void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group) |
| 371 | { | 430 | { |
| 372 | fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT); | 431 | fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL); |
| 373 | } | 432 | } |
| 374 | /* run all the marks in a group, and clear all of the inode marks */ | 433 | /* run all the marks in a group, and clear all of the inode marks */ |
| 375 | static inline void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group) | 434 | static inline void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group) |
| 376 | { | 435 | { |
| 377 | fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE); | 436 | fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE_FL); |
| 378 | } | 437 | } |
| 379 | extern void fsnotify_get_mark(struct fsnotify_mark *mark); | 438 | extern void fsnotify_get_mark(struct fsnotify_mark *mark); |
| 380 | extern void fsnotify_put_mark(struct fsnotify_mark *mark); | 439 | extern void fsnotify_put_mark(struct fsnotify_mark *mark); |
diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c index 52f368b6561e..fba78047fb37 100644 --- a/kernel/audit_fsnotify.c +++ b/kernel/audit_fsnotify.c | |||
| @@ -109,7 +109,7 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pa | |||
| 109 | audit_update_mark(audit_mark, dentry->d_inode); | 109 | audit_update_mark(audit_mark, dentry->d_inode); |
| 110 | audit_mark->rule = krule; | 110 | audit_mark->rule = krule; |
| 111 | 111 | ||
| 112 | ret = fsnotify_add_mark(&audit_mark->mark, inode, NULL, true); | 112 | ret = fsnotify_add_inode_mark(&audit_mark->mark, inode, true); |
| 113 | if (ret < 0) { | 113 | if (ret < 0) { |
| 114 | fsnotify_put_mark(&audit_mark->mark); | 114 | fsnotify_put_mark(&audit_mark->mark); |
| 115 | audit_mark = ERR_PTR(ret); | 115 | audit_mark = ERR_PTR(ret); |
| @@ -165,12 +165,11 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark) | |||
| 165 | /* Update mark data in audit rules based on fsnotify events. */ | 165 | /* Update mark data in audit rules based on fsnotify events. */ |
| 166 | static int audit_mark_handle_event(struct fsnotify_group *group, | 166 | static int audit_mark_handle_event(struct fsnotify_group *group, |
| 167 | struct inode *to_tell, | 167 | struct inode *to_tell, |
| 168 | struct fsnotify_mark *inode_mark, | ||
| 169 | struct fsnotify_mark *vfsmount_mark, | ||
| 170 | u32 mask, const void *data, int data_type, | 168 | u32 mask, const void *data, int data_type, |
| 171 | const unsigned char *dname, u32 cookie, | 169 | const unsigned char *dname, u32 cookie, |
| 172 | struct fsnotify_iter_info *iter_info) | 170 | struct fsnotify_iter_info *iter_info) |
| 173 | { | 171 | { |
| 172 | struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); | ||
| 174 | struct audit_fsnotify_mark *audit_mark; | 173 | struct audit_fsnotify_mark *audit_mark; |
| 175 | const struct inode *inode = NULL; | 174 | const struct inode *inode = NULL; |
| 176 | 175 | ||
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 67e6956c0b61..c99ebaae5abc 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
| @@ -288,8 +288,8 @@ static void untag_chunk(struct node *p) | |||
| 288 | if (!new) | 288 | if (!new) |
| 289 | goto Fallback; | 289 | goto Fallback; |
| 290 | 290 | ||
| 291 | if (fsnotify_add_mark_locked(&new->mark, entry->connector->inode, | 291 | if (fsnotify_add_inode_mark_locked(&new->mark, entry->connector->inode, |
| 292 | NULL, 1)) { | 292 | 1)) { |
| 293 | fsnotify_put_mark(&new->mark); | 293 | fsnotify_put_mark(&new->mark); |
| 294 | goto Fallback; | 294 | goto Fallback; |
| 295 | } | 295 | } |
| @@ -354,7 +354,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) | |||
| 354 | return -ENOMEM; | 354 | return -ENOMEM; |
| 355 | 355 | ||
| 356 | entry = &chunk->mark; | 356 | entry = &chunk->mark; |
| 357 | if (fsnotify_add_mark(entry, inode, NULL, 0)) { | 357 | if (fsnotify_add_inode_mark(entry, inode, 0)) { |
| 358 | fsnotify_put_mark(entry); | 358 | fsnotify_put_mark(entry); |
| 359 | return -ENOSPC; | 359 | return -ENOSPC; |
| 360 | } | 360 | } |
| @@ -434,8 +434,8 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) | |||
| 434 | return -ENOENT; | 434 | return -ENOENT; |
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | if (fsnotify_add_mark_locked(chunk_entry, | 437 | if (fsnotify_add_inode_mark_locked(chunk_entry, |
| 438 | old_entry->connector->inode, NULL, 1)) { | 438 | old_entry->connector->inode, 1)) { |
| 439 | spin_unlock(&old_entry->lock); | 439 | spin_unlock(&old_entry->lock); |
| 440 | mutex_unlock(&old_entry->group->mark_mutex); | 440 | mutex_unlock(&old_entry->group->mark_mutex); |
| 441 | fsnotify_put_mark(chunk_entry); | 441 | fsnotify_put_mark(chunk_entry); |
| @@ -989,8 +989,6 @@ static void evict_chunk(struct audit_chunk *chunk) | |||
| 989 | 989 | ||
| 990 | static int audit_tree_handle_event(struct fsnotify_group *group, | 990 | static int audit_tree_handle_event(struct fsnotify_group *group, |
| 991 | struct inode *to_tell, | 991 | struct inode *to_tell, |
| 992 | struct fsnotify_mark *inode_mark, | ||
| 993 | struct fsnotify_mark *vfsmount_mark, | ||
| 994 | u32 mask, const void *data, int data_type, | 992 | u32 mask, const void *data, int data_type, |
| 995 | const unsigned char *file_name, u32 cookie, | 993 | const unsigned char *file_name, u32 cookie, |
| 996 | struct fsnotify_iter_info *iter_info) | 994 | struct fsnotify_iter_info *iter_info) |
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index f1ba88994508..c17c0c268436 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c | |||
| @@ -160,7 +160,7 @@ static struct audit_parent *audit_init_parent(struct path *path) | |||
| 160 | 160 | ||
| 161 | fsnotify_init_mark(&parent->mark, audit_watch_group); | 161 | fsnotify_init_mark(&parent->mark, audit_watch_group); |
| 162 | parent->mark.mask = AUDIT_FS_WATCH; | 162 | parent->mark.mask = AUDIT_FS_WATCH; |
| 163 | ret = fsnotify_add_mark(&parent->mark, inode, NULL, 0); | 163 | ret = fsnotify_add_inode_mark(&parent->mark, inode, 0); |
| 164 | if (ret < 0) { | 164 | if (ret < 0) { |
| 165 | audit_free_parent(parent); | 165 | audit_free_parent(parent); |
| 166 | return ERR_PTR(ret); | 166 | return ERR_PTR(ret); |
| @@ -472,12 +472,11 @@ void audit_remove_watch_rule(struct audit_krule *krule) | |||
| 472 | /* Update watch data in audit rules based on fsnotify events. */ | 472 | /* Update watch data in audit rules based on fsnotify events. */ |
| 473 | static int audit_watch_handle_event(struct fsnotify_group *group, | 473 | static int audit_watch_handle_event(struct fsnotify_group *group, |
| 474 | struct inode *to_tell, | 474 | struct inode *to_tell, |
| 475 | struct fsnotify_mark *inode_mark, | ||
| 476 | struct fsnotify_mark *vfsmount_mark, | ||
| 477 | u32 mask, const void *data, int data_type, | 475 | u32 mask, const void *data, int data_type, |
| 478 | const unsigned char *dname, u32 cookie, | 476 | const unsigned char *dname, u32 cookie, |
| 479 | struct fsnotify_iter_info *iter_info) | 477 | struct fsnotify_iter_info *iter_info) |
| 480 | { | 478 | { |
| 479 | struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); | ||
| 481 | const struct inode *inode; | 480 | const struct inode *inode; |
| 482 | struct audit_parent *parent; | 481 | struct audit_parent *parent; |
| 483 | 482 | ||
