]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - fs/notify/mark.c
fsnotify: remove mark->free_list
[mirror_ubuntu-zesty-kernel.git] / fs / notify / mark.c
index 39ddcaf0918f145fb3f2cb916d27aa1b866a220e..3b2d1ba41e7bc61eaf1022d237a7be073ce15564 100644 (file)
@@ -203,24 +203,34 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark,
        mutex_unlock(&group->mark_mutex);
 }
 
-/*
- * Destroy all marks in the given list. The marks must be already detached from
- * the original inode / vfsmount.
- */
-void fsnotify_destroy_marks(struct list_head *to_free)
+void fsnotify_destroy_marks(struct hlist_head *head, spinlock_t *lock)
 {
-       struct fsnotify_mark *mark, *lmark;
-       struct fsnotify_group *group;
-
-       list_for_each_entry_safe(mark, lmark, to_free, free_list) {
-               spin_lock(&mark->lock);
-               fsnotify_get_group(mark->group);
-               group = mark->group;
-               spin_unlock(&mark->lock);
+       struct fsnotify_mark *mark;
 
-               fsnotify_destroy_mark(mark, group);
+       while (1) {
+               /*
+                * We have to be careful since we can race with e.g.
+                * fsnotify_clear_marks_by_group() and once we drop 'lock',
+                * mark can get removed from the obj_list and destroyed. But
+                * we are holding mark reference so mark cannot be freed and
+                * calling fsnotify_destroy_mark() more than once is fine.
+                */
+               spin_lock(lock);
+               if (hlist_empty(head)) {
+                       spin_unlock(lock);
+                       break;
+               }
+               mark = hlist_entry(head->first, struct fsnotify_mark, obj_list);
+               /*
+                * We don't update i_fsnotify_mask / mnt_fsnotify_mask here
+                * since inode / mount is going away anyway. So just remove
+                * mark from the list.
+                */
+               hlist_del_init_rcu(&mark->obj_list);
+               fsnotify_get_mark(mark);
+               spin_unlock(lock);
+               fsnotify_destroy_mark(mark, mark->group);
                fsnotify_put_mark(mark);
-               fsnotify_put_group(group);
        }
 }