From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932333AbdKMNIH (ORCPT ); Mon, 13 Nov 2017 08:08:07 -0500 Received: from mailout4.samsung.com ([203.254.224.34]:16546 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932296AbdKMNHu (ORCPT ); Mon, 13 Nov 2017 08:07:50 -0500 DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20171113130749epoutp04a0381716e44a973c3a9011a7bd61534b~2px08ic5v0466404664epoutp04c X-AuditID: b6c32a4a-149ff70000001145-21-5a0999234620 From: "LiFan" To: "'Chao Yu'" , "'Chao Yu'" , "'Jaegeuk Kim'" Cc: , Subject: [f2fs-dev] [PATCH] f2fs: fix concurrent problem for updating free bitmap Date: Mon, 13 Nov 2017 21:06:43 +0800 Message-ID: <006b01d35c80$6648c250$32da46f0$@samsung.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Mailer: Microsoft Outlook 14.0 Content-Language: zh-cn Thread-Index: AdNcf/mvX6/pvjOJSz2P5hycP8nARg== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprNKsWRmVeSWpSXmKPExsWy7bCmlq7yTM4og3vfjC1OTz3LZPFk/Sxm i0uL3C0u75rDZjH18VpWB1aPliNvWT02repk89i94DOTx+dNcgEsUVw2Kak5mWWpRfp2CVwZ d7avYixYoFvRd2ITWwPjD5UuRk4OCQETif1fnrF1MXJxCAnsZpS4+/EaE4TziVFi7frvrBDO N0aJ9vb9rDAtbf9WMkMk9jJKvF61khHCecoosenPZaBhHBxsAhoSUzfLgJgiAtkSB/vkQHqZ BXwkft+6xwxiCwsESyx908oGYrMIqEo8fTCNHcTmFbCUOLrtFxuELShxcuYTFoheeYntb+cw Q9ygILHj7GtGiLi4xJ3WVrDbRAT0JJbfmswOco6EwB42iSm7doOdIyHgIjFnYyxEr7DEq+Nb 2CFsKYnP7/ayQdjrGCU+n7GA6N3OKDHv40cmiIS1xOY1v9hB5jALaEqs36UPEbaVOHL8OTvE DXwSvb+fMEGs4pXoaBOCKFGTeLl6FguE7SHx6ekuqLWOEj03X7NOYFScheTLWUi+nIXks1kI ixcwsqxilEwtKM5NTy02LTDKSy3XK07MLS7NS9dLzs/dxAhOMlpeOxiXnfM5xCjAwajEw1tw iSNKiDWxrLgy9xCjBAezkgivWydnlBBvSmJlVWpRfnxRaU5q8SFGaQ4WJXHeYztLI4UE0hNL UrNTUwtSi2CyTBycUg2MSyoPpmf3Pq1bfmWJ4VetRc5L88umxyU0XLV0nT1J8Gl1Z/6OGQvu HGLYmtHLf/Hb8+ObF6j/UdE4fk/u1oqjRkFHnjw/WPPYKutJ5pUOruDua+ybJRM0Lqmmfw2W O8xxXWfCYRaPU673jj/4t6Lpx4d9HgreSx73VO991Pe5++XXx4tyVx+9qqzEUpyRaKjFXFSc CAB6ui31LgMAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrKLMWRmVeSWpSXmKPExsWy7bCSnK7STM4og7dntCxOTz3LZPFk/Sxm i0uL3C0u75rDZjH18VpWB1aPliNvWT02repk89i94DOTx+dNcgEsUVw2Kak5mWWpRfp2CVwZ d7avYixYoFvRd2ITWwPjD5UuRk4OCQETibZ/K5m7GLk4hAR2M0rcX/qeCSIhI7Hg8Bd2CFtY YuW/5+wQRY8ZJbo3XWTpYuTgYBPQkJi6WQakRkQgV+L0osdg9cwCfhK7Hq5gBrGFBQIl/l04 yApiswioSjx9MA2shlfAUuLotl9sELagxMmZT8BGMgvoSbRtZIQYIy+x/e0cZogTFCR2nH0N FReXuNPaygqxVk9i+a3J7BMYBWchmTQLYdIsJJNmIelewMiyilEytaA4Nz232LDAMC+1XK84 Mbe4NC9dLzk/dxMjOPC1NHcwXl4Sf4hRgINRiYe34BJHlBBrYllxZe4hRgkOZiURXrdOzigh 3pTEyqrUovz4otKc1OJDjNIcLErivE/zjkUKCaQnlqRmp6YWpBbBZJk4OKUaGCfGz1pp+/CY 1K3iFoNH+6dbWISyK59K8vFwvvW7ccHS5/XrPDwinucereyZKBkW12K8lrXp+Je8JwF9+scL shYub9q3ekLCpj9RVRui3k8z1tDKnvjm+e/3pmaXVsWc/bfCY86CnXx7y16mqWy7Gj4p5XTf OzXhb3Wimt/+dRwUfLXdP6vjY7USS3FGoqEWc1FxIgCuYVxqeAIAAA== X-CMS-MailID: 20171113130746epcas5p48964ff4d424b19d1de816bb7468957f2 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-MTR: 20171113130746epcas5p48964ff4d424b19d1de816bb7468957f2 CMS-TYPE: 105P X-CMS-RootMailID: 20171113130746epcas5p48964ff4d424b19d1de816bb7468957f2 X-RootMTR: 20171113130746epcas5p48964ff4d424b19d1de816bb7468957f2 References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org alloc_nid_failed and scan_nat_page can be called at the same time, and we haven't protected add_free_nid and update_free_nid_bitmap with the same nid_list_lock. That could lead to Thread A Thread B - __build_free_nids - scan_nat_page - add_free_nid - alloc_nid_failed - update_free_nid_bitmap - update_free_nid_bitmap scan_nat_page will clear the free bitmap since the nid is PREALLOC_NID, but alloc_nid_failed needs to set the free bitmap. This results in free nid with free bitmap cleared. This patch update the bitmap under the same nid_list_lock in add_free_nid. Signed-off-by: Fan li --- fs/f2fs/node.c | 82 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index b965a53..0a217d2 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1811,8 +1811,33 @@ static void __move_free_nid(struct f2fs_sb_info *sbi, struct free_nid *i, } } +static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, + bool set, bool build) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid); + unsigned int nid_ofs = nid - START_NID(nid); + + if (!test_bit_le(nat_ofs, nm_i->nat_block_bitmap)) + return; + + if (set) { + if (test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) + return; + __set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); + nm_i->free_nid_count[nat_ofs]++; + } else { + if (!test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) + return; + __clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); + if (!build) + nm_i->free_nid_count[nat_ofs]--; + } +} + /* return if the nid is recognized as free */ -static bool add_free_nid(struct f2fs_sb_info *sbi, nid_t nid, bool build) +static bool add_free_nid(struct f2fs_sb_info *sbi, + nid_t nid, bool build, bool update) { struct f2fs_nm_info *nm_i = NM_I(sbi); struct free_nid *i, *e; @@ -1870,6 +1895,11 @@ static bool add_free_nid(struct f2fs_sb_info *sbi, nid_t nid, bool build) ret = true; err = __insert_free_nid(sbi, i, FREE_NID); err_out: + if (update) { + update_free_nid_bitmap(sbi, nid, ret, build); + if (!build) + nm_i->available_nids++; + } spin_unlock(&nm_i->nid_list_lock); radix_tree_preload_end(); err: @@ -1896,30 +1926,6 @@ static void remove_free_nid(struct f2fs_sb_info *sbi, nid_t nid) kmem_cache_free(free_nid_slab, i); } -static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, - bool set, bool build) -{ - struct f2fs_nm_info *nm_i = NM_I(sbi); - unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid); - unsigned int nid_ofs = nid - START_NID(nid); - - if (!test_bit_le(nat_ofs, nm_i->nat_block_bitmap)) - return; - - if (set) { - if (test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) - return; - __set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); - nm_i->free_nid_count[nat_ofs]++; - } else { - if (!test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs])) - return; - __clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]); - if (!build) - nm_i->free_nid_count[nat_ofs]--; - } -} - static void scan_nat_page(struct f2fs_sb_info *sbi, struct page *nat_page, nid_t start_nid) { @@ -1937,18 +1943,18 @@ static void scan_nat_page(struct f2fs_sb_info *sbi, i = start_nid % NAT_ENTRY_PER_BLOCK; for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) { - bool freed = false; - if (unlikely(start_nid >= nm_i->max_nid)) break; blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); f2fs_bug_on(sbi, blk_addr == NEW_ADDR); - if (blk_addr == NULL_ADDR) - freed = add_free_nid(sbi, start_nid, true); - spin_lock(&NM_I(sbi)->nid_list_lock); - update_free_nid_bitmap(sbi, start_nid, freed, true); - spin_unlock(&NM_I(sbi)->nid_list_lock); + if (blk_addr == NULL_ADDR) { + add_free_nid(sbi, start_nid, true, true); + } else { + spin_lock(&NM_I(sbi)->nid_list_lock); + update_free_nid_bitmap(sbi, start_nid, false, true); + spin_unlock(&NM_I(sbi)->nid_list_lock); + } } } @@ -1974,7 +1980,7 @@ static void scan_free_nid_bits(struct f2fs_sb_info *sbi) break; nid = i * NAT_ENTRY_PER_BLOCK + idx; - add_free_nid(sbi, nid, true); + add_free_nid(sbi, nid, true, false); if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS) goto out; @@ -1988,7 +1994,7 @@ static void scan_free_nid_bits(struct f2fs_sb_info *sbi) addr = le32_to_cpu(nat_in_journal(journal, i).block_addr); nid = le32_to_cpu(nid_in_journal(journal, i)); if (addr == NULL_ADDR) - add_free_nid(sbi, nid, true); + add_free_nid(sbi, nid, true, false); else remove_free_nid(sbi, nid); } @@ -2053,7 +2059,7 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount) addr = le32_to_cpu(nat_in_journal(journal, i).block_addr); nid = le32_to_cpu(nid_in_journal(journal, i)); if (addr == NULL_ADDR) - add_free_nid(sbi, nid, true); + add_free_nid(sbi, nid, true, false); else remove_free_nid(sbi, nid); } @@ -2499,11 +2505,7 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, nat_reset_flag(ne); __clear_nat_cache_dirty(NM_I(sbi), set, ne); if (nat_get_blkaddr(ne) == NULL_ADDR) { - add_free_nid(sbi, nid, false); - spin_lock(&NM_I(sbi)->nid_list_lock); - NM_I(sbi)->available_nids++; - update_free_nid_bitmap(sbi, nid, true, false); - spin_unlock(&NM_I(sbi)->nid_list_lock); + add_free_nid(sbi, nid, false, true); } else { spin_lock(&NM_I(sbi)->nid_list_lock); update_free_nid_bitmap(sbi, nid, false, false); -- 2.7.4