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);