VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
c82ee6d3beaa4 (Thomas Gleixner 2019-05-19 15:51:48 +0200   1) // SPDX-License-Identifier: GPL-2.0-or-later
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500   2) /*
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500   3)  *  Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500   4)  */
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500   5) 
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500   6) /*
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500   7)  * fsnotify inode mark locking/lifetime/and refcnting
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500   8)  *
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500   9)  * REFCNT:
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  10)  * The group->recnt and mark->refcnt tell how many "things" in the kernel
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  11)  * currently are referencing the objects. Both kind of objects typically will
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  12)  * live inside the kernel with a refcnt of 2, one for its creation and one for
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  13)  * the reference a group and a mark hold to each other.
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  14)  * If you are holding the appropriate locks, you can take a reference and the
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  15)  * object itself is guaranteed to survive until the reference is dropped.
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  16)  *
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  17)  * LOCKING:
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  18)  * There are 3 locks involved with fsnotify inode marks and they MUST be taken
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  19)  * in order as follows:
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  20)  *
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  21)  * group->mark_mutex
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  22)  * mark->lock
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100  23)  * mark->connector->lock
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  24)  *
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  25)  * group->mark_mutex protects the marks_list anchored inside a given group and
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  26)  * each mark is hooked via the g_list.  It also protects the groups private
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  27)  * data (i.e group limits).
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  28) 
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  29)  * mark->lock protects the marks attributes like its masks and flags.
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  30)  * Furthermore it protects the access to a reference of the group that the mark
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  31)  * is assigned to as well as the access to a reference of the inode/vfsmount
9756b9187eebb (Lino Sanfilippo 2013-07-08 15:59:46 -0700  32)  * that is being watched by the mark.
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  33)  *
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100  34)  * mark->connector->lock protects the list of marks anchored inside an
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100  35)  * inode / vfsmount and each mark is hooked via the i_list.
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  36)  *
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100  37)  * A list of notification marks relating to inode / mnt is contained in
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100  38)  * fsnotify_mark_connector. That structure is alive as long as there are any
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100  39)  * marks in the list and is also protected by fsnotify_mark_srcu. A mark gets
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100  40)  * detached from fsnotify_mark_connector when last reference to the mark is
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100  41)  * dropped.  Thus having mark reference is enough to protect mark->connector
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100  42)  * pointer and to make sure fsnotify_mark_connector cannot disappear. Also
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100  43)  * because we remove mark from g_list before dropping mark reference associated
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100  44)  * with that, any mark found through g_list is guaranteed to have
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100  45)  * mark->connector set until we drop group->mark_mutex.
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  46)  *
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  47)  * LIFETIME:
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  48)  * Inode marks survive between when they are added to an inode and when their
c1f33073ac1b3 (Jan Kara        2016-12-16 10:53:32 +0100  49)  * refcnt==0. Marks are also protected by fsnotify_mark_srcu.
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  50)  *
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  51)  * The inode mark can be cleared for a number of different reasons including:
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  52)  * - The inode is unlinked for the last time.  (fsnotify_inode_remove)
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  53)  * - The inode is being evicted from cache. (fsnotify_inode_delete)
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  54)  * - The fs the inode is on is unmounted.  (fsnotify_inode_delete/fsnotify_unmount_inodes)
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  55)  * - Something explicitly requests that it be removed.  (fsnotify_destroy_mark)
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  56)  * - The fsnotify_group associated with the mark is going away and all such marks
2e37c6ca8d76c (Jan Kara        2017-01-04 10:51:58 +0100  57)  *   need to be cleaned up. (fsnotify_clear_marks_by_group)
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  58)  *
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  59)  * This has the very interesting property of being able to run concurrently with
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  60)  * any (or all) other directions.
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  61)  */
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  62) 
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  63) #include <linux/fs.h>
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  64) #include <linux/init.h>
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  65) #include <linux/kernel.h>
75c1be487a690 (Eric Paris      2010-07-28 10:18:38 -0400  66) #include <linux/kthread.h>
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  67) #include <linux/module.h>
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  68) #include <linux/mutex.h>
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  69) #include <linux/slab.h>
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  70) #include <linux/spinlock.h>
75c1be487a690 (Eric Paris      2010-07-28 10:18:38 -0400  71) #include <linux/srcu.h>
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200  72) #include <linux/ratelimit.h>
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  73) 
60063497a95e7 (Arun Sharma     2011-07-26 16:09:06 -0700  74) #include <linux/atomic.h>
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  75) 
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  76) #include <linux/fsnotify_backend.h>
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  77) #include "fsnotify.h"
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  78) 
0918f1c309b86 (Jeff Layton     2016-02-17 13:11:21 -0800  79) #define FSNOTIFY_REAPER_DELAY	(1)	/* 1 jiffy */
0918f1c309b86 (Jeff Layton     2016-02-17 13:11:21 -0800  80) 
75c1be487a690 (Eric Paris      2010-07-28 10:18:38 -0400  81) struct srcu_struct fsnotify_mark_srcu;
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100  82) struct kmem_cache *fsnotify_mark_connector_cachep;
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100  83) 
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800  84) static DEFINE_SPINLOCK(destroy_lock);
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800  85) static LIST_HEAD(destroy_list);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100  86) static struct fsnotify_mark_connector *connector_destroy_list;
0918f1c309b86 (Jeff Layton     2016-02-17 13:11:21 -0800  87) 
35e481761cdc6 (Jan Kara        2016-05-19 17:08:59 -0700  88) static void fsnotify_mark_destroy_workfn(struct work_struct *work);
35e481761cdc6 (Jan Kara        2016-05-19 17:08:59 -0700  89) static DECLARE_DELAYED_WORK(reaper_work, fsnotify_mark_destroy_workfn);
75c1be487a690 (Eric Paris      2010-07-28 10:18:38 -0400  90) 
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100  91) static void fsnotify_connector_destroy_workfn(struct work_struct *work);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100  92) static DECLARE_WORK(connector_reaper_work, fsnotify_connector_destroy_workfn);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100  93) 
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  94) void fsnotify_get_mark(struct fsnotify_mark *mark)
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  95) {
ab97f87325e28 (Elena Reshetova 2017-10-20 13:26:02 +0300  96) 	WARN_ON_ONCE(!refcount_read(&mark->refcnt));
ab97f87325e28 (Elena Reshetova 2017-10-20 13:26:02 +0300  97) 	refcount_inc(&mark->refcnt);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  98) }
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500  99) 
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 100) static __u32 *fsnotify_conn_mask_p(struct fsnotify_mark_connector *conn)
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 101) {
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 102) 	if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 103) 		return &fsnotify_conn_inode(conn)->i_fsnotify_mask;
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 104) 	else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT)
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 105) 		return &fsnotify_conn_mount(conn)->mnt_fsnotify_mask;
1e6cb72399fd5 (Amir Goldstein  2018-09-01 10:41:11 +0300 106) 	else if (conn->type == FSNOTIFY_OBJ_TYPE_SB)
1e6cb72399fd5 (Amir Goldstein  2018-09-01 10:41:11 +0300 107) 		return &fsnotify_conn_sb(conn)->s_fsnotify_mask;
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 108) 	return NULL;
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 109) }
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 110) 
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 111) __u32 fsnotify_conn_mask(struct fsnotify_mark_connector *conn)
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 112) {
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 113) 	if (WARN_ON(!fsnotify_valid_obj_type(conn->type)))
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 114) 		return 0;
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 115) 
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 116) 	return *fsnotify_conn_mask_p(conn);
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 117) }
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 118) 
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 119) static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 120) {
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 121) 	u32 new_mask = 0;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 122) 	struct fsnotify_mark *mark;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 123) 
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 124) 	assert_spin_locked(&conn->lock);
d3bc0fa8411c3 (Jan Kara        2018-08-20 13:55:45 +0200 125) 	/* We can get detached connector here when inode is getting unlinked. */
d3bc0fa8411c3 (Jan Kara        2018-08-20 13:55:45 +0200 126) 	if (!fsnotify_valid_obj_type(conn->type))
d3bc0fa8411c3 (Jan Kara        2018-08-20 13:55:45 +0200 127) 		return;
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 128) 	hlist_for_each_entry(mark, &conn->list, obj_list) {
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 129) 		if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 130) 			new_mask |= mark->mask;
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 131) 	}
3ac70bfcde812 (Amir Goldstein  2018-06-23 17:54:50 +0300 132) 	*fsnotify_conn_mask_p(conn) = new_mask;
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 133) }
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 134) 
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 135) /*
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 136)  * Calculate mask of events for a list of marks. The caller must make sure
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 137)  * connector and connector->obj cannot disappear under us.  Callers achieve
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 138)  * this by holding a mark->lock or mark->group->mark_mutex for a mark on this
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 139)  * list.
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 140)  */
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 141) void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 142) {
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 143) 	if (!conn)
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 144) 		return;
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 145) 
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 146) 	spin_lock(&conn->lock);
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 147) 	__fsnotify_recalc_mask(conn);
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 148) 	spin_unlock(&conn->lock);
d6f7b98bc8147 (Amir Goldstein  2018-04-20 16:10:49 -0700 149) 	if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 150) 		__fsnotify_update_child_dentry_flags(
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 151) 					fsnotify_conn_inode(conn));
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 152) }
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 153) 
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 154) /* Free all connectors queued for freeing once SRCU period ends */
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 155) static void fsnotify_connector_destroy_workfn(struct work_struct *work)
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 156) {
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 157) 	struct fsnotify_mark_connector *conn, *free;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 158) 
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 159) 	spin_lock(&destroy_lock);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 160) 	conn = connector_destroy_list;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 161) 	connector_destroy_list = NULL;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 162) 	spin_unlock(&destroy_lock);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 163) 
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 164) 	synchronize_srcu(&fsnotify_mark_srcu);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 165) 	while (conn) {
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 166) 		free = conn;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 167) 		conn = conn->destroy_next;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 168) 		kmem_cache_free(fsnotify_mark_connector_cachep, free);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 169) 	}
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 170) }
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 171) 
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 172) static void *fsnotify_detach_connector_from_object(
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 173) 					struct fsnotify_mark_connector *conn,
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 174) 					unsigned int *type)
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 175) {
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 176) 	struct inode *inode = NULL;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 177) 
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 178) 	*type = conn->type;
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 179) 	if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED)
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 180) 		return NULL;
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 181) 
d6f7b98bc8147 (Amir Goldstein  2018-04-20 16:10:49 -0700 182) 	if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) {
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 183) 		inode = fsnotify_conn_inode(conn);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 184) 		inode->i_fsnotify_mask = 0;
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 185) 		atomic_long_inc(&inode->i_sb->s_fsnotify_inode_refs);
d6f7b98bc8147 (Amir Goldstein  2018-04-20 16:10:49 -0700 186) 	} else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 187) 		fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0;
1e6cb72399fd5 (Amir Goldstein  2018-09-01 10:41:11 +0300 188) 	} else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) {
1e6cb72399fd5 (Amir Goldstein  2018-09-01 10:41:11 +0300 189) 		fsnotify_conn_sb(conn)->s_fsnotify_mask = 0;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 190) 	}
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 191) 
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 192) 	rcu_assign_pointer(*(conn->obj), NULL);
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 193) 	conn->obj = NULL;
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 194) 	conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 195) 
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 196) 	return inode;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 197) }
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 198) 
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 199) static void fsnotify_final_mark_destroy(struct fsnotify_mark *mark)
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 200) {
054c636e5c805 (Jan Kara        2016-12-21 18:06:12 +0100 201) 	struct fsnotify_group *group = mark->group;
054c636e5c805 (Jan Kara        2016-12-21 18:06:12 +0100 202) 
054c636e5c805 (Jan Kara        2016-12-21 18:06:12 +0100 203) 	if (WARN_ON_ONCE(!group))
054c636e5c805 (Jan Kara        2016-12-21 18:06:12 +0100 204) 		return;
054c636e5c805 (Jan Kara        2016-12-21 18:06:12 +0100 205) 	group->ops->free_mark(mark);
054c636e5c805 (Jan Kara        2016-12-21 18:06:12 +0100 206) 	fsnotify_put_group(group);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 207) }
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 208) 
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 209) /* Drop object reference originally held by a connector */
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 210) static void fsnotify_drop_object(unsigned int type, void *objp)
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 211) {
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 212) 	struct inode *inode;
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 213) 	struct super_block *sb;
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 214) 
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 215) 	if (!objp)
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 216) 		return;
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 217) 	/* Currently only inode references are passed to be dropped */
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 218) 	if (WARN_ON_ONCE(type != FSNOTIFY_OBJ_TYPE_INODE))
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 219) 		return;
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 220) 	inode = objp;
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 221) 	sb = inode->i_sb;
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 222) 	iput(inode);
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 223) 	if (atomic_long_dec_and_test(&sb->s_fsnotify_inode_refs))
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 224) 		wake_up_var(&sb->s_fsnotify_inode_refs);
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 225) }
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 226) 
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 227) void fsnotify_put_mark(struct fsnotify_mark *mark)
8212a6097a720 (Jan Kara        2017-03-15 09:48:11 +0100 228) {
b1da6a51871c6 (Jan Kara        2019-04-24 18:39:57 +0200 229) 	struct fsnotify_mark_connector *conn = READ_ONCE(mark->connector);
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 230) 	void *objp = NULL;
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 231) 	unsigned int type = FSNOTIFY_OBJ_TYPE_DETACHED;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 232) 	bool free_conn = false;
8212a6097a720 (Jan Kara        2017-03-15 09:48:11 +0100 233) 
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 234) 	/* Catch marks that were actually never attached to object */
b1da6a51871c6 (Jan Kara        2019-04-24 18:39:57 +0200 235) 	if (!conn) {
ab97f87325e28 (Elena Reshetova 2017-10-20 13:26:02 +0300 236) 		if (refcount_dec_and_test(&mark->refcnt))
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 237) 			fsnotify_final_mark_destroy(mark);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 238) 		return;
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 239) 	}
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 240) 
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 241) 	/*
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 242) 	 * We have to be careful so that traversals of obj_list under lock can
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 243) 	 * safely grab mark reference.
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 244) 	 */
b1da6a51871c6 (Jan Kara        2019-04-24 18:39:57 +0200 245) 	if (!refcount_dec_and_lock(&mark->refcnt, &conn->lock))
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 246) 		return;
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 247) 
8212a6097a720 (Jan Kara        2017-03-15 09:48:11 +0100 248) 	hlist_del_init_rcu(&mark->obj_list);
8212a6097a720 (Jan Kara        2017-03-15 09:48:11 +0100 249) 	if (hlist_empty(&conn->list)) {
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 250) 		objp = fsnotify_detach_connector_from_object(conn, &type);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 251) 		free_conn = true;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 252) 	} else {
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 253) 		__fsnotify_recalc_mask(conn);
8212a6097a720 (Jan Kara        2017-03-15 09:48:11 +0100 254) 	}
b1da6a51871c6 (Jan Kara        2019-04-24 18:39:57 +0200 255) 	WRITE_ONCE(mark->connector, NULL);
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 256) 	spin_unlock(&conn->lock);
8212a6097a720 (Jan Kara        2017-03-15 09:48:11 +0100 257) 
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 258) 	fsnotify_drop_object(type, objp);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 259) 
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 260) 	if (free_conn) {
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 261) 		spin_lock(&destroy_lock);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 262) 		conn->destroy_next = connector_destroy_list;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 263) 		connector_destroy_list = conn;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 264) 		spin_unlock(&destroy_lock);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 265) 		queue_work(system_unbound_wq, &connector_reaper_work);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 266) 	}
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 267) 	/*
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 268) 	 * Note that we didn't update flags telling whether inode cares about
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 269) 	 * what's happening with children. We update these flags from
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 270) 	 * __fsnotify_parent() lazily when next event happens on one of our
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 271) 	 * children.
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 272) 	 */
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 273) 	spin_lock(&destroy_lock);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 274) 	list_add(&mark->g_list, &destroy_list);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 275) 	spin_unlock(&destroy_lock);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 276) 	queue_delayed_work(system_unbound_wq, &reaper_work,
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 277) 			   FSNOTIFY_REAPER_DELAY);
8212a6097a720 (Jan Kara        2017-03-15 09:48:11 +0100 278) }
b72679ee89a0a (Trond Myklebust 2019-08-18 14:18:46 -0400 279) EXPORT_SYMBOL_GPL(fsnotify_put_mark);
8212a6097a720 (Jan Kara        2017-03-15 09:48:11 +0100 280) 
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 281) /*
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 282)  * Get mark reference when we found the mark via lockless traversal of object
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 283)  * list. Mark can be already removed from the list by now and on its way to be
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 284)  * destroyed once SRCU period ends.
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 285)  *
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 286)  * Also pin the group so it doesn't disappear under us.
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 287)  */
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 288) static bool fsnotify_get_mark_safe(struct fsnotify_mark *mark)
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 289) {
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 290) 	if (!mark)
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 291) 		return true;
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 292) 
ab97f87325e28 (Elena Reshetova 2017-10-20 13:26:02 +0300 293) 	if (refcount_inc_not_zero(&mark->refcnt)) {
9a31d7ad997f5 (Miklos Szeredi  2017-10-30 21:14:56 +0100 294) 		spin_lock(&mark->lock);
9a31d7ad997f5 (Miklos Szeredi  2017-10-30 21:14:56 +0100 295) 		if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) {
9a31d7ad997f5 (Miklos Szeredi  2017-10-30 21:14:56 +0100 296) 			/* mark is attached, group is still alive then */
9a31d7ad997f5 (Miklos Szeredi  2017-10-30 21:14:56 +0100 297) 			atomic_inc(&mark->group->user_waits);
9a31d7ad997f5 (Miklos Szeredi  2017-10-30 21:14:56 +0100 298) 			spin_unlock(&mark->lock);
9a31d7ad997f5 (Miklos Szeredi  2017-10-30 21:14:56 +0100 299) 			return true;
9a31d7ad997f5 (Miklos Szeredi  2017-10-30 21:14:56 +0100 300) 		}
9a31d7ad997f5 (Miklos Szeredi  2017-10-30 21:14:56 +0100 301) 		spin_unlock(&mark->lock);
9a31d7ad997f5 (Miklos Szeredi  2017-10-30 21:14:56 +0100 302) 		fsnotify_put_mark(mark);
9a31d7ad997f5 (Miklos Szeredi  2017-10-30 21:14:56 +0100 303) 	}
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 304) 	return false;
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 305) }
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 306) 
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 307) /*
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 308)  * Puts marks and wakes up group destruction if necessary.
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 309)  *
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 310)  * Pairs with fsnotify_get_mark_safe()
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 311)  */
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 312) static void fsnotify_put_mark_wake(struct fsnotify_mark *mark)
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 313) {
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 314) 	if (mark) {
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 315) 		struct fsnotify_group *group = mark->group;
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 316) 
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 317) 		fsnotify_put_mark(mark);
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 318) 		/*
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 319) 		 * We abuse notification_waitq on group shutdown for waiting for
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 320) 		 * all marks pinned when waiting for userspace.
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 321) 		 */
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 322) 		if (atomic_dec_and_test(&group->user_waits) && group->shutdown)
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 323) 			wake_up(&group->notification_waitq);
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 324) 	}
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 325) }
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 326) 
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 327) bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
00e0afb658bf1 (Jules Irenge    2020-04-13 22:42:40 +0100 328) 	__releases(&fsnotify_mark_srcu)
24c20305c7fc8 (Miklos Szeredi  2017-10-30 21:14:55 +0100 329) {
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 330) 	int type;
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 331) 
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 332) 	fsnotify_foreach_obj_type(type) {
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 333) 		/* This can fail if mark is being removed */
00e0afb658bf1 (Jules Irenge    2020-04-13 22:42:40 +0100 334) 		if (!fsnotify_get_mark_safe(iter_info->marks[type])) {
00e0afb658bf1 (Jules Irenge    2020-04-13 22:42:40 +0100 335) 			__release(&fsnotify_mark_srcu);
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 336) 			goto fail;
00e0afb658bf1 (Jules Irenge    2020-04-13 22:42:40 +0100 337) 		}
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 338) 	}
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 339) 
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 340) 	/*
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 341) 	 * Now that both marks are pinned by refcount in the inode / vfsmount
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 342) 	 * lists, we can drop SRCU lock, and safely resume the list iteration
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 343) 	 * once userspace returns.
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 344) 	 */
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 345) 	srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx);
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 346) 
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 347) 	return true;
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 348) 
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 349) fail:
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 350) 	for (type--; type >= 0; type--)
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 351) 		fsnotify_put_mark_wake(iter_info->marks[type]);
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 352) 	return false;
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 353) }
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 354) 
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 355) void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info)
00e0afb658bf1 (Jules Irenge    2020-04-13 22:42:40 +0100 356) 	__acquires(&fsnotify_mark_srcu)
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 357) {
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 358) 	int type;
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 359) 
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 360) 	iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 361) 	fsnotify_foreach_obj_type(type)
47d9c7cc457ad (Amir Goldstein  2018-04-20 16:10:52 -0700 362) 		fsnotify_put_mark_wake(iter_info->marks[type]);
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 363) }
abc77577a669f (Jan Kara        2016-11-10 16:02:11 +0100 364) 
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 365) /*
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 366)  * Mark mark as detached, remove it from group list. Mark still stays in object
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 367)  * list until its last reference is dropped. Note that we rely on mark being
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 368)  * removed from group list before corresponding reference to it is dropped. In
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 369)  * particular we rely on mark->connector being valid while we hold
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 370)  * group->mark_mutex if we found the mark through g_list.
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 371)  *
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 372)  * Must be called with group->mark_mutex held. The caller must either hold
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 373)  * reference to the mark or be protected by fsnotify_mark_srcu.
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 374)  */
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 375) void fsnotify_detach_mark(struct fsnotify_mark *mark)
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 376) {
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 377) 	struct fsnotify_group *group = mark->group;
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 378) 
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 379) 	WARN_ON_ONCE(!mutex_is_locked(&group->mark_mutex));
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 380) 	WARN_ON_ONCE(!srcu_read_lock_held(&fsnotify_mark_srcu) &&
ab97f87325e28 (Elena Reshetova 2017-10-20 13:26:02 +0300 381) 		     refcount_read(&mark->refcnt) < 1 +
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 382) 			!!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED));
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 383) 
104d06f08ea59 (Lino Sanfilippo 2011-06-14 17:29:48 +0200 384) 	spin_lock(&mark->lock);
700307a29ad61 (Eric Paris      2010-07-28 10:18:38 -0400 385) 	/* something else already called this function on this mark */
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 386) 	if (!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) {
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 387) 		spin_unlock(&mark->lock);
e2a29943e9a2e (Lino Sanfilippo 2011-06-14 17:29:51 +0200 388) 		return;
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 389) 	}
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 390) 	mark->flags &= ~FSNOTIFY_MARK_FLAG_ATTACHED;
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 391) 	list_del_init(&mark->g_list);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 392) 	spin_unlock(&mark->lock);
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 393) 
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 394) 	/* Drop mark reference acquired in fsnotify_add_mark_locked() */
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 395) 	fsnotify_put_mark(mark);
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 396) }
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 397) 
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 398) /*
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 399)  * Free fsnotify mark. The mark is actually only marked as being freed.  The
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 400)  * freeing is actually happening only once last reference to the mark is
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 401)  * dropped from a workqueue which first waits for srcu period end.
35e481761cdc6 (Jan Kara        2016-05-19 17:08:59 -0700 402)  *
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 403)  * Caller must have a reference to the mark or be protected by
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 404)  * fsnotify_mark_srcu.
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 405)  */
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 406) void fsnotify_free_mark(struct fsnotify_mark *mark)
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 407) {
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 408) 	struct fsnotify_group *group = mark->group;
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 409) 
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 410) 	spin_lock(&mark->lock);
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 411) 	/* something else already called this function on this mark */
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 412) 	if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) {
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 413) 		spin_unlock(&mark->lock);
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 414) 		return;
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 415) 	}
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 416) 	mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 417) 	spin_unlock(&mark->lock);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 418) 
d725e66c06ab4 (Linus Torvalds  2015-07-21 16:06:53 -0700 419) 	/*
d725e66c06ab4 (Linus Torvalds  2015-07-21 16:06:53 -0700 420) 	 * Some groups like to know that marks are being freed.  This is a
d725e66c06ab4 (Linus Torvalds  2015-07-21 16:06:53 -0700 421) 	 * callback to the group function to let it know that this mark
d725e66c06ab4 (Linus Torvalds  2015-07-21 16:06:53 -0700 422) 	 * is being freed.
d725e66c06ab4 (Linus Torvalds  2015-07-21 16:06:53 -0700 423) 	 */
d725e66c06ab4 (Linus Torvalds  2015-07-21 16:06:53 -0700 424) 	if (group->ops->freeing_mark)
d725e66c06ab4 (Linus Torvalds  2015-07-21 16:06:53 -0700 425) 		group->ops->freeing_mark(mark, group);
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 426) }
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 427) 
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 428) void fsnotify_destroy_mark(struct fsnotify_mark *mark,
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 429) 			   struct fsnotify_group *group)
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 430) {
6960b0d909cde (Lino Sanfilippo 2011-08-12 01:13:31 +0200 431) 	mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 432) 	fsnotify_detach_mark(mark);
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 433) 	mutex_unlock(&group->mark_mutex);
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 434) 	fsnotify_free_mark(mark);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 435) }
b72679ee89a0a (Trond Myklebust 2019-08-18 14:18:46 -0400 436) EXPORT_SYMBOL_GPL(fsnotify_destroy_mark);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 437) 
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 438) /*
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 439)  * Sorting function for lists of fsnotify marks.
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 440)  *
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 441)  * Fanotify supports different notification classes (reflected as priority of
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 442)  * notification group). Events shall be passed to notification groups in
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 443)  * decreasing priority order. To achieve this marks in notification lists for
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 444)  * inodes and vfsmounts are sorted so that priorities of corresponding groups
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 445)  * are descending.
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 446)  *
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 447)  * Furthermore correct handling of the ignore mask requires processing inode
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 448)  * and vfsmount marks of each group together. Using the group address as
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 449)  * further sort criterion provides a unique sorting order and thus we can
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 450)  * merge inode and vfsmount lists of marks in linear time and find groups
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 451)  * present in both lists.
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 452)  *
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 453)  * A return value of 1 signifies that b has priority over a.
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 454)  * A return value of 0 signifies that the two marks have to be handled together.
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 455)  * A return value of -1 signifies that a has priority over b.
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 456)  */
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 457) int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b)
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 458) {
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 459) 	if (a == b)
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 460) 		return 0;
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 461) 	if (!a)
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 462) 		return 1;
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 463) 	if (!b)
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 464) 		return -1;
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 465) 	if (a->priority < b->priority)
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 466) 		return 1;
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 467) 	if (a->priority > b->priority)
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 468) 		return -1;
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 469) 	if (a < b)
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 470) 		return 1;
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 471) 	return -1;
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 472) }
8edc6e1688fc8 (Jan Kara        2014-11-13 15:19:33 -0800 473) 
9b6e543450dc0 (Amir Goldstein  2018-06-23 17:54:47 +0300 474) static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 475) 					       unsigned int type,
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 476) 					       __kernel_fsid_t *fsid)
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 477) {
b812a9f589637 (Amir Goldstein  2018-06-23 17:54:48 +0300 478) 	struct inode *inode = NULL;
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 479) 	struct fsnotify_mark_connector *conn;
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 480) 
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 481) 	conn = kmem_cache_alloc(fsnotify_mark_connector_cachep, GFP_KERNEL);
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 482) 	if (!conn)
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 483) 		return -ENOMEM;
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 484) 	spin_lock_init(&conn->lock);
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 485) 	INIT_HLIST_HEAD(&conn->list);
b812a9f589637 (Amir Goldstein  2018-06-23 17:54:48 +0300 486) 	conn->type = type;
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 487) 	conn->obj = connp;
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 488) 	/* Cache fsid of filesystem containing the object */
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 489) 	if (fsid) {
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 490) 		conn->fsid = *fsid;
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 491) 		conn->flags = FSNOTIFY_CONN_FLAG_HAS_FSID;
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 492) 	} else {
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 493) 		conn->fsid.val[0] = conn->fsid.val[1] = 0;
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 494) 		conn->flags = 0;
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 495) 	}
b812a9f589637 (Amir Goldstein  2018-06-23 17:54:48 +0300 496) 	if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
36f10f55ff1d2 (Amir Goldstein  2018-06-23 17:54:49 +0300 497) 		inode = igrab(fsnotify_conn_inode(conn));
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 498) 	/*
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 499) 	 * cmpxchg() provides the barrier so that readers of *connp can see
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 500) 	 * only initialized structure
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 501) 	 */
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 502) 	if (cmpxchg(connp, NULL, conn)) {
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 503) 		/* Someone else created list structure for us */
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 504) 		if (inode)
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 505) 			iput(inode);
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 506) 		kmem_cache_free(fsnotify_mark_connector_cachep, conn);
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 507) 	}
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 508) 
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 509) 	return 0;
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 510) }
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 511) 
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 512) /*
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 513)  * Get mark connector, make sure it is alive and return with its lock held.
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 514)  * This is for users that get connector pointer from inode or mount. Users that
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 515)  * hold reference to a mark on the list may directly lock connector->lock as
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 516)  * they are sure list cannot go away under them.
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 517)  */
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 518) static struct fsnotify_mark_connector *fsnotify_grab_connector(
9b6e543450dc0 (Amir Goldstein  2018-06-23 17:54:47 +0300 519) 						fsnotify_connp_t *connp)
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 520) {
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 521) 	struct fsnotify_mark_connector *conn;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 522) 	int idx;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 523) 
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 524) 	idx = srcu_read_lock(&fsnotify_mark_srcu);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 525) 	conn = srcu_dereference(*connp, &fsnotify_mark_srcu);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 526) 	if (!conn)
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 527) 		goto out;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 528) 	spin_lock(&conn->lock);
d6f7b98bc8147 (Amir Goldstein  2018-04-20 16:10:49 -0700 529) 	if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) {
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 530) 		spin_unlock(&conn->lock);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 531) 		srcu_read_unlock(&fsnotify_mark_srcu, idx);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 532) 		return NULL;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 533) 	}
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 534) out:
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 535) 	srcu_read_unlock(&fsnotify_mark_srcu, idx);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 536) 	return conn;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 537) }
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 538) 
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 539) /*
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 540)  * Add mark into proper place in given list of marks. These marks may be used
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 541)  * for the fsnotify backend to determine which event types should be delivered
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 542)  * to which group and for which inodes. These marks are ordered according to
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 543)  * priority, highest number first, and then by the group's location in memory.
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 544)  */
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 545) static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
b812a9f589637 (Amir Goldstein  2018-06-23 17:54:48 +0300 546) 				  fsnotify_connp_t *connp, unsigned int type,
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 547) 				  int allow_dups, __kernel_fsid_t *fsid)
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 548) {
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 549) 	struct fsnotify_mark *lmark, *last = NULL;
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 550) 	struct fsnotify_mark_connector *conn;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 551) 	int cmp;
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 552) 	int err = 0;
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 553) 
b812a9f589637 (Amir Goldstein  2018-06-23 17:54:48 +0300 554) 	if (WARN_ON(!fsnotify_valid_obj_type(type)))
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 555) 		return -EINVAL;
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 556) 
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 557) 	/* Backend is expected to check for zero fsid (e.g. tmpfs) */
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 558) 	if (fsid && WARN_ON_ONCE(!fsid->val[0] && !fsid->val[1]))
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 559) 		return -ENODEV;
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 560) 
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 561) restart:
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 562) 	spin_lock(&mark->lock);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 563) 	conn = fsnotify_grab_connector(connp);
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 564) 	if (!conn) {
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 565) 		spin_unlock(&mark->lock);
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 566) 		err = fsnotify_attach_connector_to_object(connp, type, fsid);
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 567) 		if (err)
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 568) 			return err;
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 569) 		goto restart;
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 570) 	} else if (fsid && !(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID)) {
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 571) 		conn->fsid = *fsid;
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 572) 		/* Pairs with smp_rmb() in fanotify_get_fsid() */
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 573) 		smp_wmb();
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 574) 		conn->flags |= FSNOTIFY_CONN_FLAG_HAS_FSID;
c285a2f01d692 (Amir Goldstein  2019-06-19 13:34:44 +0300 575) 	} else if (fsid && (conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID) &&
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 576) 		   (fsid->val[0] != conn->fsid.val[0] ||
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 577) 		    fsid->val[1] != conn->fsid.val[1])) {
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 578) 		/*
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 579) 		 * Backend is expected to check for non uniform fsid
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 580) 		 * (e.g. btrfs), but maybe we missed something?
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 581) 		 * Only allow setting conn->fsid once to non zero fsid.
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 582) 		 * inotify and non-fid fanotify groups do not set nor test
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 583) 		 * conn->fsid.
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 584) 		 */
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 585) 		pr_warn_ratelimited("%s: fsid mismatch on object of type %u: "
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 586) 				    "%x.%x != %x.%x\n", __func__, conn->type,
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 587) 				    fsid->val[0], fsid->val[1],
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 588) 				    conn->fsid.val[0], conn->fsid.val[1]);
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 589) 		err = -EXDEV;
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 590) 		goto out_err;
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 591) 	}
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 592) 
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 593) 	/* is mark the first mark? */
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 594) 	if (hlist_empty(&conn->list)) {
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 595) 		hlist_add_head_rcu(&mark->obj_list, &conn->list);
86ffe245c430f (Jan Kara        2017-03-14 14:29:35 +0100 596) 		goto added;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 597) 	}
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 598) 
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 599) 	/* should mark be in the middle of the current list? */
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 600) 	hlist_for_each_entry(lmark, &conn->list, obj_list) {
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 601) 		last = lmark;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 602) 
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 603) 		if ((lmark->group == mark->group) &&
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 604) 		    (lmark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) &&
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 605) 		    !allow_dups) {
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 606) 			err = -EEXIST;
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 607) 			goto out_err;
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 608) 		}
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 609) 
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 610) 		cmp = fsnotify_compare_groups(lmark->group, mark->group);
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 611) 		if (cmp >= 0) {
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 612) 			hlist_add_before_rcu(&mark->obj_list, &lmark->obj_list);
86ffe245c430f (Jan Kara        2017-03-14 14:29:35 +0100 613) 			goto added;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 614) 		}
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 615) 	}
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 616) 
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 617) 	BUG_ON(last == NULL);
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 618) 	/* mark should be the last entry.  last is the current last entry */
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 619) 	hlist_add_behind_rcu(&mark->obj_list, &last->obj_list);
86ffe245c430f (Jan Kara        2017-03-14 14:29:35 +0100 620) added:
11a6f8e2db265 (Jan Kara        2019-05-01 18:05:11 +0200 621) 	/*
11a6f8e2db265 (Jan Kara        2019-05-01 18:05:11 +0200 622) 	 * Since connector is attached to object using cmpxchg() we are
11a6f8e2db265 (Jan Kara        2019-05-01 18:05:11 +0200 623) 	 * guaranteed that connector initialization is fully visible by anyone
11a6f8e2db265 (Jan Kara        2019-05-01 18:05:11 +0200 624) 	 * seeing mark->connector set.
11a6f8e2db265 (Jan Kara        2019-05-01 18:05:11 +0200 625) 	 */
b1da6a51871c6 (Jan Kara        2019-04-24 18:39:57 +0200 626) 	WRITE_ONCE(mark->connector, conn);
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 627) out_err:
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 628) 	spin_unlock(&conn->lock);
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 629) 	spin_unlock(&mark->lock);
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 630) 	return err;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 631) }
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 632) 
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 633) /*
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 634)  * Attach an initialized mark to a given group and fs object.
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 635)  * These marks may be used for the fsnotify backend to determine which
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 636)  * event types should be delivered to which group.
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 637)  */
b812a9f589637 (Amir Goldstein  2018-06-23 17:54:48 +0300 638) int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
b812a9f589637 (Amir Goldstein  2018-06-23 17:54:48 +0300 639) 			     fsnotify_connp_t *connp, unsigned int type,
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 640) 			     int allow_dups, __kernel_fsid_t *fsid)
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 641) {
7b1293234084d (Jan Kara        2016-12-21 18:32:48 +0100 642) 	struct fsnotify_group *group = mark->group;
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 643) 	int ret = 0;
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 644) 
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 645) 	BUG_ON(!mutex_is_locked(&group->mark_mutex));
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 646) 
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 647) 	/*
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 648) 	 * LOCKING ORDER!!!!
986ab09807ca9 (Lino Sanfilippo 2011-06-14 17:29:50 +0200 649) 	 * group->mark_mutex
104d06f08ea59 (Lino Sanfilippo 2011-06-14 17:29:48 +0200 650) 	 * mark->lock
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 651) 	 * mark->connector->lock
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 652) 	 */
104d06f08ea59 (Lino Sanfilippo 2011-06-14 17:29:48 +0200 653) 	spin_lock(&mark->lock);
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 654) 	mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE | FSNOTIFY_MARK_FLAG_ATTACHED;
700307a29ad61 (Eric Paris      2010-07-28 10:18:38 -0400 655) 
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 656) 	list_add(&mark->g_list, &group->marks_list);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 657) 	fsnotify_get_mark(mark); /* for g_list */
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 658) 	spin_unlock(&mark->lock);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 659) 
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 660) 	ret = fsnotify_add_mark_list(mark, connp, type, allow_dups, fsid);
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 661) 	if (ret)
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 662) 		goto err;
755b5bc681eb4 (Jan Kara        2017-03-14 16:11:23 +0100 663) 
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 664) 	if (mark->mask)
a242677bb1e6f (Jan Kara        2017-03-15 09:16:27 +0100 665) 		fsnotify_recalc_mask(mark->connector);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 666) 
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 667) 	return ret;
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 668) err:
9cf90cef362d4 (Jan Kara        2017-10-31 10:09:25 +0100 669) 	spin_lock(&mark->lock);
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 670) 	mark->flags &= ~(FSNOTIFY_MARK_FLAG_ALIVE |
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 671) 			 FSNOTIFY_MARK_FLAG_ATTACHED);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 672) 	list_del_init(&mark->g_list);
9cf90cef362d4 (Jan Kara        2017-10-31 10:09:25 +0100 673) 	spin_unlock(&mark->lock);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 674) 
11375145a70d6 (Jan Kara        2016-11-09 14:54:20 +0100 675) 	fsnotify_put_mark(mark);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 676) 	return ret;
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 677) }
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 678) 
b812a9f589637 (Amir Goldstein  2018-06-23 17:54:48 +0300 679) int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp,
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 680) 		      unsigned int type, int allow_dups, __kernel_fsid_t *fsid)
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 681) {
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 682) 	int ret;
7b1293234084d (Jan Kara        2016-12-21 18:32:48 +0100 683) 	struct fsnotify_group *group = mark->group;
7b1293234084d (Jan Kara        2016-12-21 18:32:48 +0100 684) 
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 685) 	mutex_lock(&group->mark_mutex);
77115225acc67 (Amir Goldstein  2019-01-10 19:04:37 +0200 686) 	ret = fsnotify_add_mark_locked(mark, connp, type, allow_dups, fsid);
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 687) 	mutex_unlock(&group->mark_mutex);
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 688) 	return ret;
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 689) }
b72679ee89a0a (Trond Myklebust 2019-08-18 14:18:46 -0400 690) EXPORT_SYMBOL_GPL(fsnotify_add_mark);
d5a335b845792 (Lino Sanfilippo 2011-06-14 17:29:52 +0200 691) 
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 692) /*
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 693)  * Given a list of marks, find the mark associated with given group. If found
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 694)  * take a reference to that mark and return it, else return NULL.
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 695)  */
9b6e543450dc0 (Amir Goldstein  2018-06-23 17:54:47 +0300 696) struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp,
9b6e543450dc0 (Amir Goldstein  2018-06-23 17:54:47 +0300 697) 					 struct fsnotify_group *group)
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 698) {
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 699) 	struct fsnotify_mark_connector *conn;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 700) 	struct fsnotify_mark *mark;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 701) 
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 702) 	conn = fsnotify_grab_connector(connp);
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 703) 	if (!conn)
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 704) 		return NULL;
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 705) 
9dd813c15b2c1 (Jan Kara        2017-03-14 12:31:02 +0100 706) 	hlist_for_each_entry(mark, &conn->list, obj_list) {
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 707) 		if (mark->group == group &&
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 708) 		    (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) {
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 709) 			fsnotify_get_mark(mark);
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 710) 			spin_unlock(&conn->lock);
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 711) 			return mark;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 712) 		}
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 713) 	}
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 714) 	spin_unlock(&conn->lock);
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 715) 	return NULL;
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 716) }
b72679ee89a0a (Trond Myklebust 2019-08-18 14:18:46 -0400 717) EXPORT_SYMBOL_GPL(fsnotify_find_mark);
0809ab69a2782 (Jan Kara        2014-12-12 16:58:36 -0800 718) 
d6f7b98bc8147 (Amir Goldstein  2018-04-20 16:10:49 -0700 719) /* Clear any marks in a group with given type mask */
18f2e0d3a4364 (Jan Kara        2017-01-04 10:33:18 +0100 720) void fsnotify_clear_marks_by_group(struct fsnotify_group *group,
d6f7b98bc8147 (Amir Goldstein  2018-04-20 16:10:49 -0700 721) 				   unsigned int type_mask)
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 722) {
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 723) 	struct fsnotify_mark *lmark, *mark;
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 724) 	LIST_HEAD(to_free);
2e37c6ca8d76c (Jan Kara        2017-01-04 10:51:58 +0100 725) 	struct list_head *head = &to_free;
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 726) 
2e37c6ca8d76c (Jan Kara        2017-01-04 10:51:58 +0100 727) 	/* Skip selection step if we want to clear all marks. */
d6f7b98bc8147 (Amir Goldstein  2018-04-20 16:10:49 -0700 728) 	if (type_mask == FSNOTIFY_OBJ_ALL_TYPES_MASK) {
2e37c6ca8d76c (Jan Kara        2017-01-04 10:51:58 +0100 729) 		head = &group->marks_list;
2e37c6ca8d76c (Jan Kara        2017-01-04 10:51:58 +0100 730) 		goto clear;
2e37c6ca8d76c (Jan Kara        2017-01-04 10:51:58 +0100 731) 	}
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 732) 	/*
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 733) 	 * We have to be really careful here. Anytime we drop mark_mutex, e.g.
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 734) 	 * fsnotify_clear_marks_by_inode() can come and free marks. Even in our
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 735) 	 * to_free list so we have to use mark_mutex even when accessing that
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 736) 	 * list. And freeing mark requires us to drop mark_mutex. So we can
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 737) 	 * reliably free only the first mark in the list. That's why we first
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 738) 	 * move marks to free to to_free list in one go and then free marks in
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 739) 	 * to_free list one by one.
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 740) 	 */
6960b0d909cde (Lino Sanfilippo 2011-08-12 01:13:31 +0200 741) 	mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 742) 	list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
d6f7b98bc8147 (Amir Goldstein  2018-04-20 16:10:49 -0700 743) 		if ((1U << mark->connector->type) & type_mask)
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 744) 			list_move(&mark->g_list, &to_free);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 745) 	}
986ab09807ca9 (Lino Sanfilippo 2011-06-14 17:29:50 +0200 746) 	mutex_unlock(&group->mark_mutex);
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 747) 
2e37c6ca8d76c (Jan Kara        2017-01-04 10:51:58 +0100 748) clear:
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 749) 	while (1) {
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 750) 		mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
2e37c6ca8d76c (Jan Kara        2017-01-04 10:51:58 +0100 751) 		if (list_empty(head)) {
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 752) 			mutex_unlock(&group->mark_mutex);
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 753) 			break;
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 754) 		}
2e37c6ca8d76c (Jan Kara        2017-01-04 10:51:58 +0100 755) 		mark = list_first_entry(head, struct fsnotify_mark, g_list);
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 756) 		fsnotify_get_mark(mark);
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 757) 		fsnotify_detach_mark(mark);
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 758) 		mutex_unlock(&group->mark_mutex);
4712e722f9145 (Jan Kara        2015-09-04 15:43:12 -0700 759) 		fsnotify_free_mark(mark);
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 760) 		fsnotify_put_mark(mark);
8f2f3eb59dff4 (Jan Kara        2015-08-06 15:46:42 -0700 761) 	}
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 762) }
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 763) 
9b6e543450dc0 (Amir Goldstein  2018-06-23 17:54:47 +0300 764) /* Destroy all marks attached to an object via connector */
9b6e543450dc0 (Amir Goldstein  2018-06-23 17:54:47 +0300 765) void fsnotify_destroy_marks(fsnotify_connp_t *connp)
0810b4f9f2079 (Jan Kara        2017-02-01 09:23:48 +0100 766) {
08991e83b7286 (Jan Kara        2017-02-01 09:21:58 +0100 767) 	struct fsnotify_mark_connector *conn;
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 768) 	struct fsnotify_mark *mark, *old_mark = NULL;
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 769) 	void *objp;
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 770) 	unsigned int type;
0810b4f9f2079 (Jan Kara        2017-02-01 09:23:48 +0100 771) 
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 772) 	conn = fsnotify_grab_connector(connp);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 773) 	if (!conn)
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 774) 		return;
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 775) 	/*
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 776) 	 * We have to be careful since we can race with e.g.
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 777) 	 * fsnotify_clear_marks_by_group() and once we drop the conn->lock, the
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 778) 	 * list can get modified. However we are holding mark reference and
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 779) 	 * thus our mark cannot be removed from obj_list so we can continue
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 780) 	 * iteration after regaining conn->lock.
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 781) 	 */
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 782) 	hlist_for_each_entry(mark, &conn->list, obj_list) {
0810b4f9f2079 (Jan Kara        2017-02-01 09:23:48 +0100 783) 		fsnotify_get_mark(mark);
04662cab59fc3 (Jan Kara        2017-02-01 08:19:43 +0100 784) 		spin_unlock(&conn->lock);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 785) 		if (old_mark)
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 786) 			fsnotify_put_mark(old_mark);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 787) 		old_mark = mark;
0810b4f9f2079 (Jan Kara        2017-02-01 09:23:48 +0100 788) 		fsnotify_destroy_mark(mark, mark->group);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 789) 		spin_lock(&conn->lock);
0810b4f9f2079 (Jan Kara        2017-02-01 09:23:48 +0100 790) 	}
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 791) 	/*
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 792) 	 * Detach list from object now so that we don't pin inode until all
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 793) 	 * mark references get dropped. It would lead to strange results such
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 794) 	 * as delaying inode deletion or blocking unmount.
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 795) 	 */
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 796) 	objp = fsnotify_detach_connector_from_object(conn, &type);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 797) 	spin_unlock(&conn->lock);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 798) 	if (old_mark)
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 799) 		fsnotify_put_mark(old_mark);
721fb6fbfd213 (Jan Kara        2018-10-17 13:07:05 +0200 800) 	fsnotify_drop_object(type, objp);
0810b4f9f2079 (Jan Kara        2017-02-01 09:23:48 +0100 801) }
0810b4f9f2079 (Jan Kara        2017-02-01 09:23:48 +0100 802) 
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 803) /*
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 804)  * Nothing fancy, just initialize lists and locks and counters.
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 805)  */
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 806) void fsnotify_init_mark(struct fsnotify_mark *mark,
054c636e5c805 (Jan Kara        2016-12-21 18:06:12 +0100 807) 			struct fsnotify_group *group)
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 808) {
ba643f04cdda1 (Eric Paris      2009-12-17 21:24:27 -0500 809) 	memset(mark, 0, sizeof(*mark));
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 810) 	spin_lock_init(&mark->lock);
ab97f87325e28 (Elena Reshetova 2017-10-20 13:26:02 +0300 811) 	refcount_set(&mark->refcnt, 1);
7b1293234084d (Jan Kara        2016-12-21 18:32:48 +0100 812) 	fsnotify_get_group(group);
7b1293234084d (Jan Kara        2016-12-21 18:32:48 +0100 813) 	mark->group = group;
b1da6a51871c6 (Jan Kara        2019-04-24 18:39:57 +0200 814) 	WRITE_ONCE(mark->connector, NULL);
5444e2981c31d (Eric Paris      2009-12-17 21:24:27 -0500 815) }
b72679ee89a0a (Trond Myklebust 2019-08-18 14:18:46 -0400 816) EXPORT_SYMBOL_GPL(fsnotify_init_mark);
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800 817) 
35e481761cdc6 (Jan Kara        2016-05-19 17:08:59 -0700 818) /*
35e481761cdc6 (Jan Kara        2016-05-19 17:08:59 -0700 819)  * Destroy all marks in destroy_list, waits for SRCU period to finish before
35e481761cdc6 (Jan Kara        2016-05-19 17:08:59 -0700 820)  * actually freeing marks.
35e481761cdc6 (Jan Kara        2016-05-19 17:08:59 -0700 821)  */
f09b04a03e023 (Jan Kara        2016-12-21 14:48:18 +0100 822) static void fsnotify_mark_destroy_workfn(struct work_struct *work)
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800 823) {
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800 824) 	struct fsnotify_mark *mark, *next;
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800 825) 	struct list_head private_destroy_list;
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800 826) 
0918f1c309b86 (Jeff Layton     2016-02-17 13:11:21 -0800 827) 	spin_lock(&destroy_lock);
0918f1c309b86 (Jeff Layton     2016-02-17 13:11:21 -0800 828) 	/* exchange the list head */
0918f1c309b86 (Jeff Layton     2016-02-17 13:11:21 -0800 829) 	list_replace_init(&destroy_list, &private_destroy_list);
0918f1c309b86 (Jeff Layton     2016-02-17 13:11:21 -0800 830) 	spin_unlock(&destroy_lock);
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800 831) 
0918f1c309b86 (Jeff Layton     2016-02-17 13:11:21 -0800 832) 	synchronize_srcu(&fsnotify_mark_srcu);
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800 833) 
0918f1c309b86 (Jeff Layton     2016-02-17 13:11:21 -0800 834) 	list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) {
0918f1c309b86 (Jeff Layton     2016-02-17 13:11:21 -0800 835) 		list_del_init(&mark->g_list);
6b3f05d24d355 (Jan Kara        2016-12-21 12:15:30 +0100 836) 		fsnotify_final_mark_destroy(mark);
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800 837) 	}
13d34ac6e55b8 (Jeff Layton     2016-02-17 13:11:18 -0800 838) }
35e481761cdc6 (Jan Kara        2016-05-19 17:08:59 -0700 839) 
f09b04a03e023 (Jan Kara        2016-12-21 14:48:18 +0100 840) /* Wait for all marks queued for destruction to be actually destroyed */
f09b04a03e023 (Jan Kara        2016-12-21 14:48:18 +0100 841) void fsnotify_wait_marks_destroyed(void)
35e481761cdc6 (Jan Kara        2016-05-19 17:08:59 -0700 842) {
f09b04a03e023 (Jan Kara        2016-12-21 14:48:18 +0100 843) 	flush_delayed_work(&reaper_work);
35e481761cdc6 (Jan Kara        2016-05-19 17:08:59 -0700 844) }
b72679ee89a0a (Trond Myklebust 2019-08-18 14:18:46 -0400 845) EXPORT_SYMBOL_GPL(fsnotify_wait_marks_destroyed);