Lines Matching full:mark

7  * fsnotify inode mark locking/lifetime/and refcnting
10 * The group->recnt and mark->refcnt tell how many "things" in the kernel
13 * the reference a group and a mark hold to each other.
22 * mark->lock
23 * mark->connector->lock
26 * each mark is hooked via the g_list. It also protects the groups private
29 * mark->lock protects the marks attributes like its masks and flags.
30 * Furthermore it protects the access to a reference of the group that the mark
32 * that is being watched by the mark.
34 * mark->connector->lock protects the list of marks anchored inside an
35 * inode / vfsmount and each mark is hooked via the i_list.
39 * marks in the list and is also protected by fsnotify_mark_srcu. A mark gets
40 * detached from fsnotify_mark_connector when last reference to the mark is
41 * dropped. Thus having mark reference is enough to protect mark->connector
43 * because we remove mark from g_list before dropping mark reference associated
44 * with that, any mark found through g_list is guaranteed to have
45 * mark->connector set until we drop group->mark_mutex.
51 * The inode mark can be cleared for a number of different reasons including:
56 * - The fsnotify_group associated with the mark is going away and all such marks
94 void fsnotify_get_mark(struct fsnotify_mark *mark) in fsnotify_get_mark() argument
96 WARN_ON_ONCE(!refcount_read(&mark->refcnt)); in fsnotify_get_mark()
97 refcount_inc(&mark->refcnt); in fsnotify_get_mark()
210 * iput() outside of spinlocks. This happens when last mark that wanted iref is
224 /* Pin inode if any mark wants inode refcount held */ in fsnotify_update_iref()
228 /* Unpin inode after detach of last mark that wanted iref */ in fsnotify_update_iref()
240 struct fsnotify_mark *mark; in __fsnotify_recalc_mask() local
246 hlist_for_each_entry(mark, &conn->list, obj_list) { in __fsnotify_recalc_mask()
247 if (!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) in __fsnotify_recalc_mask()
249 new_mask |= fsnotify_calc_mask(mark); in __fsnotify_recalc_mask()
251 !(mark->flags & FSNOTIFY_MARK_FLAG_NO_IREF)) in __fsnotify_recalc_mask()
284 * this by holding a mark->lock or mark->group->mark_mutex for a mark on this
359 static void fsnotify_final_mark_destroy(struct fsnotify_mark *mark) in fsnotify_final_mark_destroy() argument
361 struct fsnotify_group *group = mark->group; in fsnotify_final_mark_destroy()
365 group->ops->free_mark(mark); in fsnotify_final_mark_destroy()
380 void fsnotify_put_mark(struct fsnotify_mark *mark) in fsnotify_put_mark() argument
382 struct fsnotify_mark_connector *conn = READ_ONCE(mark->connector); in fsnotify_put_mark()
389 if (refcount_dec_and_test(&mark->refcnt)) in fsnotify_put_mark()
390 fsnotify_final_mark_destroy(mark); in fsnotify_put_mark()
396 * safely grab mark reference. in fsnotify_put_mark()
398 if (!refcount_dec_and_lock(&mark->refcnt, &conn->lock)) in fsnotify_put_mark()
401 hlist_del_init_rcu(&mark->obj_list); in fsnotify_put_mark()
408 /* Update watched objects after detaching mark */ in fsnotify_put_mark()
414 WRITE_ONCE(mark->connector, NULL); in fsnotify_put_mark()
433 list_add(&mark->g_list, &destroy_list); in fsnotify_put_mark()
441 * Get mark reference when we found the mark via lockless traversal of object
442 * list. Mark can be already removed from the list by now and on its way to be
447 static bool fsnotify_get_mark_safe(struct fsnotify_mark *mark) in fsnotify_get_mark_safe() argument
449 if (!mark) in fsnotify_get_mark_safe()
452 if (refcount_inc_not_zero(&mark->refcnt)) { in fsnotify_get_mark_safe()
453 spin_lock(&mark->lock); in fsnotify_get_mark_safe()
454 if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) { in fsnotify_get_mark_safe()
455 /* mark is attached, group is still alive then */ in fsnotify_get_mark_safe()
456 atomic_inc(&mark->group->user_waits); in fsnotify_get_mark_safe()
457 spin_unlock(&mark->lock); in fsnotify_get_mark_safe()
460 spin_unlock(&mark->lock); in fsnotify_get_mark_safe()
461 fsnotify_put_mark(mark); in fsnotify_get_mark_safe()
471 static void fsnotify_put_mark_wake(struct fsnotify_mark *mark) in fsnotify_put_mark_wake() argument
473 if (mark) { in fsnotify_put_mark_wake()
474 struct fsnotify_group *group = mark->group; in fsnotify_put_mark_wake()
476 fsnotify_put_mark(mark); in fsnotify_put_mark_wake()
492 /* This can fail if mark is being removed */ in fsnotify_prepare_user_wait()
525 * Mark mark as detached, remove it from group list. Mark still stays in object
526 * list until its last reference is dropped. Note that we rely on mark being
528 * particular we rely on mark->connector being valid while we hold
529 * group->mark_mutex if we found the mark through g_list.
532 * reference to the mark or be protected by fsnotify_mark_srcu.
534 void fsnotify_detach_mark(struct fsnotify_mark *mark) in fsnotify_detach_mark() argument
536 fsnotify_group_assert_locked(mark->group); in fsnotify_detach_mark()
538 refcount_read(&mark->refcnt) < 1 + in fsnotify_detach_mark()
539 !!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)); in fsnotify_detach_mark()
541 spin_lock(&mark->lock); in fsnotify_detach_mark()
542 /* something else already called this function on this mark */ in fsnotify_detach_mark()
543 if (!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { in fsnotify_detach_mark()
544 spin_unlock(&mark->lock); in fsnotify_detach_mark()
547 mark->flags &= ~FSNOTIFY_MARK_FLAG_ATTACHED; in fsnotify_detach_mark()
548 list_del_init(&mark->g_list); in fsnotify_detach_mark()
549 spin_unlock(&mark->lock); in fsnotify_detach_mark()
551 /* Drop mark reference acquired in fsnotify_add_mark_locked() */ in fsnotify_detach_mark()
552 fsnotify_put_mark(mark); in fsnotify_detach_mark()
556 * Free fsnotify mark. The mark is actually only marked as being freed. The
557 * freeing is actually happening only once last reference to the mark is
560 * Caller must have a reference to the mark or be protected by
563 void fsnotify_free_mark(struct fsnotify_mark *mark) in fsnotify_free_mark() argument
565 struct fsnotify_group *group = mark->group; in fsnotify_free_mark()
567 spin_lock(&mark->lock); in fsnotify_free_mark()
568 /* something else already called this function on this mark */ in fsnotify_free_mark()
569 if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) { in fsnotify_free_mark()
570 spin_unlock(&mark->lock); in fsnotify_free_mark()
573 mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; in fsnotify_free_mark()
574 spin_unlock(&mark->lock); in fsnotify_free_mark()
578 * callback to the group function to let it know that this mark in fsnotify_free_mark()
582 group->ops->freeing_mark(mark, group); in fsnotify_free_mark()
585 void fsnotify_destroy_mark(struct fsnotify_mark *mark, in fsnotify_destroy_mark() argument
589 fsnotify_detach_mark(mark); in fsnotify_destroy_mark()
591 fsnotify_free_mark(mark); in fsnotify_destroy_mark()
678 * Get mark connector, make sure it is alive and return with its lock held.
680 * hold reference to a mark on the list may directly lock connector->lock as
705 * Add mark into proper place in given list of marks. These marks may be used
710 static int fsnotify_add_mark_list(struct fsnotify_mark *mark, void *obj, in fsnotify_add_mark_list() argument
735 spin_lock(&mark->lock); in fsnotify_add_mark_list()
738 spin_unlock(&mark->lock); in fsnotify_add_mark_list()
745 /* is mark the first mark? */ in fsnotify_add_mark_list()
747 hlist_add_head_rcu(&mark->obj_list, &conn->list); in fsnotify_add_mark_list()
751 /* should mark be in the middle of the current list? */ in fsnotify_add_mark_list()
755 if ((lmark->group == mark->group) && in fsnotify_add_mark_list()
757 !(mark->group->flags & FSNOTIFY_GROUP_DUPS)) { in fsnotify_add_mark_list()
762 cmp = fsnotify_compare_groups(lmark->group, mark->group); in fsnotify_add_mark_list()
764 hlist_add_before_rcu(&mark->obj_list, &lmark->obj_list); in fsnotify_add_mark_list()
770 /* mark should be the last entry. last is the current last entry */ in fsnotify_add_mark_list()
771 hlist_add_behind_rcu(&mark->obj_list, &last->obj_list); in fsnotify_add_mark_list()
777 * seeing mark->connector set. in fsnotify_add_mark_list()
779 WRITE_ONCE(mark->connector, conn); in fsnotify_add_mark_list()
782 spin_unlock(&mark->lock); in fsnotify_add_mark_list()
787 * Attach an initialized mark to a given group and fs object.
791 int fsnotify_add_mark_locked(struct fsnotify_mark *mark, in fsnotify_add_mark_locked() argument
795 struct fsnotify_group *group = mark->group; in fsnotify_add_mark_locked()
803 * mark->lock in fsnotify_add_mark_locked()
804 * mark->connector->lock in fsnotify_add_mark_locked()
806 spin_lock(&mark->lock); in fsnotify_add_mark_locked()
807 mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE | FSNOTIFY_MARK_FLAG_ATTACHED; in fsnotify_add_mark_locked()
809 list_add(&mark->g_list, &group->marks_list); in fsnotify_add_mark_locked()
810 fsnotify_get_mark(mark); /* for g_list */ in fsnotify_add_mark_locked()
811 spin_unlock(&mark->lock); in fsnotify_add_mark_locked()
813 ret = fsnotify_add_mark_list(mark, obj, obj_type, add_flags); in fsnotify_add_mark_locked()
817 fsnotify_recalc_mask(mark->connector); in fsnotify_add_mark_locked()
821 spin_lock(&mark->lock); in fsnotify_add_mark_locked()
822 mark->flags &= ~(FSNOTIFY_MARK_FLAG_ALIVE | in fsnotify_add_mark_locked()
824 list_del_init(&mark->g_list); in fsnotify_add_mark_locked()
825 spin_unlock(&mark->lock); in fsnotify_add_mark_locked()
827 fsnotify_put_mark(mark); in fsnotify_add_mark_locked()
831 int fsnotify_add_mark(struct fsnotify_mark *mark, void *obj, in fsnotify_add_mark() argument
835 struct fsnotify_group *group = mark->group; in fsnotify_add_mark()
838 ret = fsnotify_add_mark_locked(mark, obj, obj_type, add_flags); in fsnotify_add_mark()
845 * Given a list of marks, find the mark associated with given group. If found
846 * take a reference to that mark and return it, else return NULL.
853 struct fsnotify_mark *mark; in fsnotify_find_mark() local
862 hlist_for_each_entry(mark, &conn->list, obj_list) { in fsnotify_find_mark()
863 if (mark->group == group && in fsnotify_find_mark()
864 (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { in fsnotify_find_mark()
865 fsnotify_get_mark(mark); in fsnotify_find_mark()
867 return mark; in fsnotify_find_mark()
879 struct fsnotify_mark *lmark, *mark; in fsnotify_clear_marks_by_group() local
892 * list. And freeing mark requires us to drop mark_mutex. So we can in fsnotify_clear_marks_by_group()
893 * reliably free only the first mark in the list. That's why we first in fsnotify_clear_marks_by_group()
898 list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { in fsnotify_clear_marks_by_group()
899 if (mark->connector->type == obj_type) in fsnotify_clear_marks_by_group()
900 list_move(&mark->g_list, &to_free); in fsnotify_clear_marks_by_group()
911 mark = list_first_entry(head, struct fsnotify_mark, g_list); in fsnotify_clear_marks_by_group()
912 fsnotify_get_mark(mark); in fsnotify_clear_marks_by_group()
913 fsnotify_detach_mark(mark); in fsnotify_clear_marks_by_group()
915 fsnotify_free_mark(mark); in fsnotify_clear_marks_by_group()
916 fsnotify_put_mark(mark); in fsnotify_clear_marks_by_group()
924 struct fsnotify_mark *mark, *old_mark = NULL; in fsnotify_destroy_marks() local
934 * list can get modified. However we are holding mark reference and in fsnotify_destroy_marks()
935 * thus our mark cannot be removed from obj_list so we can continue in fsnotify_destroy_marks()
938 hlist_for_each_entry(mark, &conn->list, obj_list) { in fsnotify_destroy_marks()
939 fsnotify_get_mark(mark); in fsnotify_destroy_marks()
943 old_mark = mark; in fsnotify_destroy_marks()
944 fsnotify_destroy_mark(mark, mark->group); in fsnotify_destroy_marks()
949 * mark references get dropped. It would lead to strange results such in fsnotify_destroy_marks()
962 void fsnotify_init_mark(struct fsnotify_mark *mark, in fsnotify_init_mark() argument
965 memset(mark, 0, sizeof(*mark)); in fsnotify_init_mark()
966 spin_lock_init(&mark->lock); in fsnotify_init_mark()
967 refcount_set(&mark->refcnt, 1); in fsnotify_init_mark()
969 mark->group = group; in fsnotify_init_mark()
970 WRITE_ONCE(mark->connector, NULL); in fsnotify_init_mark()
980 struct fsnotify_mark *mark, *next; in fsnotify_mark_destroy_workfn() local
990 list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) { in fsnotify_mark_destroy_workfn()
991 list_del_init(&mark->g_list); in fsnotify_mark_destroy_workfn()
992 fsnotify_final_mark_destroy(mark); in fsnotify_mark_destroy_workfn()