aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/mark.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/notify/mark.c')
-rw-r--r--fs/notify/mark.c52
1 files changed, 29 insertions, 23 deletions
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
295bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) 295bool 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
314fail:
315 for (type--; type >= 0; type--)
316 fsnotify_put_mark_wake(iter_info->marks[type]);
317 return false;
313} 318}
314 319
315void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info) 320void 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 */
650void fsnotify_clear_marks_by_group(struct fsnotify_group *group, 656void 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);