1c82ee6d3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 25444e298SEric Paris /* 35444e298SEric Paris * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com> 45444e298SEric Paris */ 55444e298SEric Paris 65444e298SEric Paris /* 75444e298SEric Paris * fsnotify inode mark locking/lifetime/and refcnting 85444e298SEric Paris * 95444e298SEric Paris * REFCNT: 109756b918SLino Sanfilippo * The group->recnt and mark->refcnt tell how many "things" in the kernel 119756b918SLino Sanfilippo * currently are referencing the objects. Both kind of objects typically will 129756b918SLino Sanfilippo * live inside the kernel with a refcnt of 2, one for its creation and one for 139756b918SLino Sanfilippo * the reference a group and a mark hold to each other. 149756b918SLino Sanfilippo * If you are holding the appropriate locks, you can take a reference and the 159756b918SLino Sanfilippo * object itself is guaranteed to survive until the reference is dropped. 165444e298SEric Paris * 175444e298SEric Paris * LOCKING: 189756b918SLino Sanfilippo * There are 3 locks involved with fsnotify inode marks and they MUST be taken 199756b918SLino Sanfilippo * in order as follows: 205444e298SEric Paris * 219756b918SLino Sanfilippo * group->mark_mutex 225444e298SEric Paris * mark->lock 2304662cabSJan Kara * mark->connector->lock 245444e298SEric Paris * 259756b918SLino Sanfilippo * group->mark_mutex protects the marks_list anchored inside a given group and 269756b918SLino Sanfilippo * each mark is hooked via the g_list. It also protects the groups private 279756b918SLino Sanfilippo * data (i.e group limits). 289756b918SLino Sanfilippo 299756b918SLino Sanfilippo * mark->lock protects the marks attributes like its masks and flags. 309756b918SLino Sanfilippo * Furthermore it protects the access to a reference of the group that the mark 319756b918SLino Sanfilippo * is assigned to as well as the access to a reference of the inode/vfsmount 329756b918SLino Sanfilippo * that is being watched by the mark. 335444e298SEric Paris * 3404662cabSJan Kara * mark->connector->lock protects the list of marks anchored inside an 3504662cabSJan Kara * inode / vfsmount and each mark is hooked via the i_list. 365444e298SEric Paris * 3704662cabSJan Kara * A list of notification marks relating to inode / mnt is contained in 3804662cabSJan Kara * fsnotify_mark_connector. That structure is alive as long as there are any 396b3f05d2SJan Kara * marks in the list and is also protected by fsnotify_mark_srcu. A mark gets 406b3f05d2SJan Kara * detached from fsnotify_mark_connector when last reference to the mark is 416b3f05d2SJan Kara * dropped. Thus having mark reference is enough to protect mark->connector 426b3f05d2SJan Kara * pointer and to make sure fsnotify_mark_connector cannot disappear. Also 436b3f05d2SJan Kara * because we remove mark from g_list before dropping mark reference associated 446b3f05d2SJan Kara * with that, any mark found through g_list is guaranteed to have 456b3f05d2SJan Kara * mark->connector set until we drop group->mark_mutex. 465444e298SEric Paris * 475444e298SEric Paris * LIFETIME: 485444e298SEric Paris * Inode marks survive between when they are added to an inode and when their 49c1f33073SJan Kara * refcnt==0. Marks are also protected by fsnotify_mark_srcu. 505444e298SEric Paris * 515444e298SEric Paris * The inode mark can be cleared for a number of different reasons including: 525444e298SEric Paris * - The inode is unlinked for the last time. (fsnotify_inode_remove) 535444e298SEric Paris * - The inode is being evicted from cache. (fsnotify_inode_delete) 545444e298SEric Paris * - The fs the inode is on is unmounted. (fsnotify_inode_delete/fsnotify_unmount_inodes) 555444e298SEric Paris * - Something explicitly requests that it be removed. (fsnotify_destroy_mark) 565444e298SEric Paris * - The fsnotify_group associated with the mark is going away and all such marks 572e37c6caSJan Kara * need to be cleaned up. (fsnotify_clear_marks_by_group) 585444e298SEric Paris * 595444e298SEric Paris * This has the very interesting property of being able to run concurrently with 605444e298SEric Paris * any (or all) other directions. 615444e298SEric Paris */ 625444e298SEric Paris 635444e298SEric Paris #include <linux/fs.h> 645444e298SEric Paris #include <linux/init.h> 655444e298SEric Paris #include <linux/kernel.h> 6675c1be48SEric Paris #include <linux/kthread.h> 675444e298SEric Paris #include <linux/module.h> 685444e298SEric Paris #include <linux/mutex.h> 695444e298SEric Paris #include <linux/slab.h> 705444e298SEric Paris #include <linux/spinlock.h> 7175c1be48SEric Paris #include <linux/srcu.h> 7277115225SAmir Goldstein #include <linux/ratelimit.h> 735444e298SEric Paris 7460063497SArun Sharma #include <linux/atomic.h> 755444e298SEric Paris 765444e298SEric Paris #include <linux/fsnotify_backend.h> 775444e298SEric Paris #include "fsnotify.h" 785444e298SEric Paris 790918f1c3SJeff Layton #define FSNOTIFY_REAPER_DELAY (1) /* 1 jiffy */ 800918f1c3SJeff Layton 8175c1be48SEric Paris struct srcu_struct fsnotify_mark_srcu; 829dd813c1SJan Kara struct kmem_cache *fsnotify_mark_connector_cachep; 839dd813c1SJan Kara 8413d34ac6SJeff Layton static DEFINE_SPINLOCK(destroy_lock); 8513d34ac6SJeff Layton static LIST_HEAD(destroy_list); 8608991e83SJan Kara static struct fsnotify_mark_connector *connector_destroy_list; 870918f1c3SJeff Layton 8835e48176SJan Kara static void fsnotify_mark_destroy_workfn(struct work_struct *work); 8935e48176SJan Kara static DECLARE_DELAYED_WORK(reaper_work, fsnotify_mark_destroy_workfn); 9075c1be48SEric Paris 9108991e83SJan Kara static void fsnotify_connector_destroy_workfn(struct work_struct *work); 9208991e83SJan Kara static DECLARE_WORK(connector_reaper_work, fsnotify_connector_destroy_workfn); 9308991e83SJan Kara 945444e298SEric Paris void fsnotify_get_mark(struct fsnotify_mark *mark) 955444e298SEric Paris { 96ab97f873SElena Reshetova WARN_ON_ONCE(!refcount_read(&mark->refcnt)); 97ab97f873SElena Reshetova refcount_inc(&mark->refcnt); 985444e298SEric Paris } 995444e298SEric Paris 1003ac70bfcSAmir Goldstein static __u32 *fsnotify_conn_mask_p(struct fsnotify_mark_connector *conn) 1013ac70bfcSAmir Goldstein { 1023ac70bfcSAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) 1033ac70bfcSAmir Goldstein return &fsnotify_conn_inode(conn)->i_fsnotify_mask; 1043ac70bfcSAmir Goldstein else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) 1053ac70bfcSAmir Goldstein return &fsnotify_conn_mount(conn)->mnt_fsnotify_mask; 1061e6cb723SAmir Goldstein else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) 1071e6cb723SAmir Goldstein return &fsnotify_conn_sb(conn)->s_fsnotify_mask; 1083ac70bfcSAmir Goldstein return NULL; 1093ac70bfcSAmir Goldstein } 1103ac70bfcSAmir Goldstein 1113ac70bfcSAmir Goldstein __u32 fsnotify_conn_mask(struct fsnotify_mark_connector *conn) 1123ac70bfcSAmir Goldstein { 1133ac70bfcSAmir Goldstein if (WARN_ON(!fsnotify_valid_obj_type(conn->type))) 1143ac70bfcSAmir Goldstein return 0; 1153ac70bfcSAmir Goldstein 1163ac70bfcSAmir Goldstein return *fsnotify_conn_mask_p(conn); 1173ac70bfcSAmir Goldstein } 1183ac70bfcSAmir Goldstein 119c3638b5bSAmir Goldstein static void fsnotify_get_inode_ref(struct inode *inode) 120c3638b5bSAmir Goldstein { 121c3638b5bSAmir Goldstein ihold(inode); 122c3638b5bSAmir Goldstein atomic_long_inc(&inode->i_sb->s_fsnotify_connectors); 123c3638b5bSAmir Goldstein } 124c3638b5bSAmir Goldstein 125c3638b5bSAmir Goldstein /* 126c3638b5bSAmir Goldstein * Grab or drop inode reference for the connector if needed. 127c3638b5bSAmir Goldstein * 128c3638b5bSAmir Goldstein * When it's time to drop the reference, we only clear the HAS_IREF flag and 129c3638b5bSAmir Goldstein * return the inode object. fsnotify_drop_object() will be resonsible for doing 130c3638b5bSAmir Goldstein * iput() outside of spinlocks. This happens when last mark that wanted iref is 131c3638b5bSAmir Goldstein * detached. 132c3638b5bSAmir Goldstein */ 133c3638b5bSAmir Goldstein static struct inode *fsnotify_update_iref(struct fsnotify_mark_connector *conn, 134c3638b5bSAmir Goldstein bool want_iref) 135c3638b5bSAmir Goldstein { 136c3638b5bSAmir Goldstein bool has_iref = conn->flags & FSNOTIFY_CONN_FLAG_HAS_IREF; 137c3638b5bSAmir Goldstein struct inode *inode = NULL; 138c3638b5bSAmir Goldstein 139c3638b5bSAmir Goldstein if (conn->type != FSNOTIFY_OBJ_TYPE_INODE || 140c3638b5bSAmir Goldstein want_iref == has_iref) 141c3638b5bSAmir Goldstein return NULL; 142c3638b5bSAmir Goldstein 143c3638b5bSAmir Goldstein if (want_iref) { 144c3638b5bSAmir Goldstein /* Pin inode if any mark wants inode refcount held */ 145c3638b5bSAmir Goldstein fsnotify_get_inode_ref(fsnotify_conn_inode(conn)); 146c3638b5bSAmir Goldstein conn->flags |= FSNOTIFY_CONN_FLAG_HAS_IREF; 147c3638b5bSAmir Goldstein } else { 148c3638b5bSAmir Goldstein /* Unpin inode after detach of last mark that wanted iref */ 149c3638b5bSAmir Goldstein inode = fsnotify_conn_inode(conn); 150c3638b5bSAmir Goldstein conn->flags &= ~FSNOTIFY_CONN_FLAG_HAS_IREF; 151c3638b5bSAmir Goldstein } 152c3638b5bSAmir Goldstein 153c3638b5bSAmir Goldstein return inode; 154c3638b5bSAmir Goldstein } 155c3638b5bSAmir Goldstein 156c3638b5bSAmir Goldstein static void *__fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) 1570809ab69SJan Kara { 1580809ab69SJan Kara u32 new_mask = 0; 159c3638b5bSAmir Goldstein bool want_iref = false; 1600809ab69SJan Kara struct fsnotify_mark *mark; 1610809ab69SJan Kara 16204662cabSJan Kara assert_spin_locked(&conn->lock); 163d3bc0fa8SJan Kara /* We can get detached connector here when inode is getting unlinked. */ 164d3bc0fa8SJan Kara if (!fsnotify_valid_obj_type(conn->type)) 165c3638b5bSAmir Goldstein return NULL; 1666b3f05d2SJan Kara hlist_for_each_entry(mark, &conn->list, obj_list) { 167c3638b5bSAmir Goldstein if (!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) 168c3638b5bSAmir Goldstein continue; 1694f0b903dSAmir Goldstein new_mask |= fsnotify_calc_mask(mark); 170c3638b5bSAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_INODE && 171c3638b5bSAmir Goldstein !(mark->flags & FSNOTIFY_MARK_FLAG_NO_IREF)) 172c3638b5bSAmir Goldstein want_iref = true; 1736b3f05d2SJan Kara } 1743ac70bfcSAmir Goldstein *fsnotify_conn_mask_p(conn) = new_mask; 175c3638b5bSAmir Goldstein 176c3638b5bSAmir Goldstein return fsnotify_update_iref(conn, want_iref); 177a242677bSJan Kara } 178a242677bSJan Kara 179a242677bSJan Kara /* 180a242677bSJan Kara * Calculate mask of events for a list of marks. The caller must make sure 18136f10f55SAmir Goldstein * connector and connector->obj cannot disappear under us. Callers achieve 1826b3f05d2SJan Kara * this by holding a mark->lock or mark->group->mark_mutex for a mark on this 1836b3f05d2SJan Kara * list. 184a242677bSJan Kara */ 185a242677bSJan Kara void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) 186a242677bSJan Kara { 187a242677bSJan Kara if (!conn) 188a242677bSJan Kara return; 189a242677bSJan Kara 19004662cabSJan Kara spin_lock(&conn->lock); 191a242677bSJan Kara __fsnotify_recalc_mask(conn); 19204662cabSJan Kara spin_unlock(&conn->lock); 193d6f7b98bSAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) 19436f10f55SAmir Goldstein __fsnotify_update_child_dentry_flags( 19536f10f55SAmir Goldstein fsnotify_conn_inode(conn)); 1960809ab69SJan Kara } 1970809ab69SJan Kara 19808991e83SJan Kara /* Free all connectors queued for freeing once SRCU period ends */ 19908991e83SJan Kara static void fsnotify_connector_destroy_workfn(struct work_struct *work) 20008991e83SJan Kara { 20108991e83SJan Kara struct fsnotify_mark_connector *conn, *free; 20208991e83SJan Kara 20308991e83SJan Kara spin_lock(&destroy_lock); 20408991e83SJan Kara conn = connector_destroy_list; 20508991e83SJan Kara connector_destroy_list = NULL; 20608991e83SJan Kara spin_unlock(&destroy_lock); 20708991e83SJan Kara 20808991e83SJan Kara synchronize_srcu(&fsnotify_mark_srcu); 20908991e83SJan Kara while (conn) { 21008991e83SJan Kara free = conn; 21108991e83SJan Kara conn = conn->destroy_next; 21208991e83SJan Kara kmem_cache_free(fsnotify_mark_connector_cachep, free); 21308991e83SJan Kara } 21408991e83SJan Kara } 21508991e83SJan Kara 21611fa333bSAmir Goldstein static void fsnotify_put_inode_ref(struct inode *inode) 21711fa333bSAmir Goldstein { 21811fa333bSAmir Goldstein struct super_block *sb = inode->i_sb; 21911fa333bSAmir Goldstein 22011fa333bSAmir Goldstein iput(inode); 221ec44610fSAmir Goldstein if (atomic_long_dec_and_test(&sb->s_fsnotify_connectors)) 222ec44610fSAmir Goldstein wake_up_var(&sb->s_fsnotify_connectors); 223ec44610fSAmir Goldstein } 224ec44610fSAmir Goldstein 225ec44610fSAmir Goldstein static void fsnotify_get_sb_connectors(struct fsnotify_mark_connector *conn) 226ec44610fSAmir Goldstein { 227ec44610fSAmir Goldstein struct super_block *sb = fsnotify_connector_sb(conn); 228ec44610fSAmir Goldstein 229ec44610fSAmir Goldstein if (sb) 230ec44610fSAmir Goldstein atomic_long_inc(&sb->s_fsnotify_connectors); 231ec44610fSAmir Goldstein } 232ec44610fSAmir Goldstein 233ec44610fSAmir Goldstein static void fsnotify_put_sb_connectors(struct fsnotify_mark_connector *conn) 234ec44610fSAmir Goldstein { 235ec44610fSAmir Goldstein struct super_block *sb = fsnotify_connector_sb(conn); 236ec44610fSAmir Goldstein 237ec44610fSAmir Goldstein if (sb && atomic_long_dec_and_test(&sb->s_fsnotify_connectors)) 238ec44610fSAmir Goldstein wake_up_var(&sb->s_fsnotify_connectors); 23911fa333bSAmir Goldstein } 24011fa333bSAmir Goldstein 241721fb6fbSJan Kara static void *fsnotify_detach_connector_from_object( 242721fb6fbSJan Kara struct fsnotify_mark_connector *conn, 243721fb6fbSJan Kara unsigned int *type) 24408991e83SJan Kara { 24508991e83SJan Kara struct inode *inode = NULL; 24608991e83SJan Kara 247721fb6fbSJan Kara *type = conn->type; 24836f10f55SAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) 24936f10f55SAmir Goldstein return NULL; 25036f10f55SAmir Goldstein 251d6f7b98bSAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) { 25236f10f55SAmir Goldstein inode = fsnotify_conn_inode(conn); 25308991e83SJan Kara inode->i_fsnotify_mask = 0; 254c3638b5bSAmir Goldstein 255c3638b5bSAmir Goldstein /* Unpin inode when detaching from connector */ 256c3638b5bSAmir Goldstein if (!(conn->flags & FSNOTIFY_CONN_FLAG_HAS_IREF)) 257c3638b5bSAmir Goldstein inode = NULL; 258d6f7b98bSAmir Goldstein } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) { 25936f10f55SAmir Goldstein fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0; 2601e6cb723SAmir Goldstein } else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) { 2611e6cb723SAmir Goldstein fsnotify_conn_sb(conn)->s_fsnotify_mask = 0; 26208991e83SJan Kara } 26308991e83SJan Kara 264ec44610fSAmir Goldstein fsnotify_put_sb_connectors(conn); 26536f10f55SAmir Goldstein rcu_assign_pointer(*(conn->obj), NULL); 26636f10f55SAmir Goldstein conn->obj = NULL; 26736f10f55SAmir Goldstein conn->type = FSNOTIFY_OBJ_TYPE_DETACHED; 26836f10f55SAmir Goldstein 26908991e83SJan Kara return inode; 27008991e83SJan Kara } 27108991e83SJan Kara 2726b3f05d2SJan Kara static void fsnotify_final_mark_destroy(struct fsnotify_mark *mark) 2736b3f05d2SJan Kara { 274054c636eSJan Kara struct fsnotify_group *group = mark->group; 275054c636eSJan Kara 276054c636eSJan Kara if (WARN_ON_ONCE(!group)) 277054c636eSJan Kara return; 278054c636eSJan Kara group->ops->free_mark(mark); 279054c636eSJan Kara fsnotify_put_group(group); 2806b3f05d2SJan Kara } 2816b3f05d2SJan Kara 282721fb6fbSJan Kara /* Drop object reference originally held by a connector */ 283721fb6fbSJan Kara static void fsnotify_drop_object(unsigned int type, void *objp) 284721fb6fbSJan Kara { 285721fb6fbSJan Kara if (!objp) 286721fb6fbSJan Kara return; 287721fb6fbSJan Kara /* Currently only inode references are passed to be dropped */ 288721fb6fbSJan Kara if (WARN_ON_ONCE(type != FSNOTIFY_OBJ_TYPE_INODE)) 289721fb6fbSJan Kara return; 29011fa333bSAmir Goldstein fsnotify_put_inode_ref(objp); 291721fb6fbSJan Kara } 292721fb6fbSJan Kara 2936b3f05d2SJan Kara void fsnotify_put_mark(struct fsnotify_mark *mark) 2948212a609SJan Kara { 295b1da6a51SJan Kara struct fsnotify_mark_connector *conn = READ_ONCE(mark->connector); 296721fb6fbSJan Kara void *objp = NULL; 297721fb6fbSJan Kara unsigned int type = FSNOTIFY_OBJ_TYPE_DETACHED; 29808991e83SJan Kara bool free_conn = false; 2998212a609SJan Kara 3006b3f05d2SJan Kara /* Catch marks that were actually never attached to object */ 301b1da6a51SJan Kara if (!conn) { 302ab97f873SElena Reshetova if (refcount_dec_and_test(&mark->refcnt)) 3036b3f05d2SJan Kara fsnotify_final_mark_destroy(mark); 3046b3f05d2SJan Kara return; 3056b3f05d2SJan Kara } 3066b3f05d2SJan Kara 3076b3f05d2SJan Kara /* 3086b3f05d2SJan Kara * We have to be careful so that traversals of obj_list under lock can 3096b3f05d2SJan Kara * safely grab mark reference. 3106b3f05d2SJan Kara */ 311b1da6a51SJan Kara if (!refcount_dec_and_lock(&mark->refcnt, &conn->lock)) 3126b3f05d2SJan Kara return; 3136b3f05d2SJan Kara 3148212a609SJan Kara hlist_del_init_rcu(&mark->obj_list); 3158212a609SJan Kara if (hlist_empty(&conn->list)) { 316721fb6fbSJan Kara objp = fsnotify_detach_connector_from_object(conn, &type); 31708991e83SJan Kara free_conn = true; 31808991e83SJan Kara } else { 319c3638b5bSAmir Goldstein objp = __fsnotify_recalc_mask(conn); 320c3638b5bSAmir Goldstein type = conn->type; 32108991e83SJan Kara } 322b1da6a51SJan Kara WRITE_ONCE(mark->connector, NULL); 32304662cabSJan Kara spin_unlock(&conn->lock); 3248212a609SJan Kara 325721fb6fbSJan Kara fsnotify_drop_object(type, objp); 3266b3f05d2SJan Kara 32708991e83SJan Kara if (free_conn) { 32808991e83SJan Kara spin_lock(&destroy_lock); 32908991e83SJan Kara conn->destroy_next = connector_destroy_list; 33008991e83SJan Kara connector_destroy_list = conn; 33108991e83SJan Kara spin_unlock(&destroy_lock); 33208991e83SJan Kara queue_work(system_unbound_wq, &connector_reaper_work); 33308991e83SJan Kara } 3346b3f05d2SJan Kara /* 3356b3f05d2SJan Kara * Note that we didn't update flags telling whether inode cares about 3366b3f05d2SJan Kara * what's happening with children. We update these flags from 3376b3f05d2SJan Kara * __fsnotify_parent() lazily when next event happens on one of our 3386b3f05d2SJan Kara * children. 3396b3f05d2SJan Kara */ 3406b3f05d2SJan Kara spin_lock(&destroy_lock); 3416b3f05d2SJan Kara list_add(&mark->g_list, &destroy_list); 3426b3f05d2SJan Kara spin_unlock(&destroy_lock); 3436b3f05d2SJan Kara queue_delayed_work(system_unbound_wq, &reaper_work, 3446b3f05d2SJan Kara FSNOTIFY_REAPER_DELAY); 3458212a609SJan Kara } 346b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_put_mark); 3478212a609SJan Kara 34824c20305SMiklos Szeredi /* 34924c20305SMiklos Szeredi * Get mark reference when we found the mark via lockless traversal of object 35024c20305SMiklos Szeredi * list. Mark can be already removed from the list by now and on its way to be 35124c20305SMiklos Szeredi * destroyed once SRCU period ends. 35224c20305SMiklos Szeredi * 35324c20305SMiklos Szeredi * Also pin the group so it doesn't disappear under us. 35424c20305SMiklos Szeredi */ 35524c20305SMiklos Szeredi static bool fsnotify_get_mark_safe(struct fsnotify_mark *mark) 356abc77577SJan Kara { 35724c20305SMiklos Szeredi if (!mark) 35824c20305SMiklos Szeredi return true; 359abc77577SJan Kara 360ab97f873SElena Reshetova if (refcount_inc_not_zero(&mark->refcnt)) { 3619a31d7adSMiklos Szeredi spin_lock(&mark->lock); 3629a31d7adSMiklos Szeredi if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) { 3639a31d7adSMiklos Szeredi /* mark is attached, group is still alive then */ 3649a31d7adSMiklos Szeredi atomic_inc(&mark->group->user_waits); 3659a31d7adSMiklos Szeredi spin_unlock(&mark->lock); 36624c20305SMiklos Szeredi return true; 3679a31d7adSMiklos Szeredi } 3689a31d7adSMiklos Szeredi spin_unlock(&mark->lock); 3699a31d7adSMiklos Szeredi fsnotify_put_mark(mark); 3709a31d7adSMiklos Szeredi } 37124c20305SMiklos Szeredi return false; 37224c20305SMiklos Szeredi } 37324c20305SMiklos Szeredi 37424c20305SMiklos Szeredi /* 37524c20305SMiklos Szeredi * Puts marks and wakes up group destruction if necessary. 37624c20305SMiklos Szeredi * 37724c20305SMiklos Szeredi * Pairs with fsnotify_get_mark_safe() 37824c20305SMiklos Szeredi */ 37924c20305SMiklos Szeredi static void fsnotify_put_mark_wake(struct fsnotify_mark *mark) 38024c20305SMiklos Szeredi { 38124c20305SMiklos Szeredi if (mark) { 38224c20305SMiklos Szeredi struct fsnotify_group *group = mark->group; 38324c20305SMiklos Szeredi 38424c20305SMiklos Szeredi fsnotify_put_mark(mark); 38524c20305SMiklos Szeredi /* 38624c20305SMiklos Szeredi * We abuse notification_waitq on group shutdown for waiting for 38724c20305SMiklos Szeredi * all marks pinned when waiting for userspace. 38824c20305SMiklos Szeredi */ 38924c20305SMiklos Szeredi if (atomic_dec_and_test(&group->user_waits) && group->shutdown) 39024c20305SMiklos Szeredi wake_up(&group->notification_waitq); 39124c20305SMiklos Szeredi } 39224c20305SMiklos Szeredi } 39324c20305SMiklos Szeredi 39424c20305SMiklos Szeredi bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) 39500e0afb6SJules Irenge __releases(&fsnotify_mark_srcu) 39624c20305SMiklos Szeredi { 39747d9c7ccSAmir Goldstein int type; 39847d9c7ccSAmir Goldstein 3991c9007d6SAmir Goldstein fsnotify_foreach_iter_type(type) { 400abc77577SJan Kara /* This can fail if mark is being removed */ 40100e0afb6SJules Irenge if (!fsnotify_get_mark_safe(iter_info->marks[type])) { 40200e0afb6SJules Irenge __release(&fsnotify_mark_srcu); 40347d9c7ccSAmir Goldstein goto fail; 404abc77577SJan Kara } 40500e0afb6SJules Irenge } 406abc77577SJan Kara 407abc77577SJan Kara /* 408abc77577SJan Kara * Now that both marks are pinned by refcount in the inode / vfsmount 409abc77577SJan Kara * lists, we can drop SRCU lock, and safely resume the list iteration 410abc77577SJan Kara * once userspace returns. 411abc77577SJan Kara */ 412abc77577SJan Kara srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx); 413abc77577SJan Kara 414abc77577SJan Kara return true; 41547d9c7ccSAmir Goldstein 41647d9c7ccSAmir Goldstein fail: 41747d9c7ccSAmir Goldstein for (type--; type >= 0; type--) 41847d9c7ccSAmir Goldstein fsnotify_put_mark_wake(iter_info->marks[type]); 41947d9c7ccSAmir Goldstein return false; 420abc77577SJan Kara } 421abc77577SJan Kara 422abc77577SJan Kara void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info) 42300e0afb6SJules Irenge __acquires(&fsnotify_mark_srcu) 424abc77577SJan Kara { 42547d9c7ccSAmir Goldstein int type; 42647d9c7ccSAmir Goldstein 427abc77577SJan Kara iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); 4281c9007d6SAmir Goldstein fsnotify_foreach_iter_type(type) 42947d9c7ccSAmir Goldstein fsnotify_put_mark_wake(iter_info->marks[type]); 430abc77577SJan Kara } 431abc77577SJan Kara 4325444e298SEric Paris /* 4336b3f05d2SJan Kara * Mark mark as detached, remove it from group list. Mark still stays in object 4346b3f05d2SJan Kara * list until its last reference is dropped. Note that we rely on mark being 4356b3f05d2SJan Kara * removed from group list before corresponding reference to it is dropped. In 4366b3f05d2SJan Kara * particular we rely on mark->connector being valid while we hold 4376b3f05d2SJan Kara * group->mark_mutex if we found the mark through g_list. 4384712e722SJan Kara * 43911375145SJan Kara * Must be called with group->mark_mutex held. The caller must either hold 44011375145SJan Kara * reference to the mark or be protected by fsnotify_mark_srcu. 4415444e298SEric Paris */ 4424712e722SJan Kara void fsnotify_detach_mark(struct fsnotify_mark *mark) 4435444e298SEric Paris { 44443b245a7SAmir Goldstein fsnotify_group_assert_locked(mark->group); 44511375145SJan Kara WARN_ON_ONCE(!srcu_read_lock_held(&fsnotify_mark_srcu) && 446ab97f873SElena Reshetova refcount_read(&mark->refcnt) < 1 + 44711375145SJan Kara !!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)); 448d5a335b8SLino Sanfilippo 449104d06f0SLino Sanfilippo spin_lock(&mark->lock); 450700307a2SEric Paris /* something else already called this function on this mark */ 4514712e722SJan Kara if (!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { 4525444e298SEric Paris spin_unlock(&mark->lock); 453e2a29943SLino Sanfilippo return; 4545444e298SEric Paris } 4554712e722SJan Kara mark->flags &= ~FSNOTIFY_MARK_FLAG_ATTACHED; 4565444e298SEric Paris list_del_init(&mark->g_list); 4575444e298SEric Paris spin_unlock(&mark->lock); 458d5a335b8SLino Sanfilippo 45911375145SJan Kara /* Drop mark reference acquired in fsnotify_add_mark_locked() */ 46011375145SJan Kara fsnotify_put_mark(mark); 4614712e722SJan Kara } 4624712e722SJan Kara 4634712e722SJan Kara /* 46411375145SJan Kara * Free fsnotify mark. The mark is actually only marked as being freed. The 46511375145SJan Kara * freeing is actually happening only once last reference to the mark is 46611375145SJan Kara * dropped from a workqueue which first waits for srcu period end. 46735e48176SJan Kara * 46811375145SJan Kara * Caller must have a reference to the mark or be protected by 46911375145SJan Kara * fsnotify_mark_srcu. 4704712e722SJan Kara */ 47111375145SJan Kara void fsnotify_free_mark(struct fsnotify_mark *mark) 4724712e722SJan Kara { 4734712e722SJan Kara struct fsnotify_group *group = mark->group; 4744712e722SJan Kara 4754712e722SJan Kara spin_lock(&mark->lock); 4764712e722SJan Kara /* something else already called this function on this mark */ 4774712e722SJan Kara if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) { 4784712e722SJan Kara spin_unlock(&mark->lock); 47911375145SJan Kara return; 4804712e722SJan Kara } 4814712e722SJan Kara mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; 4824712e722SJan Kara spin_unlock(&mark->lock); 4835444e298SEric Paris 484d725e66cSLinus Torvalds /* 485d725e66cSLinus Torvalds * Some groups like to know that marks are being freed. This is a 486d725e66cSLinus Torvalds * callback to the group function to let it know that this mark 487d725e66cSLinus Torvalds * is being freed. 488d725e66cSLinus Torvalds */ 489d725e66cSLinus Torvalds if (group->ops->freeing_mark) 490d725e66cSLinus Torvalds group->ops->freeing_mark(mark, group); 491d5a335b8SLino Sanfilippo } 492d5a335b8SLino Sanfilippo 493d5a335b8SLino Sanfilippo void fsnotify_destroy_mark(struct fsnotify_mark *mark, 494d5a335b8SLino Sanfilippo struct fsnotify_group *group) 495d5a335b8SLino Sanfilippo { 49643b245a7SAmir Goldstein fsnotify_group_lock(group); 4974712e722SJan Kara fsnotify_detach_mark(mark); 49843b245a7SAmir Goldstein fsnotify_group_unlock(group); 4994712e722SJan Kara fsnotify_free_mark(mark); 5005444e298SEric Paris } 501b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_destroy_mark); 5025444e298SEric Paris 5035444e298SEric Paris /* 5048edc6e16SJan Kara * Sorting function for lists of fsnotify marks. 5058edc6e16SJan Kara * 5068edc6e16SJan Kara * Fanotify supports different notification classes (reflected as priority of 5078edc6e16SJan Kara * notification group). Events shall be passed to notification groups in 5088edc6e16SJan Kara * decreasing priority order. To achieve this marks in notification lists for 5098edc6e16SJan Kara * inodes and vfsmounts are sorted so that priorities of corresponding groups 5108edc6e16SJan Kara * are descending. 5118edc6e16SJan Kara * 5128edc6e16SJan Kara * Furthermore correct handling of the ignore mask requires processing inode 5138edc6e16SJan Kara * and vfsmount marks of each group together. Using the group address as 5148edc6e16SJan Kara * further sort criterion provides a unique sorting order and thus we can 5158edc6e16SJan Kara * merge inode and vfsmount lists of marks in linear time and find groups 5168edc6e16SJan Kara * present in both lists. 5178edc6e16SJan Kara * 5188edc6e16SJan Kara * A return value of 1 signifies that b has priority over a. 5198edc6e16SJan Kara * A return value of 0 signifies that the two marks have to be handled together. 5208edc6e16SJan Kara * A return value of -1 signifies that a has priority over b. 5218edc6e16SJan Kara */ 5228edc6e16SJan Kara int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b) 5238edc6e16SJan Kara { 5248edc6e16SJan Kara if (a == b) 5258edc6e16SJan Kara return 0; 5268edc6e16SJan Kara if (!a) 5278edc6e16SJan Kara return 1; 5288edc6e16SJan Kara if (!b) 5298edc6e16SJan Kara return -1; 5308edc6e16SJan Kara if (a->priority < b->priority) 5318edc6e16SJan Kara return 1; 5328edc6e16SJan Kara if (a->priority > b->priority) 5338edc6e16SJan Kara return -1; 5348edc6e16SJan Kara if (a < b) 5358edc6e16SJan Kara return 1; 5368edc6e16SJan Kara return -1; 5378edc6e16SJan Kara } 5388edc6e16SJan Kara 5399b6e5434SAmir Goldstein static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp, 540*7232522eSAmir Goldstein unsigned int obj_type) 5419dd813c1SJan Kara { 5429dd813c1SJan Kara struct fsnotify_mark_connector *conn; 5439dd813c1SJan Kara 544755b5bc6SJan Kara conn = kmem_cache_alloc(fsnotify_mark_connector_cachep, GFP_KERNEL); 5459dd813c1SJan Kara if (!conn) 5469dd813c1SJan Kara return -ENOMEM; 54704662cabSJan Kara spin_lock_init(&conn->lock); 5489dd813c1SJan Kara INIT_HLIST_HEAD(&conn->list); 549c3638b5bSAmir Goldstein conn->flags = 0; 550ad69cd99SAmir Goldstein conn->type = obj_type; 55136f10f55SAmir Goldstein conn->obj = connp; 552c285a2f0SAmir Goldstein conn->flags = 0; 553ec44610fSAmir Goldstein fsnotify_get_sb_connectors(conn); 55409ddbe69SAmir Goldstein 5559dd813c1SJan Kara /* 55604662cabSJan Kara * cmpxchg() provides the barrier so that readers of *connp can see 55704662cabSJan Kara * only initialized structure 5589dd813c1SJan Kara */ 55904662cabSJan Kara if (cmpxchg(connp, NULL, conn)) { 56004662cabSJan Kara /* Someone else created list structure for us */ 5614396a731SAmir Goldstein fsnotify_put_sb_connectors(conn); 562755b5bc6SJan Kara kmem_cache_free(fsnotify_mark_connector_cachep, conn); 56304662cabSJan Kara } 5649dd813c1SJan Kara 5659dd813c1SJan Kara return 0; 5669dd813c1SJan Kara } 5679dd813c1SJan Kara 5689dd813c1SJan Kara /* 56908991e83SJan Kara * Get mark connector, make sure it is alive and return with its lock held. 57008991e83SJan Kara * This is for users that get connector pointer from inode or mount. Users that 57108991e83SJan Kara * hold reference to a mark on the list may directly lock connector->lock as 57208991e83SJan Kara * they are sure list cannot go away under them. 57308991e83SJan Kara */ 57408991e83SJan Kara static struct fsnotify_mark_connector *fsnotify_grab_connector( 5759b6e5434SAmir Goldstein fsnotify_connp_t *connp) 57608991e83SJan Kara { 57708991e83SJan Kara struct fsnotify_mark_connector *conn; 57808991e83SJan Kara int idx; 57908991e83SJan Kara 58008991e83SJan Kara idx = srcu_read_lock(&fsnotify_mark_srcu); 58108991e83SJan Kara conn = srcu_dereference(*connp, &fsnotify_mark_srcu); 58208991e83SJan Kara if (!conn) 58308991e83SJan Kara goto out; 58408991e83SJan Kara spin_lock(&conn->lock); 585d6f7b98bSAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) { 58608991e83SJan Kara spin_unlock(&conn->lock); 58708991e83SJan Kara srcu_read_unlock(&fsnotify_mark_srcu, idx); 58808991e83SJan Kara return NULL; 58908991e83SJan Kara } 59008991e83SJan Kara out: 59108991e83SJan Kara srcu_read_unlock(&fsnotify_mark_srcu, idx); 59208991e83SJan Kara return conn; 59308991e83SJan Kara } 59408991e83SJan Kara 59508991e83SJan Kara /* 5969dd813c1SJan Kara * Add mark into proper place in given list of marks. These marks may be used 5979dd813c1SJan Kara * for the fsnotify backend to determine which event types should be delivered 5989dd813c1SJan Kara * to which group and for which inodes. These marks are ordered according to 5999dd813c1SJan Kara * priority, highest number first, and then by the group's location in memory. 6009dd813c1SJan Kara */ 601755b5bc6SJan Kara static int fsnotify_add_mark_list(struct fsnotify_mark *mark, 602ad69cd99SAmir Goldstein fsnotify_connp_t *connp, 603*7232522eSAmir Goldstein unsigned int obj_type, int add_flags) 6040809ab69SJan Kara { 6050809ab69SJan Kara struct fsnotify_mark *lmark, *last = NULL; 6069dd813c1SJan Kara struct fsnotify_mark_connector *conn; 6070809ab69SJan Kara int cmp; 608755b5bc6SJan Kara int err = 0; 609755b5bc6SJan Kara 610ad69cd99SAmir Goldstein if (WARN_ON(!fsnotify_valid_obj_type(obj_type))) 611755b5bc6SJan Kara return -EINVAL; 61277115225SAmir Goldstein 61308991e83SJan Kara restart: 61408991e83SJan Kara spin_lock(&mark->lock); 61508991e83SJan Kara conn = fsnotify_grab_connector(connp); 61608991e83SJan Kara if (!conn) { 61708991e83SJan Kara spin_unlock(&mark->lock); 618*7232522eSAmir Goldstein err = fsnotify_attach_connector_to_object(connp, obj_type); 6199dd813c1SJan Kara if (err) 6209dd813c1SJan Kara return err; 62108991e83SJan Kara goto restart; 6229dd813c1SJan Kara } 6230809ab69SJan Kara 6240809ab69SJan Kara /* is mark the first mark? */ 6259dd813c1SJan Kara if (hlist_empty(&conn->list)) { 6269dd813c1SJan Kara hlist_add_head_rcu(&mark->obj_list, &conn->list); 62786ffe245SJan Kara goto added; 6280809ab69SJan Kara } 6290809ab69SJan Kara 6300809ab69SJan Kara /* should mark be in the middle of the current list? */ 6319dd813c1SJan Kara hlist_for_each_entry(lmark, &conn->list, obj_list) { 6320809ab69SJan Kara last = lmark; 6330809ab69SJan Kara 6346b3f05d2SJan Kara if ((lmark->group == mark->group) && 6356b3f05d2SJan Kara (lmark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) && 636f3010343SAmir Goldstein !(mark->group->flags & FSNOTIFY_GROUP_DUPS)) { 637755b5bc6SJan Kara err = -EEXIST; 638755b5bc6SJan Kara goto out_err; 639755b5bc6SJan Kara } 6400809ab69SJan Kara 6410809ab69SJan Kara cmp = fsnotify_compare_groups(lmark->group, mark->group); 6420809ab69SJan Kara if (cmp >= 0) { 6430809ab69SJan Kara hlist_add_before_rcu(&mark->obj_list, &lmark->obj_list); 64486ffe245SJan Kara goto added; 6450809ab69SJan Kara } 6460809ab69SJan Kara } 6470809ab69SJan Kara 6480809ab69SJan Kara BUG_ON(last == NULL); 6490809ab69SJan Kara /* mark should be the last entry. last is the current last entry */ 6500809ab69SJan Kara hlist_add_behind_rcu(&mark->obj_list, &last->obj_list); 65186ffe245SJan Kara added: 65211a6f8e2SJan Kara /* 65311a6f8e2SJan Kara * Since connector is attached to object using cmpxchg() we are 65411a6f8e2SJan Kara * guaranteed that connector initialization is fully visible by anyone 65511a6f8e2SJan Kara * seeing mark->connector set. 65611a6f8e2SJan Kara */ 657b1da6a51SJan Kara WRITE_ONCE(mark->connector, conn); 658755b5bc6SJan Kara out_err: 65904662cabSJan Kara spin_unlock(&conn->lock); 660755b5bc6SJan Kara spin_unlock(&mark->lock); 661755b5bc6SJan Kara return err; 6620809ab69SJan Kara } 6630809ab69SJan Kara 6648edc6e16SJan Kara /* 6655444e298SEric Paris * Attach an initialized mark to a given group and fs object. 6665444e298SEric Paris * These marks may be used for the fsnotify backend to determine which 6675444e298SEric Paris * event types should be delivered to which group. 6685444e298SEric Paris */ 669b812a9f5SAmir Goldstein int fsnotify_add_mark_locked(struct fsnotify_mark *mark, 670ad69cd99SAmir Goldstein fsnotify_connp_t *connp, unsigned int obj_type, 671*7232522eSAmir Goldstein int add_flags) 6725444e298SEric Paris { 6737b129323SJan Kara struct fsnotify_group *group = mark->group; 6745444e298SEric Paris int ret = 0; 6755444e298SEric Paris 67643b245a7SAmir Goldstein fsnotify_group_assert_locked(group); 6775444e298SEric Paris 6785444e298SEric Paris /* 6795444e298SEric Paris * LOCKING ORDER!!!! 680986ab098SLino Sanfilippo * group->mark_mutex 681104d06f0SLino Sanfilippo * mark->lock 68204662cabSJan Kara * mark->connector->lock 6835444e298SEric Paris */ 684104d06f0SLino Sanfilippo spin_lock(&mark->lock); 6854712e722SJan Kara mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE | FSNOTIFY_MARK_FLAG_ATTACHED; 686700307a2SEric Paris 6875444e298SEric Paris list_add(&mark->g_list, &group->marks_list); 6886b3f05d2SJan Kara fsnotify_get_mark(mark); /* for g_list */ 6895444e298SEric Paris spin_unlock(&mark->lock); 6905444e298SEric Paris 691*7232522eSAmir Goldstein ret = fsnotify_add_mark_list(mark, connp, obj_type, add_flags); 692755b5bc6SJan Kara if (ret) 693755b5bc6SJan Kara goto err; 694755b5bc6SJan Kara 695a242677bSJan Kara fsnotify_recalc_mask(mark->connector); 6965444e298SEric Paris 6975444e298SEric Paris return ret; 6985444e298SEric Paris err: 6999cf90cefSJan Kara spin_lock(&mark->lock); 70011375145SJan Kara mark->flags &= ~(FSNOTIFY_MARK_FLAG_ALIVE | 70111375145SJan Kara FSNOTIFY_MARK_FLAG_ATTACHED); 7025444e298SEric Paris list_del_init(&mark->g_list); 7039cf90cefSJan Kara spin_unlock(&mark->lock); 7045444e298SEric Paris 70511375145SJan Kara fsnotify_put_mark(mark); 7065444e298SEric Paris return ret; 7075444e298SEric Paris } 7085444e298SEric Paris 709b812a9f5SAmir Goldstein int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp, 710*7232522eSAmir Goldstein unsigned int obj_type, int add_flags) 711d5a335b8SLino Sanfilippo { 712d5a335b8SLino Sanfilippo int ret; 7137b129323SJan Kara struct fsnotify_group *group = mark->group; 7147b129323SJan Kara 71543b245a7SAmir Goldstein fsnotify_group_lock(group); 716*7232522eSAmir Goldstein ret = fsnotify_add_mark_locked(mark, connp, obj_type, add_flags); 71743b245a7SAmir Goldstein fsnotify_group_unlock(group); 718d5a335b8SLino Sanfilippo return ret; 719d5a335b8SLino Sanfilippo } 720b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_add_mark); 721d5a335b8SLino Sanfilippo 7225444e298SEric Paris /* 7230809ab69SJan Kara * Given a list of marks, find the mark associated with given group. If found 7240809ab69SJan Kara * take a reference to that mark and return it, else return NULL. 7250809ab69SJan Kara */ 7269b6e5434SAmir Goldstein struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp, 7270809ab69SJan Kara struct fsnotify_group *group) 7280809ab69SJan Kara { 72908991e83SJan Kara struct fsnotify_mark_connector *conn; 7300809ab69SJan Kara struct fsnotify_mark *mark; 7310809ab69SJan Kara 73208991e83SJan Kara conn = fsnotify_grab_connector(connp); 7339dd813c1SJan Kara if (!conn) 7349dd813c1SJan Kara return NULL; 7359dd813c1SJan Kara 7369dd813c1SJan Kara hlist_for_each_entry(mark, &conn->list, obj_list) { 7376b3f05d2SJan Kara if (mark->group == group && 7386b3f05d2SJan Kara (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { 7390809ab69SJan Kara fsnotify_get_mark(mark); 74004662cabSJan Kara spin_unlock(&conn->lock); 7410809ab69SJan Kara return mark; 7420809ab69SJan Kara } 7430809ab69SJan Kara } 74404662cabSJan Kara spin_unlock(&conn->lock); 7450809ab69SJan Kara return NULL; 7460809ab69SJan Kara } 747b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_find_mark); 7480809ab69SJan Kara 749d6f7b98bSAmir Goldstein /* Clear any marks in a group with given type mask */ 75018f2e0d3SJan Kara void fsnotify_clear_marks_by_group(struct fsnotify_group *group, 751ad69cd99SAmir Goldstein unsigned int obj_type) 7525444e298SEric Paris { 7535444e298SEric Paris struct fsnotify_mark *lmark, *mark; 7548f2f3eb5SJan Kara LIST_HEAD(to_free); 7552e37c6caSJan Kara struct list_head *head = &to_free; 7565444e298SEric Paris 7572e37c6caSJan Kara /* Skip selection step if we want to clear all marks. */ 758ad69cd99SAmir Goldstein if (obj_type == FSNOTIFY_OBJ_TYPE_ANY) { 7592e37c6caSJan Kara head = &group->marks_list; 7602e37c6caSJan Kara goto clear; 7612e37c6caSJan Kara } 7628f2f3eb5SJan Kara /* 7638f2f3eb5SJan Kara * We have to be really careful here. Anytime we drop mark_mutex, e.g. 7648f2f3eb5SJan Kara * fsnotify_clear_marks_by_inode() can come and free marks. Even in our 7658f2f3eb5SJan Kara * to_free list so we have to use mark_mutex even when accessing that 7668f2f3eb5SJan Kara * list. And freeing mark requires us to drop mark_mutex. So we can 7678f2f3eb5SJan Kara * reliably free only the first mark in the list. That's why we first 7688f2f3eb5SJan Kara * move marks to free to to_free list in one go and then free marks in 7698f2f3eb5SJan Kara * to_free list one by one. 7708f2f3eb5SJan Kara */ 77143b245a7SAmir Goldstein fsnotify_group_lock(group); 7725444e298SEric Paris list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { 773ad69cd99SAmir Goldstein if (mark->connector->type == obj_type) 7748f2f3eb5SJan Kara list_move(&mark->g_list, &to_free); 7754d92604cSEric Paris } 77643b245a7SAmir Goldstein fsnotify_group_unlock(group); 7778f2f3eb5SJan Kara 7782e37c6caSJan Kara clear: 7798f2f3eb5SJan Kara while (1) { 78043b245a7SAmir Goldstein fsnotify_group_lock(group); 7812e37c6caSJan Kara if (list_empty(head)) { 78243b245a7SAmir Goldstein fsnotify_group_unlock(group); 7838f2f3eb5SJan Kara break; 7848f2f3eb5SJan Kara } 7852e37c6caSJan Kara mark = list_first_entry(head, struct fsnotify_mark, g_list); 7868f2f3eb5SJan Kara fsnotify_get_mark(mark); 7874712e722SJan Kara fsnotify_detach_mark(mark); 78843b245a7SAmir Goldstein fsnotify_group_unlock(group); 7894712e722SJan Kara fsnotify_free_mark(mark); 7908f2f3eb5SJan Kara fsnotify_put_mark(mark); 7918f2f3eb5SJan Kara } 7925444e298SEric Paris } 7935444e298SEric Paris 7949b6e5434SAmir Goldstein /* Destroy all marks attached to an object via connector */ 7959b6e5434SAmir Goldstein void fsnotify_destroy_marks(fsnotify_connp_t *connp) 7960810b4f9SJan Kara { 79708991e83SJan Kara struct fsnotify_mark_connector *conn; 7986b3f05d2SJan Kara struct fsnotify_mark *mark, *old_mark = NULL; 799721fb6fbSJan Kara void *objp; 800721fb6fbSJan Kara unsigned int type; 8010810b4f9SJan Kara 8026b3f05d2SJan Kara conn = fsnotify_grab_connector(connp); 8036b3f05d2SJan Kara if (!conn) 8046b3f05d2SJan Kara return; 8050810b4f9SJan Kara /* 8060810b4f9SJan Kara * We have to be careful since we can race with e.g. 8076b3f05d2SJan Kara * fsnotify_clear_marks_by_group() and once we drop the conn->lock, the 8086b3f05d2SJan Kara * list can get modified. However we are holding mark reference and 8096b3f05d2SJan Kara * thus our mark cannot be removed from obj_list so we can continue 8106b3f05d2SJan Kara * iteration after regaining conn->lock. 8110810b4f9SJan Kara */ 8126b3f05d2SJan Kara hlist_for_each_entry(mark, &conn->list, obj_list) { 8130810b4f9SJan Kara fsnotify_get_mark(mark); 81404662cabSJan Kara spin_unlock(&conn->lock); 8156b3f05d2SJan Kara if (old_mark) 8166b3f05d2SJan Kara fsnotify_put_mark(old_mark); 8176b3f05d2SJan Kara old_mark = mark; 8180810b4f9SJan Kara fsnotify_destroy_mark(mark, mark->group); 8196b3f05d2SJan Kara spin_lock(&conn->lock); 8200810b4f9SJan Kara } 8216b3f05d2SJan Kara /* 8226b3f05d2SJan Kara * Detach list from object now so that we don't pin inode until all 8236b3f05d2SJan Kara * mark references get dropped. It would lead to strange results such 8246b3f05d2SJan Kara * as delaying inode deletion or blocking unmount. 8256b3f05d2SJan Kara */ 826721fb6fbSJan Kara objp = fsnotify_detach_connector_from_object(conn, &type); 8276b3f05d2SJan Kara spin_unlock(&conn->lock); 8286b3f05d2SJan Kara if (old_mark) 8296b3f05d2SJan Kara fsnotify_put_mark(old_mark); 830721fb6fbSJan Kara fsnotify_drop_object(type, objp); 8310810b4f9SJan Kara } 8320810b4f9SJan Kara 8335444e298SEric Paris /* 8345444e298SEric Paris * Nothing fancy, just initialize lists and locks and counters. 8355444e298SEric Paris */ 8365444e298SEric Paris void fsnotify_init_mark(struct fsnotify_mark *mark, 837054c636eSJan Kara struct fsnotify_group *group) 8385444e298SEric Paris { 839ba643f04SEric Paris memset(mark, 0, sizeof(*mark)); 8405444e298SEric Paris spin_lock_init(&mark->lock); 841ab97f873SElena Reshetova refcount_set(&mark->refcnt, 1); 8427b129323SJan Kara fsnotify_get_group(group); 8437b129323SJan Kara mark->group = group; 844b1da6a51SJan Kara WRITE_ONCE(mark->connector, NULL); 8455444e298SEric Paris } 846b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_init_mark); 84713d34ac6SJeff Layton 84835e48176SJan Kara /* 84935e48176SJan Kara * Destroy all marks in destroy_list, waits for SRCU period to finish before 85035e48176SJan Kara * actually freeing marks. 85135e48176SJan Kara */ 852f09b04a0SJan Kara static void fsnotify_mark_destroy_workfn(struct work_struct *work) 85313d34ac6SJeff Layton { 85413d34ac6SJeff Layton struct fsnotify_mark *mark, *next; 85513d34ac6SJeff Layton struct list_head private_destroy_list; 85613d34ac6SJeff Layton 85713d34ac6SJeff Layton spin_lock(&destroy_lock); 85813d34ac6SJeff Layton /* exchange the list head */ 85913d34ac6SJeff Layton list_replace_init(&destroy_list, &private_destroy_list); 86013d34ac6SJeff Layton spin_unlock(&destroy_lock); 86113d34ac6SJeff Layton 86213d34ac6SJeff Layton synchronize_srcu(&fsnotify_mark_srcu); 86313d34ac6SJeff Layton 86413d34ac6SJeff Layton list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) { 86513d34ac6SJeff Layton list_del_init(&mark->g_list); 8666b3f05d2SJan Kara fsnotify_final_mark_destroy(mark); 86713d34ac6SJeff Layton } 86813d34ac6SJeff Layton } 86935e48176SJan Kara 870f09b04a0SJan Kara /* Wait for all marks queued for destruction to be actually destroyed */ 871f09b04a0SJan Kara void fsnotify_wait_marks_destroyed(void) 87235e48176SJan Kara { 873f09b04a0SJan Kara flush_delayed_work(&reaper_work); 87435e48176SJan Kara } 875b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_wait_marks_destroyed); 876