From a86bb6729ca889037c7d91505a9a48b432b3eb7a Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Fri, 12 Aug 2011 01:13:31 +0200 Subject: [PATCH] --- yaml --- r: 347903 b: refs/heads/master c: 6960b0d909cde5bdff49e4e5c1250edd10be7ebd h: refs/heads/master i: 347901: d79e0f4f66a217370d9a722b01f4ddeb4c89920c 347899: 72636de59f807ce924c9de5730b7ffbb83c300cb 347895: f3783af37775d2c3dda0e0fa12094b8d7353ed99 347887: 7e1a77266f080e719b60a5071773340b7784a3c1 347871: fd68a1191ac3553dfe9f55b26c4427474a2d27f9 347839: 829ff6e9dd801c902bcf1abb00d18fa53003ff49 347775: 1992ce13aed0851923a6ebbd47612c6ae11a5cbc 347647: 599f33f8154fdadcbcf3c3110b267ed5f78a014a v: v3 --- [refs] | 2 +- trunk/fs/notify/mark.c | 20 ++++++++++---------- trunk/include/linux/fsnotify_backend.h | 7 ++++--- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/[refs] b/[refs] index a103379d971b..2adcd019c111 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 64c20d2a20fce295c260ea6cb3b468edfa2fb07b +refs/heads/master: 6960b0d909cde5bdff49e4e5c1250edd10be7ebd diff --git a/trunk/fs/notify/mark.c b/trunk/fs/notify/mark.c index 0e93d90bb753..fc6b49bf7360 100644 --- a/trunk/fs/notify/mark.c +++ b/trunk/fs/notify/mark.c @@ -150,6 +150,8 @@ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark, spin_unlock(&mark->lock); + if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED)) + iput(inode); /* release lock temporarily */ mutex_unlock(&group->mark_mutex); @@ -157,6 +159,11 @@ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark, list_add(&mark->destroy_list, &destroy_list); spin_unlock(&destroy_lock); wake_up(&destroy_waitq); + /* + * We don't necessarily have a ref on mark from caller so the above destroy + * may have actually freed it, unless this group provides a 'freeing_mark' + * function which must be holding a reference. + */ /* * Some groups like to know that marks are being freed. This is a @@ -178,22 +185,15 @@ void fsnotify_destroy_mark_locked(struct fsnotify_mark *mark, * is just a lazy update (and could be a perf win...) */ - if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED)) - iput(inode); - /* - * We don't necessarily have a ref on mark from caller so the above iput - * may have already destroyed it. Don't touch from now on. - */ - atomic_dec(&group->num_marks); - mutex_lock(&group->mark_mutex); + mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); } void fsnotify_destroy_mark(struct fsnotify_mark *mark, struct fsnotify_group *group) { - mutex_lock(&group->mark_mutex); + mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); fsnotify_destroy_mark_locked(mark, group); mutex_unlock(&group->mark_mutex); } @@ -300,7 +300,7 @@ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, { struct fsnotify_mark *lmark, *mark; - mutex_lock(&group->mark_mutex); + mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { if (mark->flags & flags) { fsnotify_get_mark(mark); diff --git a/trunk/include/linux/fsnotify_backend.h b/trunk/include/linux/fsnotify_backend.h index 5a8899350456..1af2f6a722c0 100644 --- a/trunk/include/linux/fsnotify_backend.h +++ b/trunk/include/linux/fsnotify_backend.h @@ -88,9 +88,10 @@ struct fsnotify_event_private_data; * if the group is interested in this event. * handle_event - main call for a group to handle an fs event * free_group_priv - called when a group refcnt hits 0 to clean up the private union - * freeing-mark - this means that a mark has been flagged to die when everything - * finishes using it. The function is supplied with what must be a - * valid group and inode to use to clean up. + * freeing_mark - called when a mark is being destroyed for some reason. The group + * MUST be holding a reference on each mark and that reference must be + * dropped in this function. inotify uses this function to send + * userspace messages that marks have been removed. */ struct fsnotify_ops { bool (*should_send_event)(struct fsnotify_group *group, struct inode *inode,