From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 49D07FA372A for ; Thu, 17 Oct 2019 08:39:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 26210214E0 for ; Thu, 17 Oct 2019 08:39:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2405204AbfJQIj2 (ORCPT ); Thu, 17 Oct 2019 04:39:28 -0400 Received: from mx2.suse.de ([195.135.220.15]:53172 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2388788AbfJQIj2 (ORCPT ); Thu, 17 Oct 2019 04:39:28 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 77B09B172; Thu, 17 Oct 2019 08:39:26 +0000 (UTC) Received: by quack2.suse.cz (Postfix, from userid 1000) id 41AB51E485F; Thu, 17 Oct 2019 10:39:26 +0200 (CEST) Date: Thu, 17 Oct 2019 10:39:26 +0200 From: Jan Kara To: Eric Sandeen Cc: fsdevel , Jan Kara , Al Viro , Eric Paris Subject: Re: [PATCH 2/1] fs: call fsnotify_sb_delete after evict_inodes Message-ID: <20191017083926.GD20260@quack2.suse.cz> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org On Wed 16-10-19 12:11:24, Eric Sandeen wrote: > 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, even though it will > only act on inodes with a refcount. This is inefficient and can lead > to livelocks as it iterates over many unrefcounted inodes. > > However, since fsnotify_sb_delete() and evict_inodes() are working > on orthogonal sets of inodes (fsnotify_sb_delete() only cares about nonzero > refcount, and evict_inodes() only cares about zero refcount), we can swap > the order of the calls. The fsnotify call will then have a much smaller > list to walk (any refcounted inodes). > > This should speed things up overall, and avoid livelocks in > fsnotify_unmount_inodes(). > > Signed-off-by: Eric Sandeen Thanks for the patch. It looks good to me. Feel free to add: Reviewed-by: Jan Kara > --- > > I just did basic sanity testing here, but AFAIK there is no *notify > test suite, so I'm not sure how to really give this a workout. LTP has quite a few tests for inotify & fanotify. Honza > diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c > index ac9eb273e28c..426f03b6e660 100644 > --- a/fs/notify/fsnotify.c > +++ b/fs/notify/fsnotify.c > @@ -57,6 +57,10 @@ 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); > > -- Jan Kara SUSE Labs, CR