7979#define FSNOTIFY_REAPER_DELAY (1) /* 1 jiffy */
8080
8181struct srcu_struct fsnotify_mark_srcu ;
82- struct kmem_cache * fsnotify_mark_connector_cachep ;
82+ static struct kmem_cache * fsnotify_mark_connector_cachep ;
83+ static struct kmem_cache * fsnotify_inode_mark_connector_cachep ;
8384
8485static DEFINE_SPINLOCK (destroy_lock );
8586static LIST_HEAD (destroy_list );
@@ -323,10 +324,12 @@ static void fsnotify_connector_destroy_workfn(struct work_struct *work)
323324 while (conn ) {
324325 free = conn ;
325326 conn = conn -> destroy_next ;
326- kmem_cache_free ( fsnotify_mark_connector_cachep , free );
327+ kfree ( free );
327328 }
328329}
329330
331+ static void fsnotify_untrack_connector (struct fsnotify_mark_connector * conn );
332+
330333static void * fsnotify_detach_connector_from_object (
331334 struct fsnotify_mark_connector * conn ,
332335 unsigned int * type )
@@ -342,6 +345,7 @@ static void *fsnotify_detach_connector_from_object(
342345 if (conn -> type == FSNOTIFY_OBJ_TYPE_INODE ) {
343346 inode = fsnotify_conn_inode (conn );
344347 inode -> i_fsnotify_mask = 0 ;
348+ fsnotify_untrack_connector (conn );
345349
346350 /* Unpin inode when detaching from connector */
347351 if (!(conn -> flags & FSNOTIFY_CONN_FLAG_HAS_IREF ))
@@ -644,6 +648,8 @@ static int fsnotify_attach_info_to_sb(struct super_block *sb)
644648 if (!sbinfo )
645649 return - ENOMEM ;
646650
651+ INIT_LIST_HEAD (& sbinfo -> inode_conn_list );
652+ spin_lock_init (& sbinfo -> list_lock );
647653 /*
648654 * cmpxchg() provides the barrier so that callers of fsnotify_sb_info()
649655 * will observe an initialized structure
@@ -655,28 +661,132 @@ static int fsnotify_attach_info_to_sb(struct super_block *sb)
655661 return 0 ;
656662}
657663
658- static int fsnotify_attach_connector_to_object (fsnotify_connp_t * connp ,
659- void * obj , unsigned int obj_type )
664+ struct fsnotify_inode_mark_connector {
665+ struct fsnotify_mark_connector common ;
666+ struct list_head conns_list ;
667+ };
668+
669+ static struct inode * fsnotify_get_living_inode (struct fsnotify_sb_info * sbinfo )
660670{
661- struct fsnotify_mark_connector * conn ;
671+ struct fsnotify_inode_mark_connector * iconn ;
672+ struct inode * inode ;
673+
674+ spin_lock (& sbinfo -> list_lock );
675+ /* Find the first non-evicting inode */
676+ list_for_each_entry (iconn , & sbinfo -> inode_conn_list , conns_list ) {
677+ /* All connectors on the list are still attached to an inode */
678+ inode = iconn -> common .obj ;
679+ /*
680+ * For connectors without FSNOTIFY_CONN_FLAG_HAS_IREF
681+ * (evictable marks) corresponding inode may well have 0
682+ * refcount and can be undergoing eviction. OTOH list_lock
683+ * protects us from the connector getting detached and inode
684+ * freed. So we can poke around the inode safely.
685+ */
686+ spin_lock (& inode -> i_lock );
687+ if (likely (
688+ !(inode_state_read (inode ) & (I_FREEING | I_WILL_FREE )))) {
689+ __iget (inode );
690+ spin_unlock (& inode -> i_lock );
691+ spin_unlock (& sbinfo -> list_lock );
692+ return inode ;
693+ }
694+ spin_unlock (& inode -> i_lock );
695+ }
696+ spin_unlock (& sbinfo -> list_lock );
662697
663- conn = kmem_cache_alloc (fsnotify_mark_connector_cachep , GFP_KERNEL );
664- if (!conn )
665- return - ENOMEM ;
698+ return NULL ;
699+ }
700+
701+ /**
702+ * fsnotify_unmount_inodes - an sb is unmounting. Handle any watched inodes.
703+ * @sbinfo: fsnotify info for superblock being unmounted.
704+ *
705+ * Walk all inode connectors for the superblock and free all associated marks.
706+ */
707+ void fsnotify_unmount_inodes (struct fsnotify_sb_info * sbinfo )
708+ {
709+ struct inode * inode ;
710+
711+ while ((inode = fsnotify_get_living_inode (sbinfo ))) {
712+ fsnotify_inode (inode , FS_UNMOUNT );
713+ fsnotify_clear_marks_by_inode (inode );
714+ iput (inode );
715+ cond_resched ();
716+ }
717+ }
718+
719+ static void fsnotify_init_connector (struct fsnotify_mark_connector * conn ,
720+ void * obj , unsigned int obj_type )
721+ {
666722 spin_lock_init (& conn -> lock );
667723 INIT_HLIST_HEAD (& conn -> list );
668724 conn -> flags = 0 ;
669725 conn -> prio = 0 ;
670726 conn -> type = obj_type ;
671727 conn -> obj = obj ;
728+ }
729+
730+ static struct fsnotify_mark_connector *
731+ fsnotify_alloc_inode_connector (struct inode * inode )
732+ {
733+ struct fsnotify_inode_mark_connector * iconn ;
734+ struct fsnotify_sb_info * sbinfo = fsnotify_sb_info (inode -> i_sb );
735+
736+ iconn = kmem_cache_alloc (fsnotify_inode_mark_connector_cachep ,
737+ GFP_KERNEL );
738+ if (!iconn )
739+ return NULL ;
740+
741+ fsnotify_init_connector (& iconn -> common , inode , FSNOTIFY_OBJ_TYPE_INODE );
742+ spin_lock (& sbinfo -> list_lock );
743+ list_add (& iconn -> conns_list , & sbinfo -> inode_conn_list );
744+ spin_unlock (& sbinfo -> list_lock );
745+
746+ return & iconn -> common ;
747+ }
748+
749+ static void fsnotify_untrack_connector (struct fsnotify_mark_connector * conn )
750+ {
751+ struct fsnotify_inode_mark_connector * iconn ;
752+ struct fsnotify_sb_info * sbinfo ;
753+
754+ if (conn -> type != FSNOTIFY_OBJ_TYPE_INODE )
755+ return ;
756+
757+ iconn = container_of (conn , struct fsnotify_inode_mark_connector , common );
758+ sbinfo = fsnotify_sb_info (fsnotify_conn_inode (conn )-> i_sb );
759+ spin_lock (& sbinfo -> list_lock );
760+ list_del (& iconn -> conns_list );
761+ spin_unlock (& sbinfo -> list_lock );
762+ }
763+
764+ static int fsnotify_attach_connector_to_object (fsnotify_connp_t * connp ,
765+ void * obj , unsigned int obj_type )
766+ {
767+ struct fsnotify_mark_connector * conn ;
768+
769+ if (obj_type == FSNOTIFY_OBJ_TYPE_INODE ) {
770+ struct inode * inode = obj ;
771+
772+ conn = fsnotify_alloc_inode_connector (inode );
773+ } else {
774+ conn = kmem_cache_alloc (fsnotify_mark_connector_cachep ,
775+ GFP_KERNEL );
776+ if (conn )
777+ fsnotify_init_connector (conn , obj , obj_type );
778+ }
779+ if (!conn )
780+ return - ENOMEM ;
672781
673782 /*
674783 * cmpxchg() provides the barrier so that readers of *connp can see
675784 * only initialized structure
676785 */
677786 if (cmpxchg (connp , NULL , conn )) {
678787 /* Someone else created list structure for us */
679- kmem_cache_free (fsnotify_mark_connector_cachep , conn );
788+ fsnotify_untrack_connector (conn );
789+ kfree (conn );
680790 }
681791 return 0 ;
682792}
@@ -1007,3 +1117,12 @@ void fsnotify_wait_marks_destroyed(void)
10071117 flush_delayed_work (& reaper_work );
10081118}
10091119EXPORT_SYMBOL_GPL (fsnotify_wait_marks_destroyed );
1120+
1121+ __init void fsnotify_init_connector_caches (void )
1122+ {
1123+ fsnotify_mark_connector_cachep = KMEM_CACHE (fsnotify_mark_connector ,
1124+ SLAB_PANIC );
1125+ fsnotify_inode_mark_connector_cachep = KMEM_CACHE (
1126+ fsnotify_inode_mark_connector ,
1127+ SLAB_PANIC );
1128+ }
0 commit comments