lkml.org 
[lkml]   [2020]   [Jan]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 105/165] fs: call fsnotify_sb_delete after evict_inodes
    Date
    From: Eric Sandeen <sandeen@redhat.com>

    [ Upstream commit 1edc8eb2e93130e36ac74ac9c80913815a57d413 ]

    When a filesystem is unmounted, we currently call fsnotify_sb_delete()
    before evict_inodes(), which means that fsnotify_unmount_inodes()
    must iterate over all inodes on the superblock looking for any inodes
    with watches. This is inefficient and can lead to livelocks as it
    iterates over many unwatched inodes.

    At this point, SB_ACTIVE is gone and dropping refcount to zero kicks
    the inode out out immediately, so anything processed by
    fsnotify_sb_delete / fsnotify_unmount_inodes gets evicted in that loop.

    After that, the call to evict_inodes will evict everything else with a
    zero refcount.

    This should speed things up overall, and avoid livelocks in
    fsnotify_unmount_inodes().

    Signed-off-by: Eric Sandeen <sandeen@redhat.com>
    Reviewed-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/notify/fsnotify.c | 3 +++
    fs/super.c | 4 +++-
    2 files changed, 6 insertions(+), 1 deletion(-)

    diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
    index ac9eb273e28c..f44e39c68328 100644
    --- a/fs/notify/fsnotify.c
    +++ b/fs/notify/fsnotify.c
    @@ -57,6 +57,9 @@ static void fsnotify_unmount_inodes(struct super_block *sb)
    * doing an __iget/iput with SB_ACTIVE clear would actually
    * evict all inodes with zero i_count from icache which is
    * unnecessarily violent and may in fact be illegal to do.
    + * However, we should have been called /after/ evict_inodes
    + * removed all zero refcount inodes, in any case. Test to
    + * be sure.
    */
    if (!atomic_read(&inode->i_count)) {
    spin_unlock(&inode->i_lock);
    diff --git a/fs/super.c b/fs/super.c
    index cfadab2cbf35..cd352530eca9 100644
    --- a/fs/super.c
    +++ b/fs/super.c
    @@ -448,10 +448,12 @@ void generic_shutdown_super(struct super_block *sb)
    sync_filesystem(sb);
    sb->s_flags &= ~SB_ACTIVE;

    - fsnotify_sb_delete(sb);
    cgroup_writeback_umount();

    + /* evict all inodes with zero refcount */
    evict_inodes(sb);
    + /* only nonzero refcount inodes can have marks */
    + fsnotify_sb_delete(sb);

    if (sb->s_dio_done_wq) {
    destroy_workqueue(sb->s_dio_done_wq);
    --
    2.20.1


    \
     
     \ /
      Last update: 2020-01-11 11:28    [W:5.361 / U:0.364 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site