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 119a242677bSJan Kara static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) 1200809ab69SJan Kara { 1210809ab69SJan Kara u32 new_mask = 0; 1220809ab69SJan Kara struct fsnotify_mark *mark; 1230809ab69SJan Kara 12404662cabSJan Kara assert_spin_locked(&conn->lock); 125d3bc0fa8SJan Kara /* We can get detached connector here when inode is getting unlinked. */ 126d3bc0fa8SJan Kara if (!fsnotify_valid_obj_type(conn->type)) 127d3bc0fa8SJan Kara return; 1286b3f05d2SJan Kara hlist_for_each_entry(mark, &conn->list, obj_list) { 1296b3f05d2SJan Kara if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) 1300809ab69SJan Kara new_mask |= mark->mask; 1316b3f05d2SJan Kara } 1323ac70bfcSAmir Goldstein *fsnotify_conn_mask_p(conn) = new_mask; 133a242677bSJan Kara } 134a242677bSJan Kara 135a242677bSJan Kara /* 136a242677bSJan Kara * Calculate mask of events for a list of marks. The caller must make sure 13736f10f55SAmir Goldstein * connector and connector->obj cannot disappear under us. Callers achieve 1386b3f05d2SJan Kara * this by holding a mark->lock or mark->group->mark_mutex for a mark on this 1396b3f05d2SJan Kara * list. 140a242677bSJan Kara */ 141a242677bSJan Kara void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) 142a242677bSJan Kara { 143a242677bSJan Kara if (!conn) 144a242677bSJan Kara return; 145a242677bSJan Kara 14604662cabSJan Kara spin_lock(&conn->lock); 147a242677bSJan Kara __fsnotify_recalc_mask(conn); 14804662cabSJan Kara spin_unlock(&conn->lock); 149d6f7b98bSAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) 15036f10f55SAmir Goldstein __fsnotify_update_child_dentry_flags( 15136f10f55SAmir Goldstein fsnotify_conn_inode(conn)); 1520809ab69SJan Kara } 1530809ab69SJan Kara 15408991e83SJan Kara /* Free all connectors queued for freeing once SRCU period ends */ 15508991e83SJan Kara static void fsnotify_connector_destroy_workfn(struct work_struct *work) 15608991e83SJan Kara { 15708991e83SJan Kara struct fsnotify_mark_connector *conn, *free; 15808991e83SJan Kara 15908991e83SJan Kara spin_lock(&destroy_lock); 16008991e83SJan Kara conn = connector_destroy_list; 16108991e83SJan Kara connector_destroy_list = NULL; 16208991e83SJan Kara spin_unlock(&destroy_lock); 16308991e83SJan Kara 16408991e83SJan Kara synchronize_srcu(&fsnotify_mark_srcu); 16508991e83SJan Kara while (conn) { 16608991e83SJan Kara free = conn; 16708991e83SJan Kara conn = conn->destroy_next; 16808991e83SJan Kara kmem_cache_free(fsnotify_mark_connector_cachep, free); 16908991e83SJan Kara } 17008991e83SJan Kara } 17108991e83SJan Kara 17211fa333bSAmir Goldstein static void fsnotify_get_inode_ref(struct inode *inode) 17311fa333bSAmir Goldstein { 17411fa333bSAmir Goldstein ihold(inode); 175ec44610fSAmir Goldstein atomic_long_inc(&inode->i_sb->s_fsnotify_connectors); 17611fa333bSAmir Goldstein } 17711fa333bSAmir Goldstein 17811fa333bSAmir Goldstein static void fsnotify_put_inode_ref(struct inode *inode) 17911fa333bSAmir Goldstein { 18011fa333bSAmir Goldstein struct super_block *sb = inode->i_sb; 18111fa333bSAmir Goldstein 18211fa333bSAmir Goldstein iput(inode); 183ec44610fSAmir Goldstein if (atomic_long_dec_and_test(&sb->s_fsnotify_connectors)) 184ec44610fSAmir Goldstein wake_up_var(&sb->s_fsnotify_connectors); 185ec44610fSAmir Goldstein } 186ec44610fSAmir Goldstein 187ec44610fSAmir Goldstein static void fsnotify_get_sb_connectors(struct fsnotify_mark_connector *conn) 188ec44610fSAmir Goldstein { 189ec44610fSAmir Goldstein struct super_block *sb = fsnotify_connector_sb(conn); 190ec44610fSAmir Goldstein 191ec44610fSAmir Goldstein if (sb) 192ec44610fSAmir Goldstein atomic_long_inc(&sb->s_fsnotify_connectors); 193ec44610fSAmir Goldstein } 194ec44610fSAmir Goldstein 195ec44610fSAmir Goldstein static void fsnotify_put_sb_connectors(struct fsnotify_mark_connector *conn) 196ec44610fSAmir Goldstein { 197ec44610fSAmir Goldstein struct super_block *sb = fsnotify_connector_sb(conn); 198ec44610fSAmir Goldstein 199ec44610fSAmir Goldstein if (sb && atomic_long_dec_and_test(&sb->s_fsnotify_connectors)) 200ec44610fSAmir Goldstein wake_up_var(&sb->s_fsnotify_connectors); 20111fa333bSAmir Goldstein } 20211fa333bSAmir Goldstein 203721fb6fbSJan Kara static void *fsnotify_detach_connector_from_object( 204721fb6fbSJan Kara struct fsnotify_mark_connector *conn, 205721fb6fbSJan Kara unsigned int *type) 20608991e83SJan Kara { 20708991e83SJan Kara struct inode *inode = NULL; 20808991e83SJan Kara 209721fb6fbSJan Kara *type = conn->type; 21036f10f55SAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) 21136f10f55SAmir Goldstein return NULL; 21236f10f55SAmir Goldstein 213d6f7b98bSAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) { 21436f10f55SAmir Goldstein inode = fsnotify_conn_inode(conn); 21508991e83SJan Kara inode->i_fsnotify_mask = 0; 216d6f7b98bSAmir Goldstein } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) { 21736f10f55SAmir Goldstein fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0; 2181e6cb723SAmir Goldstein } else if (conn->type == FSNOTIFY_OBJ_TYPE_SB) { 2191e6cb723SAmir Goldstein fsnotify_conn_sb(conn)->s_fsnotify_mask = 0; 22008991e83SJan Kara } 22108991e83SJan Kara 222ec44610fSAmir Goldstein fsnotify_put_sb_connectors(conn); 22336f10f55SAmir Goldstein rcu_assign_pointer(*(conn->obj), NULL); 22436f10f55SAmir Goldstein conn->obj = NULL; 22536f10f55SAmir Goldstein conn->type = FSNOTIFY_OBJ_TYPE_DETACHED; 22636f10f55SAmir Goldstein 22708991e83SJan Kara return inode; 22808991e83SJan Kara } 22908991e83SJan Kara 2306b3f05d2SJan Kara static void fsnotify_final_mark_destroy(struct fsnotify_mark *mark) 2316b3f05d2SJan Kara { 232054c636eSJan Kara struct fsnotify_group *group = mark->group; 233054c636eSJan Kara 234054c636eSJan Kara if (WARN_ON_ONCE(!group)) 235054c636eSJan Kara return; 236054c636eSJan Kara group->ops->free_mark(mark); 237054c636eSJan Kara fsnotify_put_group(group); 2386b3f05d2SJan Kara } 2396b3f05d2SJan Kara 240721fb6fbSJan Kara /* Drop object reference originally held by a connector */ 241721fb6fbSJan Kara static void fsnotify_drop_object(unsigned int type, void *objp) 242721fb6fbSJan Kara { 243721fb6fbSJan Kara if (!objp) 244721fb6fbSJan Kara return; 245721fb6fbSJan Kara /* Currently only inode references are passed to be dropped */ 246721fb6fbSJan Kara if (WARN_ON_ONCE(type != FSNOTIFY_OBJ_TYPE_INODE)) 247721fb6fbSJan Kara return; 24811fa333bSAmir Goldstein fsnotify_put_inode_ref(objp); 249721fb6fbSJan Kara } 250721fb6fbSJan Kara 2516b3f05d2SJan Kara void fsnotify_put_mark(struct fsnotify_mark *mark) 2528212a609SJan Kara { 253b1da6a51SJan Kara struct fsnotify_mark_connector *conn = READ_ONCE(mark->connector); 254721fb6fbSJan Kara void *objp = NULL; 255721fb6fbSJan Kara unsigned int type = FSNOTIFY_OBJ_TYPE_DETACHED; 25608991e83SJan Kara bool free_conn = false; 2578212a609SJan Kara 2586b3f05d2SJan Kara /* Catch marks that were actually never attached to object */ 259b1da6a51SJan Kara if (!conn) { 260ab97f873SElena Reshetova if (refcount_dec_and_test(&mark->refcnt)) 2616b3f05d2SJan Kara fsnotify_final_mark_destroy(mark); 2626b3f05d2SJan Kara return; 2636b3f05d2SJan Kara } 2646b3f05d2SJan Kara 2656b3f05d2SJan Kara /* 2666b3f05d2SJan Kara * We have to be careful so that traversals of obj_list under lock can 2676b3f05d2SJan Kara * safely grab mark reference. 2686b3f05d2SJan Kara */ 269b1da6a51SJan Kara if (!refcount_dec_and_lock(&mark->refcnt, &conn->lock)) 2706b3f05d2SJan Kara return; 2716b3f05d2SJan Kara 2728212a609SJan Kara hlist_del_init_rcu(&mark->obj_list); 2738212a609SJan Kara if (hlist_empty(&conn->list)) { 274721fb6fbSJan Kara objp = fsnotify_detach_connector_from_object(conn, &type); 27508991e83SJan Kara free_conn = true; 27608991e83SJan Kara } else { 27773cd3c33SJan Kara __fsnotify_recalc_mask(conn); 27808991e83SJan Kara } 279b1da6a51SJan Kara WRITE_ONCE(mark->connector, NULL); 28004662cabSJan Kara spin_unlock(&conn->lock); 2818212a609SJan Kara 282721fb6fbSJan Kara fsnotify_drop_object(type, objp); 2836b3f05d2SJan Kara 28408991e83SJan Kara if (free_conn) { 28508991e83SJan Kara spin_lock(&destroy_lock); 28608991e83SJan Kara conn->destroy_next = connector_destroy_list; 28708991e83SJan Kara connector_destroy_list = conn; 28808991e83SJan Kara spin_unlock(&destroy_lock); 28908991e83SJan Kara queue_work(system_unbound_wq, &connector_reaper_work); 29008991e83SJan Kara } 2916b3f05d2SJan Kara /* 2926b3f05d2SJan Kara * Note that we didn't update flags telling whether inode cares about 2936b3f05d2SJan Kara * what's happening with children. We update these flags from 2946b3f05d2SJan Kara * __fsnotify_parent() lazily when next event happens on one of our 2956b3f05d2SJan Kara * children. 2966b3f05d2SJan Kara */ 2976b3f05d2SJan Kara spin_lock(&destroy_lock); 2986b3f05d2SJan Kara list_add(&mark->g_list, &destroy_list); 2996b3f05d2SJan Kara spin_unlock(&destroy_lock); 3006b3f05d2SJan Kara queue_delayed_work(system_unbound_wq, &reaper_work, 3016b3f05d2SJan Kara FSNOTIFY_REAPER_DELAY); 3028212a609SJan Kara } 303b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_put_mark); 3048212a609SJan Kara 30524c20305SMiklos Szeredi /* 30624c20305SMiklos Szeredi * Get mark reference when we found the mark via lockless traversal of object 30724c20305SMiklos Szeredi * list. Mark can be already removed from the list by now and on its way to be 30824c20305SMiklos Szeredi * destroyed once SRCU period ends. 30924c20305SMiklos Szeredi * 31024c20305SMiklos Szeredi * Also pin the group so it doesn't disappear under us. 31124c20305SMiklos Szeredi */ 31224c20305SMiklos Szeredi static bool fsnotify_get_mark_safe(struct fsnotify_mark *mark) 313abc77577SJan Kara { 31424c20305SMiklos Szeredi if (!mark) 31524c20305SMiklos Szeredi return true; 316abc77577SJan Kara 317ab97f873SElena Reshetova if (refcount_inc_not_zero(&mark->refcnt)) { 3189a31d7adSMiklos Szeredi spin_lock(&mark->lock); 3199a31d7adSMiklos Szeredi if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) { 3209a31d7adSMiklos Szeredi /* mark is attached, group is still alive then */ 3219a31d7adSMiklos Szeredi atomic_inc(&mark->group->user_waits); 3229a31d7adSMiklos Szeredi spin_unlock(&mark->lock); 32324c20305SMiklos Szeredi return true; 3249a31d7adSMiklos Szeredi } 3259a31d7adSMiklos Szeredi spin_unlock(&mark->lock); 3269a31d7adSMiklos Szeredi fsnotify_put_mark(mark); 3279a31d7adSMiklos Szeredi } 32824c20305SMiklos Szeredi return false; 32924c20305SMiklos Szeredi } 33024c20305SMiklos Szeredi 33124c20305SMiklos Szeredi /* 33224c20305SMiklos Szeredi * Puts marks and wakes up group destruction if necessary. 33324c20305SMiklos Szeredi * 33424c20305SMiklos Szeredi * Pairs with fsnotify_get_mark_safe() 33524c20305SMiklos Szeredi */ 33624c20305SMiklos Szeredi static void fsnotify_put_mark_wake(struct fsnotify_mark *mark) 33724c20305SMiklos Szeredi { 33824c20305SMiklos Szeredi if (mark) { 33924c20305SMiklos Szeredi struct fsnotify_group *group = mark->group; 34024c20305SMiklos Szeredi 34124c20305SMiklos Szeredi fsnotify_put_mark(mark); 34224c20305SMiklos Szeredi /* 34324c20305SMiklos Szeredi * We abuse notification_waitq on group shutdown for waiting for 34424c20305SMiklos Szeredi * all marks pinned when waiting for userspace. 34524c20305SMiklos Szeredi */ 34624c20305SMiklos Szeredi if (atomic_dec_and_test(&group->user_waits) && group->shutdown) 34724c20305SMiklos Szeredi wake_up(&group->notification_waitq); 34824c20305SMiklos Szeredi } 34924c20305SMiklos Szeredi } 35024c20305SMiklos Szeredi 35124c20305SMiklos Szeredi bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) 35200e0afb6SJules Irenge __releases(&fsnotify_mark_srcu) 35324c20305SMiklos Szeredi { 35447d9c7ccSAmir Goldstein int type; 35547d9c7ccSAmir Goldstein 356*1c9007d6SAmir Goldstein fsnotify_foreach_iter_type(type) { 357abc77577SJan Kara /* This can fail if mark is being removed */ 35800e0afb6SJules Irenge if (!fsnotify_get_mark_safe(iter_info->marks[type])) { 35900e0afb6SJules Irenge __release(&fsnotify_mark_srcu); 36047d9c7ccSAmir Goldstein goto fail; 361abc77577SJan Kara } 36200e0afb6SJules Irenge } 363abc77577SJan Kara 364abc77577SJan Kara /* 365abc77577SJan Kara * Now that both marks are pinned by refcount in the inode / vfsmount 366abc77577SJan Kara * lists, we can drop SRCU lock, and safely resume the list iteration 367abc77577SJan Kara * once userspace returns. 368abc77577SJan Kara */ 369abc77577SJan Kara srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx); 370abc77577SJan Kara 371abc77577SJan Kara return true; 37247d9c7ccSAmir Goldstein 37347d9c7ccSAmir Goldstein fail: 37447d9c7ccSAmir Goldstein for (type--; type >= 0; type--) 37547d9c7ccSAmir Goldstein fsnotify_put_mark_wake(iter_info->marks[type]); 37647d9c7ccSAmir Goldstein return false; 377abc77577SJan Kara } 378abc77577SJan Kara 379abc77577SJan Kara void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info) 38000e0afb6SJules Irenge __acquires(&fsnotify_mark_srcu) 381abc77577SJan Kara { 38247d9c7ccSAmir Goldstein int type; 38347d9c7ccSAmir Goldstein 384abc77577SJan Kara iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); 385*1c9007d6SAmir Goldstein fsnotify_foreach_iter_type(type) 38647d9c7ccSAmir Goldstein fsnotify_put_mark_wake(iter_info->marks[type]); 387abc77577SJan Kara } 388abc77577SJan Kara 3895444e298SEric Paris /* 3906b3f05d2SJan Kara * Mark mark as detached, remove it from group list. Mark still stays in object 3916b3f05d2SJan Kara * list until its last reference is dropped. Note that we rely on mark being 3926b3f05d2SJan Kara * removed from group list before corresponding reference to it is dropped. In 3936b3f05d2SJan Kara * particular we rely on mark->connector being valid while we hold 3946b3f05d2SJan Kara * group->mark_mutex if we found the mark through g_list. 3954712e722SJan Kara * 39611375145SJan Kara * Must be called with group->mark_mutex held. The caller must either hold 39711375145SJan Kara * reference to the mark or be protected by fsnotify_mark_srcu. 3985444e298SEric Paris */ 3994712e722SJan Kara void fsnotify_detach_mark(struct fsnotify_mark *mark) 4005444e298SEric Paris { 4014712e722SJan Kara struct fsnotify_group *group = mark->group; 4025444e298SEric Paris 40311375145SJan Kara WARN_ON_ONCE(!mutex_is_locked(&group->mark_mutex)); 40411375145SJan Kara WARN_ON_ONCE(!srcu_read_lock_held(&fsnotify_mark_srcu) && 405ab97f873SElena Reshetova refcount_read(&mark->refcnt) < 1 + 40611375145SJan Kara !!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)); 407d5a335b8SLino Sanfilippo 408104d06f0SLino Sanfilippo spin_lock(&mark->lock); 409700307a2SEric Paris /* something else already called this function on this mark */ 4104712e722SJan Kara if (!(mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { 4115444e298SEric Paris spin_unlock(&mark->lock); 412e2a29943SLino Sanfilippo return; 4135444e298SEric Paris } 4144712e722SJan Kara mark->flags &= ~FSNOTIFY_MARK_FLAG_ATTACHED; 4155444e298SEric Paris list_del_init(&mark->g_list); 4165444e298SEric Paris spin_unlock(&mark->lock); 417d5a335b8SLino Sanfilippo 41811375145SJan Kara /* Drop mark reference acquired in fsnotify_add_mark_locked() */ 41911375145SJan Kara fsnotify_put_mark(mark); 4204712e722SJan Kara } 4214712e722SJan Kara 4224712e722SJan Kara /* 42311375145SJan Kara * Free fsnotify mark. The mark is actually only marked as being freed. The 42411375145SJan Kara * freeing is actually happening only once last reference to the mark is 42511375145SJan Kara * dropped from a workqueue which first waits for srcu period end. 42635e48176SJan Kara * 42711375145SJan Kara * Caller must have a reference to the mark or be protected by 42811375145SJan Kara * fsnotify_mark_srcu. 4294712e722SJan Kara */ 43011375145SJan Kara void fsnotify_free_mark(struct fsnotify_mark *mark) 4314712e722SJan Kara { 4324712e722SJan Kara struct fsnotify_group *group = mark->group; 4334712e722SJan Kara 4344712e722SJan Kara spin_lock(&mark->lock); 4354712e722SJan Kara /* something else already called this function on this mark */ 4364712e722SJan Kara if (!(mark->flags & FSNOTIFY_MARK_FLAG_ALIVE)) { 4374712e722SJan Kara spin_unlock(&mark->lock); 43811375145SJan Kara return; 4394712e722SJan Kara } 4404712e722SJan Kara mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE; 4414712e722SJan Kara spin_unlock(&mark->lock); 4425444e298SEric Paris 443d725e66cSLinus Torvalds /* 444d725e66cSLinus Torvalds * Some groups like to know that marks are being freed. This is a 445d725e66cSLinus Torvalds * callback to the group function to let it know that this mark 446d725e66cSLinus Torvalds * is being freed. 447d725e66cSLinus Torvalds */ 448d725e66cSLinus Torvalds if (group->ops->freeing_mark) 449d725e66cSLinus Torvalds group->ops->freeing_mark(mark, group); 450d5a335b8SLino Sanfilippo } 451d5a335b8SLino Sanfilippo 452d5a335b8SLino Sanfilippo void fsnotify_destroy_mark(struct fsnotify_mark *mark, 453d5a335b8SLino Sanfilippo struct fsnotify_group *group) 454d5a335b8SLino Sanfilippo { 4556960b0d9SLino Sanfilippo mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); 4564712e722SJan Kara fsnotify_detach_mark(mark); 457d5a335b8SLino Sanfilippo mutex_unlock(&group->mark_mutex); 4584712e722SJan Kara fsnotify_free_mark(mark); 4595444e298SEric Paris } 460b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_destroy_mark); 4615444e298SEric Paris 4625444e298SEric Paris /* 4638edc6e16SJan Kara * Sorting function for lists of fsnotify marks. 4648edc6e16SJan Kara * 4658edc6e16SJan Kara * Fanotify supports different notification classes (reflected as priority of 4668edc6e16SJan Kara * notification group). Events shall be passed to notification groups in 4678edc6e16SJan Kara * decreasing priority order. To achieve this marks in notification lists for 4688edc6e16SJan Kara * inodes and vfsmounts are sorted so that priorities of corresponding groups 4698edc6e16SJan Kara * are descending. 4708edc6e16SJan Kara * 4718edc6e16SJan Kara * Furthermore correct handling of the ignore mask requires processing inode 4728edc6e16SJan Kara * and vfsmount marks of each group together. Using the group address as 4738edc6e16SJan Kara * further sort criterion provides a unique sorting order and thus we can 4748edc6e16SJan Kara * merge inode and vfsmount lists of marks in linear time and find groups 4758edc6e16SJan Kara * present in both lists. 4768edc6e16SJan Kara * 4778edc6e16SJan Kara * A return value of 1 signifies that b has priority over a. 4788edc6e16SJan Kara * A return value of 0 signifies that the two marks have to be handled together. 4798edc6e16SJan Kara * A return value of -1 signifies that a has priority over b. 4808edc6e16SJan Kara */ 4818edc6e16SJan Kara int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b) 4828edc6e16SJan Kara { 4838edc6e16SJan Kara if (a == b) 4848edc6e16SJan Kara return 0; 4858edc6e16SJan Kara if (!a) 4868edc6e16SJan Kara return 1; 4878edc6e16SJan Kara if (!b) 4888edc6e16SJan Kara return -1; 4898edc6e16SJan Kara if (a->priority < b->priority) 4908edc6e16SJan Kara return 1; 4918edc6e16SJan Kara if (a->priority > b->priority) 4928edc6e16SJan Kara return -1; 4938edc6e16SJan Kara if (a < b) 4948edc6e16SJan Kara return 1; 4958edc6e16SJan Kara return -1; 4968edc6e16SJan Kara } 4978edc6e16SJan Kara 4989b6e5434SAmir Goldstein static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp, 499ad69cd99SAmir Goldstein unsigned int obj_type, 50077115225SAmir Goldstein __kernel_fsid_t *fsid) 5019dd813c1SJan Kara { 502b812a9f5SAmir Goldstein struct inode *inode = NULL; 5039dd813c1SJan Kara struct fsnotify_mark_connector *conn; 5049dd813c1SJan Kara 505755b5bc6SJan Kara conn = kmem_cache_alloc(fsnotify_mark_connector_cachep, GFP_KERNEL); 5069dd813c1SJan Kara if (!conn) 5079dd813c1SJan Kara return -ENOMEM; 50804662cabSJan Kara spin_lock_init(&conn->lock); 5099dd813c1SJan Kara INIT_HLIST_HEAD(&conn->list); 510ad69cd99SAmir Goldstein conn->type = obj_type; 51136f10f55SAmir Goldstein conn->obj = connp; 51277115225SAmir Goldstein /* Cache fsid of filesystem containing the object */ 513c285a2f0SAmir Goldstein if (fsid) { 51477115225SAmir Goldstein conn->fsid = *fsid; 515c285a2f0SAmir Goldstein conn->flags = FSNOTIFY_CONN_FLAG_HAS_FSID; 516c285a2f0SAmir Goldstein } else { 51777115225SAmir Goldstein conn->fsid.val[0] = conn->fsid.val[1] = 0; 518c285a2f0SAmir Goldstein conn->flags = 0; 519c285a2f0SAmir Goldstein } 52009ddbe69SAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) { 52109ddbe69SAmir Goldstein inode = fsnotify_conn_inode(conn); 52211fa333bSAmir Goldstein fsnotify_get_inode_ref(inode); 52309ddbe69SAmir Goldstein } 524ec44610fSAmir Goldstein fsnotify_get_sb_connectors(conn); 52509ddbe69SAmir Goldstein 5269dd813c1SJan Kara /* 52704662cabSJan Kara * cmpxchg() provides the barrier so that readers of *connp can see 52804662cabSJan Kara * only initialized structure 5299dd813c1SJan Kara */ 53004662cabSJan Kara if (cmpxchg(connp, NULL, conn)) { 53104662cabSJan Kara /* Someone else created list structure for us */ 53208991e83SJan Kara if (inode) 53311fa333bSAmir Goldstein fsnotify_put_inode_ref(inode); 5344396a731SAmir Goldstein fsnotify_put_sb_connectors(conn); 535755b5bc6SJan Kara kmem_cache_free(fsnotify_mark_connector_cachep, conn); 53604662cabSJan Kara } 5379dd813c1SJan Kara 5389dd813c1SJan Kara return 0; 5399dd813c1SJan Kara } 5409dd813c1SJan Kara 5419dd813c1SJan Kara /* 54208991e83SJan Kara * Get mark connector, make sure it is alive and return with its lock held. 54308991e83SJan Kara * This is for users that get connector pointer from inode or mount. Users that 54408991e83SJan Kara * hold reference to a mark on the list may directly lock connector->lock as 54508991e83SJan Kara * they are sure list cannot go away under them. 54608991e83SJan Kara */ 54708991e83SJan Kara static struct fsnotify_mark_connector *fsnotify_grab_connector( 5489b6e5434SAmir Goldstein fsnotify_connp_t *connp) 54908991e83SJan Kara { 55008991e83SJan Kara struct fsnotify_mark_connector *conn; 55108991e83SJan Kara int idx; 55208991e83SJan Kara 55308991e83SJan Kara idx = srcu_read_lock(&fsnotify_mark_srcu); 55408991e83SJan Kara conn = srcu_dereference(*connp, &fsnotify_mark_srcu); 55508991e83SJan Kara if (!conn) 55608991e83SJan Kara goto out; 55708991e83SJan Kara spin_lock(&conn->lock); 558d6f7b98bSAmir Goldstein if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) { 55908991e83SJan Kara spin_unlock(&conn->lock); 56008991e83SJan Kara srcu_read_unlock(&fsnotify_mark_srcu, idx); 56108991e83SJan Kara return NULL; 56208991e83SJan Kara } 56308991e83SJan Kara out: 56408991e83SJan Kara srcu_read_unlock(&fsnotify_mark_srcu, idx); 56508991e83SJan Kara return conn; 56608991e83SJan Kara } 56708991e83SJan Kara 56808991e83SJan Kara /* 5699dd813c1SJan Kara * Add mark into proper place in given list of marks. These marks may be used 5709dd813c1SJan Kara * for the fsnotify backend to determine which event types should be delivered 5719dd813c1SJan Kara * to which group and for which inodes. These marks are ordered according to 5729dd813c1SJan Kara * priority, highest number first, and then by the group's location in memory. 5739dd813c1SJan Kara */ 574755b5bc6SJan Kara static int fsnotify_add_mark_list(struct fsnotify_mark *mark, 575ad69cd99SAmir Goldstein fsnotify_connp_t *connp, 576ad69cd99SAmir Goldstein unsigned int obj_type, 57777115225SAmir Goldstein int allow_dups, __kernel_fsid_t *fsid) 5780809ab69SJan Kara { 5790809ab69SJan Kara struct fsnotify_mark *lmark, *last = NULL; 5809dd813c1SJan Kara struct fsnotify_mark_connector *conn; 5810809ab69SJan Kara int cmp; 582755b5bc6SJan Kara int err = 0; 583755b5bc6SJan Kara 584ad69cd99SAmir Goldstein if (WARN_ON(!fsnotify_valid_obj_type(obj_type))) 585755b5bc6SJan Kara return -EINVAL; 58677115225SAmir Goldstein 58777115225SAmir Goldstein /* Backend is expected to check for zero fsid (e.g. tmpfs) */ 58877115225SAmir Goldstein if (fsid && WARN_ON_ONCE(!fsid->val[0] && !fsid->val[1])) 58977115225SAmir Goldstein return -ENODEV; 59077115225SAmir Goldstein 59108991e83SJan Kara restart: 59208991e83SJan Kara spin_lock(&mark->lock); 59308991e83SJan Kara conn = fsnotify_grab_connector(connp); 59408991e83SJan Kara if (!conn) { 59508991e83SJan Kara spin_unlock(&mark->lock); 596ad69cd99SAmir Goldstein err = fsnotify_attach_connector_to_object(connp, obj_type, 597ad69cd99SAmir Goldstein fsid); 5989dd813c1SJan Kara if (err) 5999dd813c1SJan Kara return err; 60008991e83SJan Kara goto restart; 601c285a2f0SAmir Goldstein } else if (fsid && !(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID)) { 602c285a2f0SAmir Goldstein conn->fsid = *fsid; 603c285a2f0SAmir Goldstein /* Pairs with smp_rmb() in fanotify_get_fsid() */ 604c285a2f0SAmir Goldstein smp_wmb(); 605c285a2f0SAmir Goldstein conn->flags |= FSNOTIFY_CONN_FLAG_HAS_FSID; 606c285a2f0SAmir Goldstein } else if (fsid && (conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID) && 60777115225SAmir Goldstein (fsid->val[0] != conn->fsid.val[0] || 60877115225SAmir Goldstein fsid->val[1] != conn->fsid.val[1])) { 60977115225SAmir Goldstein /* 61077115225SAmir Goldstein * Backend is expected to check for non uniform fsid 61177115225SAmir Goldstein * (e.g. btrfs), but maybe we missed something? 61277115225SAmir Goldstein * Only allow setting conn->fsid once to non zero fsid. 61377115225SAmir Goldstein * inotify and non-fid fanotify groups do not set nor test 61477115225SAmir Goldstein * conn->fsid. 61577115225SAmir Goldstein */ 61677115225SAmir Goldstein pr_warn_ratelimited("%s: fsid mismatch on object of type %u: " 61777115225SAmir Goldstein "%x.%x != %x.%x\n", __func__, conn->type, 61877115225SAmir Goldstein fsid->val[0], fsid->val[1], 61977115225SAmir Goldstein conn->fsid.val[0], conn->fsid.val[1]); 62077115225SAmir Goldstein err = -EXDEV; 62177115225SAmir Goldstein goto out_err; 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) && 6366b3f05d2SJan Kara !allow_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, 67177115225SAmir Goldstein int allow_dups, __kernel_fsid_t *fsid) 6725444e298SEric Paris { 6737b129323SJan Kara struct fsnotify_group *group = mark->group; 6745444e298SEric Paris int ret = 0; 6755444e298SEric Paris 676d5a335b8SLino Sanfilippo BUG_ON(!mutex_is_locked(&group->mark_mutex)); 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 691ad69cd99SAmir Goldstein ret = fsnotify_add_mark_list(mark, connp, obj_type, allow_dups, fsid); 692755b5bc6SJan Kara if (ret) 693755b5bc6SJan Kara goto err; 694755b5bc6SJan Kara 695a242677bSJan Kara if (mark->mask) 696a242677bSJan Kara fsnotify_recalc_mask(mark->connector); 6975444e298SEric Paris 6985444e298SEric Paris return ret; 6995444e298SEric Paris err: 7009cf90cefSJan Kara spin_lock(&mark->lock); 70111375145SJan Kara mark->flags &= ~(FSNOTIFY_MARK_FLAG_ALIVE | 70211375145SJan Kara FSNOTIFY_MARK_FLAG_ATTACHED); 7035444e298SEric Paris list_del_init(&mark->g_list); 7049cf90cefSJan Kara spin_unlock(&mark->lock); 7055444e298SEric Paris 70611375145SJan Kara fsnotify_put_mark(mark); 7075444e298SEric Paris return ret; 7085444e298SEric Paris } 7095444e298SEric Paris 710b812a9f5SAmir Goldstein int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp, 711ad69cd99SAmir Goldstein unsigned int obj_type, int allow_dups, 712ad69cd99SAmir Goldstein __kernel_fsid_t *fsid) 713d5a335b8SLino Sanfilippo { 714d5a335b8SLino Sanfilippo int ret; 7157b129323SJan Kara struct fsnotify_group *group = mark->group; 7167b129323SJan Kara 717d5a335b8SLino Sanfilippo mutex_lock(&group->mark_mutex); 718ad69cd99SAmir Goldstein ret = fsnotify_add_mark_locked(mark, connp, obj_type, allow_dups, fsid); 719d5a335b8SLino Sanfilippo mutex_unlock(&group->mark_mutex); 720d5a335b8SLino Sanfilippo return ret; 721d5a335b8SLino Sanfilippo } 722b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_add_mark); 723d5a335b8SLino Sanfilippo 7245444e298SEric Paris /* 7250809ab69SJan Kara * Given a list of marks, find the mark associated with given group. If found 7260809ab69SJan Kara * take a reference to that mark and return it, else return NULL. 7270809ab69SJan Kara */ 7289b6e5434SAmir Goldstein struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp, 7290809ab69SJan Kara struct fsnotify_group *group) 7300809ab69SJan Kara { 73108991e83SJan Kara struct fsnotify_mark_connector *conn; 7320809ab69SJan Kara struct fsnotify_mark *mark; 7330809ab69SJan Kara 73408991e83SJan Kara conn = fsnotify_grab_connector(connp); 7359dd813c1SJan Kara if (!conn) 7369dd813c1SJan Kara return NULL; 7379dd813c1SJan Kara 7389dd813c1SJan Kara hlist_for_each_entry(mark, &conn->list, obj_list) { 7396b3f05d2SJan Kara if (mark->group == group && 7406b3f05d2SJan Kara (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { 7410809ab69SJan Kara fsnotify_get_mark(mark); 74204662cabSJan Kara spin_unlock(&conn->lock); 7430809ab69SJan Kara return mark; 7440809ab69SJan Kara } 7450809ab69SJan Kara } 74604662cabSJan Kara spin_unlock(&conn->lock); 7470809ab69SJan Kara return NULL; 7480809ab69SJan Kara } 749b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_find_mark); 7500809ab69SJan Kara 751d6f7b98bSAmir Goldstein /* Clear any marks in a group with given type mask */ 75218f2e0d3SJan Kara void fsnotify_clear_marks_by_group(struct fsnotify_group *group, 753ad69cd99SAmir Goldstein unsigned int obj_type) 7545444e298SEric Paris { 7555444e298SEric Paris struct fsnotify_mark *lmark, *mark; 7568f2f3eb5SJan Kara LIST_HEAD(to_free); 7572e37c6caSJan Kara struct list_head *head = &to_free; 7585444e298SEric Paris 7592e37c6caSJan Kara /* Skip selection step if we want to clear all marks. */ 760ad69cd99SAmir Goldstein if (obj_type == FSNOTIFY_OBJ_TYPE_ANY) { 7612e37c6caSJan Kara head = &group->marks_list; 7622e37c6caSJan Kara goto clear; 7632e37c6caSJan Kara } 7648f2f3eb5SJan Kara /* 7658f2f3eb5SJan Kara * We have to be really careful here. Anytime we drop mark_mutex, e.g. 7668f2f3eb5SJan Kara * fsnotify_clear_marks_by_inode() can come and free marks. Even in our 7678f2f3eb5SJan Kara * to_free list so we have to use mark_mutex even when accessing that 7688f2f3eb5SJan Kara * list. And freeing mark requires us to drop mark_mutex. So we can 7698f2f3eb5SJan Kara * reliably free only the first mark in the list. That's why we first 7708f2f3eb5SJan Kara * move marks to free to to_free list in one go and then free marks in 7718f2f3eb5SJan Kara * to_free list one by one. 7728f2f3eb5SJan Kara */ 7736960b0d9SLino Sanfilippo mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); 7745444e298SEric Paris list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { 775ad69cd99SAmir Goldstein if (mark->connector->type == obj_type) 7768f2f3eb5SJan Kara list_move(&mark->g_list, &to_free); 7774d92604cSEric Paris } 778986ab098SLino Sanfilippo mutex_unlock(&group->mark_mutex); 7798f2f3eb5SJan Kara 7802e37c6caSJan Kara clear: 7818f2f3eb5SJan Kara while (1) { 7828f2f3eb5SJan Kara mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); 7832e37c6caSJan Kara if (list_empty(head)) { 7848f2f3eb5SJan Kara mutex_unlock(&group->mark_mutex); 7858f2f3eb5SJan Kara break; 7868f2f3eb5SJan Kara } 7872e37c6caSJan Kara mark = list_first_entry(head, struct fsnotify_mark, g_list); 7888f2f3eb5SJan Kara fsnotify_get_mark(mark); 7894712e722SJan Kara fsnotify_detach_mark(mark); 7908f2f3eb5SJan Kara mutex_unlock(&group->mark_mutex); 7914712e722SJan Kara fsnotify_free_mark(mark); 7928f2f3eb5SJan Kara fsnotify_put_mark(mark); 7938f2f3eb5SJan Kara } 7945444e298SEric Paris } 7955444e298SEric Paris 7969b6e5434SAmir Goldstein /* Destroy all marks attached to an object via connector */ 7979b6e5434SAmir Goldstein void fsnotify_destroy_marks(fsnotify_connp_t *connp) 7980810b4f9SJan Kara { 79908991e83SJan Kara struct fsnotify_mark_connector *conn; 8006b3f05d2SJan Kara struct fsnotify_mark *mark, *old_mark = NULL; 801721fb6fbSJan Kara void *objp; 802721fb6fbSJan Kara unsigned int type; 8030810b4f9SJan Kara 8046b3f05d2SJan Kara conn = fsnotify_grab_connector(connp); 8056b3f05d2SJan Kara if (!conn) 8066b3f05d2SJan Kara return; 8070810b4f9SJan Kara /* 8080810b4f9SJan Kara * We have to be careful since we can race with e.g. 8096b3f05d2SJan Kara * fsnotify_clear_marks_by_group() and once we drop the conn->lock, the 8106b3f05d2SJan Kara * list can get modified. However we are holding mark reference and 8116b3f05d2SJan Kara * thus our mark cannot be removed from obj_list so we can continue 8126b3f05d2SJan Kara * iteration after regaining conn->lock. 8130810b4f9SJan Kara */ 8146b3f05d2SJan Kara hlist_for_each_entry(mark, &conn->list, obj_list) { 8150810b4f9SJan Kara fsnotify_get_mark(mark); 81604662cabSJan Kara spin_unlock(&conn->lock); 8176b3f05d2SJan Kara if (old_mark) 8186b3f05d2SJan Kara fsnotify_put_mark(old_mark); 8196b3f05d2SJan Kara old_mark = mark; 8200810b4f9SJan Kara fsnotify_destroy_mark(mark, mark->group); 8216b3f05d2SJan Kara spin_lock(&conn->lock); 8220810b4f9SJan Kara } 8236b3f05d2SJan Kara /* 8246b3f05d2SJan Kara * Detach list from object now so that we don't pin inode until all 8256b3f05d2SJan Kara * mark references get dropped. It would lead to strange results such 8266b3f05d2SJan Kara * as delaying inode deletion or blocking unmount. 8276b3f05d2SJan Kara */ 828721fb6fbSJan Kara objp = fsnotify_detach_connector_from_object(conn, &type); 8296b3f05d2SJan Kara spin_unlock(&conn->lock); 8306b3f05d2SJan Kara if (old_mark) 8316b3f05d2SJan Kara fsnotify_put_mark(old_mark); 832721fb6fbSJan Kara fsnotify_drop_object(type, objp); 8330810b4f9SJan Kara } 8340810b4f9SJan Kara 8355444e298SEric Paris /* 8365444e298SEric Paris * Nothing fancy, just initialize lists and locks and counters. 8375444e298SEric Paris */ 8385444e298SEric Paris void fsnotify_init_mark(struct fsnotify_mark *mark, 839054c636eSJan Kara struct fsnotify_group *group) 8405444e298SEric Paris { 841ba643f04SEric Paris memset(mark, 0, sizeof(*mark)); 8425444e298SEric Paris spin_lock_init(&mark->lock); 843ab97f873SElena Reshetova refcount_set(&mark->refcnt, 1); 8447b129323SJan Kara fsnotify_get_group(group); 8457b129323SJan Kara mark->group = group; 846b1da6a51SJan Kara WRITE_ONCE(mark->connector, NULL); 8475444e298SEric Paris } 848b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_init_mark); 84913d34ac6SJeff Layton 85035e48176SJan Kara /* 85135e48176SJan Kara * Destroy all marks in destroy_list, waits for SRCU period to finish before 85235e48176SJan Kara * actually freeing marks. 85335e48176SJan Kara */ 854f09b04a0SJan Kara static void fsnotify_mark_destroy_workfn(struct work_struct *work) 85513d34ac6SJeff Layton { 85613d34ac6SJeff Layton struct fsnotify_mark *mark, *next; 85713d34ac6SJeff Layton struct list_head private_destroy_list; 85813d34ac6SJeff Layton 85913d34ac6SJeff Layton spin_lock(&destroy_lock); 86013d34ac6SJeff Layton /* exchange the list head */ 86113d34ac6SJeff Layton list_replace_init(&destroy_list, &private_destroy_list); 86213d34ac6SJeff Layton spin_unlock(&destroy_lock); 86313d34ac6SJeff Layton 86413d34ac6SJeff Layton synchronize_srcu(&fsnotify_mark_srcu); 86513d34ac6SJeff Layton 86613d34ac6SJeff Layton list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) { 86713d34ac6SJeff Layton list_del_init(&mark->g_list); 8686b3f05d2SJan Kara fsnotify_final_mark_destroy(mark); 86913d34ac6SJeff Layton } 87013d34ac6SJeff Layton } 87135e48176SJan Kara 872f09b04a0SJan Kara /* Wait for all marks queued for destruction to be actually destroyed */ 873f09b04a0SJan Kara void fsnotify_wait_marks_destroyed(void) 87435e48176SJan Kara { 875f09b04a0SJan Kara flush_delayed_work(&reaper_work); 87635e48176SJan Kara } 877b72679eeSTrond Myklebust EXPORT_SYMBOL_GPL(fsnotify_wait_marks_destroyed); 878