Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp10790210imu; Thu, 6 Dec 2018 06:52:39 -0800 (PST) X-Google-Smtp-Source: AFSGD/WkAJ29O0xHtlDGzfgo3z5SBEMLGiGd5SQtsbZCWvoKXgwzOmu8sFwvSPqy49A6PJIk6vPu X-Received: by 2002:a62:1212:: with SMTP id a18mr29719245pfj.217.1544107959297; Thu, 06 Dec 2018 06:52:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544107959; cv=none; d=google.com; s=arc-20160816; b=d3Rgdb6rPvm/o3VHukjIlKkym1RVYzEGMCkBG6MAEUa4JE/E8cMnHBc3DPWxV3H8FP 4Kioo/18apjyxyEWmfBj37m4H6MOyiAprG69bAQX+iQU22XXwmoF1nmB7Y6y/dXgfCE+ ZL1xd/ap8Kgkub1Uwz1RhpFb27s16VWNQMWHEq8Z4nUnN+Qr5531usRpEKlikvbByxQZ YD025MnjxwtPe/c1Xq1PCwT6E5x3vYsKLKq9LuLEVF1Q4E8Ru5Rjlqlev9eNd4+J1yb2 izk65Y5LV2lcCMBtep3YmX2C1kzB1QCkxe/olnLHaEtI5U5Oj4LzPcCol6L6it9qhceY DpCw== 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=xQwJ9M4J7sf1NndLxTMB4BulXVf8ek+wNFdrrxcssZA=; b=zyyRLOTTAOOLKJ9TthzDuaqBdAvH0lKBkSCPg5C44bM+Q05yMk7BwF6Z7uhk9Uol6r JC0qktvKuJm0vjKpft9PsUE6gJP+7yS7eYdGF8DXt4aCnJrI1i8KMpvxf09G28KtZCGK oECTn+f6B0LiiQGG3o/6ltul2U3ZQNP0vV8eilldjVi6soyf5+wDEdZj7bNtO9e3MSY8 4xg4t+Nihauw0fhvLGwi3AzJ5V0BRChKHGzyiAJcBmgufPUaD4QboweZpQvoE4QpsGI2 GVmgoYpUcsDL3EIkp+2XGSvE0hSxCoN5/SNsNEbXapuE6Jx8vnaEP+6QN6F3DnRgvX/6 Smrw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="xjBsCT/G"; 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 x5si389021pgq.535.2018.12.06.06.52.08; Thu, 06 Dec 2018 06:52:39 -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="xjBsCT/G"; 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 S1731419AbeLFOrb (ORCPT + 99 others); Thu, 6 Dec 2018 09:47:31 -0500 Received: from mail.kernel.org ([198.145.29.99]:52374 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730832AbeLFOrX (ORCPT ); Thu, 6 Dec 2018 09:47:23 -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 805B7214DB; Thu, 6 Dec 2018 14:47:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1544107642; bh=HMAPDKrJxOskXBpcbtWTzohcd41VGDS/SCXHp0q0Zfw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=xjBsCT/GZkGr1Q/GmDz9iyFgWWzChGvWhb/cJIOeVHKPXTaAGpXAKJvbWuif3Rrw4 0zDgvBzc8JzatjYTZ3+IdmtRJUpfvB66X13aaW4nnqGi1k4ufphZUbCmPUFl9sUq+v z3gIOE2A9FJAEQyfjITknBTrd5YDXb85EJDzOXcw= 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.9 084/101] f2fs: fix race condition in between free nid allocator/initializer Date: Thu, 6 Dec 2018 15:39:23 +0100 Message-Id: <20181206143017.524708368@linuxfoundation.org> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181206143011.174892052@linuxfoundation.org> References: <20181206143011.174892052@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.9-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.9: - 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 @@ -1704,8 +1704,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; @@ -1714,35 +1715,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)