Received: by 2002:a05:6358:1087:b0:cb:c9d3:cd90 with SMTP id j7csp2859198rwi; Fri, 28 Oct 2022 12:13:54 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5UGfpBcHdD/6zJWH1MfxUyTqXigwqezHjAm/zZGtjA7i0xHCIdvYkMz/Y3V1OU61dJTixS X-Received: by 2002:a63:6cc9:0:b0:43c:7998:8a78 with SMTP id h192-20020a636cc9000000b0043c79988a78mr868738pgc.600.1666984433823; Fri, 28 Oct 2022 12:13:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666984433; cv=none; d=google.com; s=arc-20160816; b=fGTsNMrEcxdOu6cURlz0wfx0X5caTKSohcEXoRx6ups8rgNPxB9wIomdyim31NfXUr UuXv6/nCy6kppjOuSWOPVd9VQWQe+C//KsYoV2lqglWUsxR/8tE+RAxZhjKcHgyiw+Ty Gw8+sfwDVmC1eIbu7QcoVOSvz8v4RF/tHnJIk/VHpKpeYRyheqTEZjnMa5Ao606jm96i 8uOH0bqV0+xPnDX1fn/hNaK8QxFp+d3Akc8Hi2D2Fgq5+XwQVoBw25NF3yECCpQfMri8 c0mBxjHdgbZyncTgC/Avl3OWjEbHPdzrpsFIzHx/D+YJksdtatvAQsXvT4KoW9s5PXNS NnMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=TksKynyYY7mzZxtT3FG1fm2+t0LF+9Q17S2kfceuxGc=; b=TgmDhHqod19A/Uq6zCFIOT9sRtrQjczf5ZRcUKZcsL41NV8e2mF+awuxj0tpTTB95u c4ChCO3daFu+EqZvkkt6Rd6SyHZFB6FanMor+ZAvCWgIJS14gS70Q/whmFGy1xTgC8F1 nyOfCkAfuIQMJ4HcHG4+xMCzICQgBOnRXrARBlzGVKhl0NKy7e16R0Dmq91Yh60f28Cn S43oWC8lbw6Y5GGoRiWLqrn0QgJQNy/DF5dCt8I7XzWSyriBImEcc74wgOdnn6mScs+9 4agOeZKnTJeTIEdzZlxt/3dZetCtpyVnRRc25pX4O0N9tYNKouuqNx7WRO4lTWVUxz5h QFnw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=q9WAS2Kg; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id a6-20020a170902710600b0017f7fffb591si5472768pll.374.2022.10.28.12.13.39; Fri, 28 Oct 2022 12:13:53 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=q9WAS2Kg; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229975AbiJ1S5T (ORCPT + 99 others); Fri, 28 Oct 2022 14:57:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55100 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229455AbiJ1S5S (ORCPT ); Fri, 28 Oct 2022 14:57:18 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 98BBA1D2B51 for ; Fri, 28 Oct 2022 11:57:17 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 3820562A26 for ; Fri, 28 Oct 2022 18:57:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3EDB9C43470; Fri, 28 Oct 2022 18:57:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1666983436; bh=NJmStmbj9UXmkjFc0+Ec0WT9PNFAnNPfSrmtnQZ5jFY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=q9WAS2KgoswbDz16wXiy6IchkH7G5dDMRb7tmEfuQM+3T6RgJWjCJNVlp2YZeJunL 9KlsbR201V04kYx+RHrQst72e+8JtqRIzbpdfM/ajUSHkdmtDDwmC6xSTRg5UYrzVn oHpVft1mqj3Twsx/5/71fp4++WHgTQCI7GC2pUEND0envsM3xMSMFvNLPa/a6bPn3i YHHuewirylsAOPukbRm4N3mnYNNljexJLqBnkKwZokDRQK2QlRe7llDA9RvdL6iCr2 khCRwSq/r9HePS5hcetJJvA4wtpqptGvqapEEwB1dfjyBKxz6+FFHNklzvbQKqCy4H OQnUvJggP/Pvg== From: Jeff Layton To: chuck.lever@oracle.com Cc: linux-nfs@vger.kernel.org, neilb@suse.de Subject: [PATCH v3 3/4] nfsd: close race between unhashing and LRU addition Date: Fri, 28 Oct 2022 14:57:11 -0400 Message-Id: <20221028185712.79863-4-jlayton@kernel.org> X-Mailer: git-send-email 2.37.3 In-Reply-To: <20221028185712.79863-1-jlayton@kernel.org> References: <20221028185712.79863-1-jlayton@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org The list_lru_add and list_lru_del functions use list_empty checks to see whether the object is already on the LRU. That's fine in most cases, but we occasionally repurpose nf_lru after unhashing. It's possible for an LRU removal to remove it from a different list altogether if we lose a race. Add a new NFSD_FILE_LRU flag, which indicates that the object actually resides on the LRU and not some other list. Use that when adding and removing it from the LRU instead of just relying on list_empty checks. Add an extra HASHED check after adding the entry to the LRU. If it's now clear, just remove it from the LRU again and put the reference if that remove is successful. Signed-off-by: Jeff Layton --- fs/nfsd/filecache.c | 44 +++++++++++++++++++++++++++++--------------- fs/nfsd/filecache.h | 1 + 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index d928c5e38eeb..47cdc6129a7b 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -403,18 +403,22 @@ nfsd_file_check_writeback(struct nfsd_file *nf) static bool nfsd_file_lru_add(struct nfsd_file *nf) { set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags); - if (list_lru_add(&nfsd_file_lru, &nf->nf_lru)) { - trace_nfsd_file_lru_add(nf); - return true; + if (!test_and_set_bit(NFSD_FILE_LRU, &nf->nf_flags)) { + if (list_lru_add(&nfsd_file_lru, &nf->nf_lru)) { + trace_nfsd_file_lru_add(nf); + return true; + } } return false; } static bool nfsd_file_lru_remove(struct nfsd_file *nf) { - if (list_lru_del(&nfsd_file_lru, &nf->nf_lru)) { - trace_nfsd_file_lru_del(nf); - return true; + if (test_and_clear_bit(NFSD_FILE_LRU, &nf->nf_flags)) { + if (list_lru_del(&nfsd_file_lru, &nf->nf_lru)) { + trace_nfsd_file_lru_del(nf); + return true; + } } return false; } @@ -469,20 +473,30 @@ nfsd_file_put(struct nfsd_file *nf) { trace_nfsd_file_put(nf); - /* - * The HASHED check is racy. We may end up with the occasional - * unhashed entry on the LRU, but they should get cleaned up - * like any other. - */ if (test_bit(NFSD_FILE_GC, &nf->nf_flags) && test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) { /* - * If this is the last reference (nf_ref == 1), then transfer - * it to the LRU. If the add to the LRU fails, just put it as - * usual. + * If this is the last reference (nf_ref == 1), then try to + * transfer it to the LRU. */ - if (refcount_dec_not_one(&nf->nf_ref) || nfsd_file_lru_add(nf)) + if (refcount_dec_not_one(&nf->nf_ref)) return; + + /* Try to add it to the LRU. If that fails, decrement. */ + if (nfsd_file_lru_add(nf)) { + /* If it's still hashed, we're done */ + if (test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) + return; + + /* + * We're racing with unhashing, so try to remove it from + * the LRU. If removal fails, then someone else already + * has our reference and we're done. If it succeeds, + * fall through to decrement. + */ + if (!nfsd_file_lru_remove(nf)) + return; + } } if (refcount_dec_and_test(&nf->nf_ref)) nfsd_file_free(nf); diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h index b7efb2c3ddb1..e52ab7d5a44c 100644 --- a/fs/nfsd/filecache.h +++ b/fs/nfsd/filecache.h @@ -39,6 +39,7 @@ struct nfsd_file { #define NFSD_FILE_PENDING (1) #define NFSD_FILE_REFERENCED (2) #define NFSD_FILE_GC (3) +#define NFSD_FILE_LRU (4) /* file is on LRU */ unsigned long nf_flags; struct inode *nf_inode; /* don't deref */ refcount_t nf_ref; -- 2.37.3