diff mbox

[11/22] fsnotify: Remove special handling of mark destruction on group shutdown

Message ID 20161222091538.28702-12-jack@suse.cz (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Kara Dec. 22, 2016, 9:15 a.m. UTC
Currently we queue all marks for destruction on group shutdown and then
destroy them from fsnotify_destroy_group() instead from a worker thread
which is the usual path. However worker can already be processing some
list of marks to destroy so this does not make 100% all marks are really
destroyed by the time group is shut down. This isn't a big problem as
each mark holds group reference and thus group stays partially alive
until all marks are really freed but there's no point in complicating
our lives - just wait for the delayed work to be finished instead.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/notify/fsnotify.h |  6 ++----
 fs/notify/group.c    | 10 ++++++----
 fs/notify/mark.c     |  9 +++++----
 3 files changed, 13 insertions(+), 12 deletions(-)

Comments

Amir Goldstein Dec. 23, 2016, 12:12 p.m. UTC | #1
On Thu, Dec 22, 2016 at 11:15 AM, Jan Kara <jack@suse.cz> wrote:
> Currently we queue all marks for destruction on group shutdown and then
> destroy them from fsnotify_destroy_group() instead from a worker thread
> which is the usual path. However worker can already be processing some
> list of marks to destroy so this does not make 100% all marks are really
> destroyed by the time group is shut down. This isn't a big problem as
> each mark holds group reference and thus group stays partially alive
> until all marks are really freed but there's no point in complicating
> our lives - just wait for the delayed work to be finished instead.
>
> Signed-off-by: Jan Kara <jack@suse.cz>

Isn't it *required* to wait for all marks to really be freed and not only
nice behavior following the same reason for
35e4817 fsnotify: avoid spurious EMFILE errors from inotify_init()

Otherwise

Reviewed-by: Amir Goldstein <amir73il@gmail.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jan Kara Dec. 23, 2016, 1:31 p.m. UTC | #2
On Fri 23-12-16 14:12:19, Amir Goldstein wrote:
> On Thu, Dec 22, 2016 at 11:15 AM, Jan Kara <jack@suse.cz> wrote:
> > Currently we queue all marks for destruction on group shutdown and then
> > destroy them from fsnotify_destroy_group() instead from a worker thread
> > which is the usual path. However worker can already be processing some
> > list of marks to destroy so this does not make 100% all marks are really
> > destroyed by the time group is shut down. This isn't a big problem as
> > each mark holds group reference and thus group stays partially alive
> > until all marks are really freed but there's no point in complicating
> > our lives - just wait for the delayed work to be finished instead.
> >
> > Signed-off-by: Jan Kara <jack@suse.cz>
> 
> Isn't it *required* to wait for all marks to really be freed and not only
> nice behavior following the same reason for
> 35e4817 fsnotify: avoid spurious EMFILE errors from inotify_init()
> 
> Otherwise
> 
> Reviewed-by: Amir Goldstein <amir73il@gmail.com>

Well, it is not nice to leave marks dangling after the group destruction
exactly for the reason you reference above. But OTOH it is mostly an
annoyance and not a serious issue unless it happens a lot (which it did not
in this case).

								Honza
diff mbox

Patch

diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h
index bdc489af0e5b..670c2bac1342 100644
--- a/fs/notify/fsnotify.h
+++ b/fs/notify/fsnotify.h
@@ -36,10 +36,8 @@  static inline void fsnotify_clear_marks_by_mount(struct vfsmount *mnt)
 }
 /* prepare for freeing all marks associated with given group */
 extern void fsnotify_detach_group_marks(struct fsnotify_group *group);
-/*
- * wait for fsnotify_mark_srcu period to end and free all marks in destroy_list
- */
-extern void fsnotify_mark_destroy_list(void);
+/* Wait until all marks queued for destruction are destroyed */
+extern void fsnotify_wait_marks_destroyed(void);
 
 /*
  * update the dentry->d_flags of all of inode's children to indicate if inode cares
diff --git a/fs/notify/group.c b/fs/notify/group.c
index fbe3cbebec16..0fb4aadcc19f 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -66,14 +66,16 @@  void fsnotify_destroy_group(struct fsnotify_group *group)
 	 */
 	fsnotify_group_stop_queueing(group);
 
-	/* clear all inode marks for this group, attach them to destroy_list */
+	/* Clear all marks for this group and queue them for destruction */
 	fsnotify_detach_group_marks(group);
 
 	/*
-	 * Wait for fsnotify_mark_srcu period to end and free all marks in
-	 * destroy_list
+	 * Wait until all marks get really destroyed. We could actually destroy
+	 * them ourselves instead of waiting for worker to do it, however that
+	 * would be racy as worker can already be processing some marks before
+	 * we even entered fsnotify_destroy_group().
 	 */
-	fsnotify_mark_destroy_list();
+	fsnotify_wait_marks_destroyed();
 
 	/*
 	 * Since we have waited for fsnotify_mark_srcu in
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 55550dad6617..60f5754ce5ed 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -650,7 +650,7 @@  void fsnotify_detach_group_marks(struct fsnotify_group *group)
 		fsnotify_get_mark(mark);
 		fsnotify_detach_mark(mark);
 		mutex_unlock(&group->mark_mutex);
-		__fsnotify_free_mark(mark);
+		fsnotify_free_mark(mark);
 		fsnotify_put_mark(mark);
 	}
 }
@@ -710,7 +710,7 @@  void fsnotify_init_mark(struct fsnotify_mark *mark,
  * Destroy all marks in destroy_list, waits for SRCU period to finish before
  * actually freeing marks.
  */
-void fsnotify_mark_destroy_list(void)
+static void fsnotify_mark_destroy_workfn(struct work_struct *work)
 {
 	struct fsnotify_mark *mark, *next;
 	struct list_head private_destroy_list;
@@ -728,7 +728,8 @@  void fsnotify_mark_destroy_list(void)
 	}
 }
 
-static void fsnotify_mark_destroy_workfn(struct work_struct *work)
+/* Wait for all marks queued for destruction to be actually destroyed */
+void fsnotify_wait_marks_destroyed(void)
 {
-	fsnotify_mark_destroy_list();
+	flush_delayed_work(&reaper_work);
 }