• Jan Kara's avatar
    fsnotify: Fix busy inodes during unmount · 721fb6fb
    Jan Kara authored
    Detaching of mark connector from fsnotify_put_mark() can race with
    unmounting of the filesystem like:
    
      CPU1				CPU2
    fsnotify_put_mark()
      spin_lock(&conn->lock);
      ...
      inode = fsnotify_detach_connector_from_object(conn)
      spin_unlock(&conn->lock);
    				generic_shutdown_super()
    				  fsnotify_unmount_inodes()
    				    sees connector detached for inode
    				      -> nothing to do
    				  evict_inode()
    				    barfs on pending inode reference
      iput(inode);
    
    Resulting in "Busy inodes after unmount" message and possible kernel
    oops. Make fsnotify_unmount_inodes() properly wait for outstanding inode
    references from detached connectors.
    
    Note that the accounting of outstanding inode references in the
    superblock can cause some cacheline contention on the counter. OTOH it
    happens only during deletion of the last notification mark from an inode
    (or during unlinking of watched inode) and that is not too bad. I have
    measured time to create & delete inotify watch 100000 times from 64
    processes in parallel (each process having its own inotify group and its
    own file on a shared superblock) on a 64 CPU machine. Average and
    standard deviation of 15 runs look like:
    
    	Avg		Stddev
    Vanilla	9.817400	0.276165
    Fixed	9.710467	0.228294
    
    So there's no statistically significant difference.
    
    Fixes: 6b3f05d2 ("fsnotify: Detach mark from object list when last reference is dropped")
    CC: stable@vger.kernel.org
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    721fb6fb
Name
Last commit
Last update
..
dnotify Loading commit data...
fanotify Loading commit data...
inotify Loading commit data...
Kconfig Loading commit data...
Makefile Loading commit data...
fdinfo.c Loading commit data...
fdinfo.h Loading commit data...
fsnotify.c Loading commit data...
fsnotify.h Loading commit data...
group.c Loading commit data...
mark.c Loading commit data...
notification.c Loading commit data...