Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2410544imu; Thu, 24 Jan 2019 12:16:46 -0800 (PST) X-Google-Smtp-Source: ALg8bN57KiG7gdWoFwu/cTS1t9Mie15EgODG7FbrvHJluRoojEOQR5InyOEuCe/tcQuORgSjNwDA X-Received: by 2002:a63:8e43:: with SMTP id k64mr7190045pge.346.1548361006348; Thu, 24 Jan 2019 12:16:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1548361006; cv=none; d=google.com; s=arc-20160816; b=iR+8/liRTYD11XD854xXIDoenudHs0EDREkUn7qfl+7Nv2vkQJqmQ6uo4VjFbte6N7 keRtHayFV2ZKDFDxxdU0B6qBHE2P6pYu0iRGkahkQ6OlK6/YoHpkeJduiZR6rdbXR/Bm QTlLjq+BzbOY/8QkNxmlDdN0HDZmzVkZfBhh7IANlT87r19OgGCIBJtwYhc6T0ZCDTxq 0swX787HjqZ43uducB0HCvPG3M7IDSKydL4/jzizpcbExWHXKC37aNnHB+NFy1MSxK7x 5VJKfzy438Qqxnh4RpTAIe1s9w3Ia1P8fTkJruKzDcJ8mXLVxZfvVYnsznagK786ECzy KZsA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=hvTCpXep+Ut/pi9Y+nCTYMo7iawQAMlaqrZn9Foex18=; b=m3giSzKZ2MAYzqSmGxHWIhRQSS8Uik/Ze0Gexm+k1jIecwsd8OBYt48TjQum+v9TRn +ba1niuyuYhhHjb9OnO2HRRTqexVZXSASYHG8EN5lP88RZhUVpyuduhb7Vouy7usoIM8 3TW8dziuzfmmwCzHVOS15DMYoPlh0bPp0B3atYbNH7PY1wx3bw4ycDqKv0ar3G9/vm0z Evfuhef2dr0wxhBFvitdkJ1qrykIo3v8WismbtFmFRYaLm+7e00J5vmqsg6UW4X4VeTD o6mE5QU8Jq5vkUypepc6byRQsTT/ExV1OkSgBAI2w9ByeRYfFsEgEJSKXbXuN83S0Yvz fRQw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=TljzDFUQ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c9si3454687pll.439.2019.01.24.12.16.31; Thu, 24 Jan 2019 12:16:46 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=TljzDFUQ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730187AbfAXTYl (ORCPT + 99 others); Thu, 24 Jan 2019 14:24:41 -0500 Received: from mail.kernel.org ([198.145.29.99]:49960 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729664AbfAXTYj (ORCPT ); Thu, 24 Jan 2019 14:24:39 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id ED89D218D2; Thu, 24 Jan 2019 19:24:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548357878; bh=ae2EPSmIspwwbYq2ZTwzE7LmjDUa2QCNWhjmL7RjaLU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TljzDFUQLMl1cpkQ+RPmPBsA6NC9sk6Ys/UXwAaoe+3rqh59Cb/F3NPdu++i3Rzny cuhW+BEP8aBsDbh6dxvwtug8bOTYqehOJ3n6qW6H9ixPeO3Qwln0arPyGDPk4TwHgz 0DsQS8nwg8JF1ye+Av0JUVcOaCG7mTQ1KClwcNKE= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jaegeuk Kim , Chao Yu , Ben Hutchings Subject: [PATCH 4.4 020/104] f2fs: fix race condition in between free nid allocator/initializer Date: Thu, 24 Jan 2019 20:19:09 +0100 Message-Id: <20190124190157.168928312@linuxfoundation.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190124190154.968308875@linuxfoundation.org> References: <20190124190154.968308875@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.4-stable review patch. If anyone has any objections, please let me know. ------------------ From: Chao Yu commit 30a61ddf8117c26ac5b295e1233eaa9629a94ca3 upstream. In below concurrent case, allocated nid can be loaded into free nid cache and be allocated again. Thread A Thread B - f2fs_create - f2fs_new_inode - alloc_nid - __insert_nid_to_list(ALLOC_NID_LIST) - f2fs_balance_fs_bg - build_free_nids - __build_free_nids - scan_nat_page - add_free_nid - __lookup_nat_cache - f2fs_add_link - init_inode_metadata - new_inode_page - new_node_page - set_node_addr - alloc_nid_done - __remove_nid_from_list(ALLOC_NID_LIST) - __insert_nid_to_list(FREE_NID_LIST) This patch makes nat cache lookup and free nid list operation being atomical to avoid this race condition. Signed-off-by: Jaegeuk Kim Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim [bwh: Backported to 4.4: - add_free_nid() returns 0 in case of any error (except low memory) - Tree/list addition has not been moved into __insert_nid_to_list()] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- fs/f2fs/node.c | 62 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 19 deletions(-) --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1428,8 +1428,9 @@ static void __del_from_free_nid_list(str static int add_free_nid(struct f2fs_sb_info *sbi, nid_t nid, bool build) { struct f2fs_nm_info *nm_i = NM_I(sbi); - struct free_nid *i; + struct free_nid *i, *e; struct nat_entry *ne; + int err = -EINVAL; if (!available_free_memory(sbi, FREE_NIDS)) return -1; @@ -1438,35 +1439,58 @@ static int add_free_nid(struct f2fs_sb_i if (unlikely(nid == 0)) return 0; - if (build) { - /* do not add allocated nids */ - ne = __lookup_nat_cache(nm_i, nid); - if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) || - nat_get_blkaddr(ne) != NULL_ADDR)) - return 0; - } - i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS); i->nid = nid; i->state = NID_NEW; - if (radix_tree_preload(GFP_NOFS)) { - kmem_cache_free(free_nid_slab, i); - return 0; - } + if (radix_tree_preload(GFP_NOFS)) + goto err; spin_lock(&nm_i->free_nid_list_lock); - if (radix_tree_insert(&nm_i->free_nid_root, i->nid, i)) { - spin_unlock(&nm_i->free_nid_list_lock); - radix_tree_preload_end(); - kmem_cache_free(free_nid_slab, i); - return 0; + + if (build) { + /* + * Thread A Thread B + * - f2fs_create + * - f2fs_new_inode + * - alloc_nid + * - __insert_nid_to_list(ALLOC_NID_LIST) + * - f2fs_balance_fs_bg + * - build_free_nids + * - __build_free_nids + * - scan_nat_page + * - add_free_nid + * - __lookup_nat_cache + * - f2fs_add_link + * - init_inode_metadata + * - new_inode_page + * - new_node_page + * - set_node_addr + * - alloc_nid_done + * - __remove_nid_from_list(ALLOC_NID_LIST) + * - __insert_nid_to_list(FREE_NID_LIST) + */ + ne = __lookup_nat_cache(nm_i, nid); + if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) || + nat_get_blkaddr(ne) != NULL_ADDR)) + goto err_out; + + e = __lookup_free_nid_list(nm_i, nid); + if (e) + goto err_out; } + if (radix_tree_insert(&nm_i->free_nid_root, i->nid, i)) + goto err_out; + err = 0; list_add_tail(&i->list, &nm_i->free_nid_list); nm_i->fcnt++; +err_out: spin_unlock(&nm_i->free_nid_list_lock); radix_tree_preload_end(); - return 1; +err: + if (err) + kmem_cache_free(free_nid_slab, i); + return !err; } static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)