From patchwork Mon Apr 1 08:17:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "zhaoyang.huang" X-Patchwork-Id: 13612602 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 69D8ECD128A for ; Mon, 1 Apr 2024 08:18:27 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 848616B0082; Mon, 1 Apr 2024 04:18:26 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 7D04B6B0083; Mon, 1 Apr 2024 04:18:26 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 671096B0085; Mon, 1 Apr 2024 04:18:26 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 480C06B0082 for ; Mon, 1 Apr 2024 04:18:26 -0400 (EDT) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id C324C80493 for ; Mon, 1 Apr 2024 08:18:25 +0000 (UTC) X-FDA: 81960260970.11.AE8E8ED Received: from SHSQR01.spreadtrum.com (mx1.unisoc.com [222.66.158.135]) by imf30.hostedemail.com (Postfix) with ESMTP id 1D78780005 for ; Mon, 1 Apr 2024 08:18:21 +0000 (UTC) Authentication-Results: imf30.hostedemail.com; dkim=none; spf=pass (imf30.hostedemail.com: domain of zhaoyang.huang@unisoc.com designates 222.66.158.135 as permitted sender) smtp.mailfrom=zhaoyang.huang@unisoc.com; dmarc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1711959503; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:in-reply-to: references; bh=oLG6POi8dZf1sD4NuyA0FIN3gCJ1AD3jB82AeTzvKq8=; b=hebWsiY8jmBfT3Mvn1rwUVT/noJA1fhSTvo2PCcQNjJ3H/LKQbvCq+tlWvTEFVMy49mUpt Q3q5CvSwwEUxPij0Z4tOH9DS3VcAA7Jdc0l2mrxqWDyBCpfxippEvmlrvF1cypbXIpjUf5 C8XLsH6w8+YK27P8yFb2CDylMn1j7jE= ARC-Authentication-Results: i=1; imf30.hostedemail.com; dkim=none; spf=pass (imf30.hostedemail.com: domain of zhaoyang.huang@unisoc.com designates 222.66.158.135 as permitted sender) smtp.mailfrom=zhaoyang.huang@unisoc.com; dmarc=none ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1711959503; a=rsa-sha256; cv=none; b=YK9ABJyWW30UsKOpoY2y3akNUMNgX/Jx6zqVFt5kBCVqybFIPWNLDhafP9bxUd6EWxSpqq SLmoaqS0CIWcCAiub1Dae42vCHlVfkCNeMgkHQc7U0cxX6vfYWjPJWKDFzgILUvprFQyJk oG9s9RyZ+oR/xPUqCPP2hoDNGqbw/S4= Received: from dlp.unisoc.com ([10.29.3.86]) by SHSQR01.spreadtrum.com with ESMTP id 4318HlFb028029; Mon, 1 Apr 2024 16:17:47 +0800 (+08) (envelope-from zhaoyang.huang@unisoc.com) Received: from SHDLP.spreadtrum.com (bjmbx01.spreadtrum.com [10.0.64.7]) by dlp.unisoc.com (SkyGuard) with ESMTPS id 4V7P3G46yjz2MDQdm; Mon, 1 Apr 2024 16:15:54 +0800 (CST) Received: from bj03382pcu01.spreadtrum.com (10.0.73.40) by BJMBX01.spreadtrum.com (10.0.64.7) with Microsoft SMTP Server (TLS) id 15.0.1497.23; Mon, 1 Apr 2024 16:17:45 +0800 From: "zhaoyang.huang" To: Andrew Morton , NeilBrown , , , Zhaoyang Huang , CC: Matthew Wilcox , Christoph Hellwig Subject: [PATCHv2 1/1] mm: fix unproperly folio_put by changing API in read_pages Date: Mon, 1 Apr 2024 16:17:34 +0800 Message-ID: <20240401081734.1433755-1-zhaoyang.huang@unisoc.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Originating-IP: [10.0.73.40] X-ClientProxiedBy: SHCAS03.spreadtrum.com (10.0.1.207) To BJMBX01.spreadtrum.com (10.0.64.7) X-MAIL: SHSQR01.spreadtrum.com 4318HlFb028029 X-Rspamd-Queue-Id: 1D78780005 X-Rspam-User: X-Stat-Signature: hkefi83aoiqw5bep85prnjz3km4oh76f X-Rspamd-Server: rspam01 X-HE-Tag: 1711959501-891672 X-HE-Meta: U2FsdGVkX1+CY9ify30BeERe2IiqGCVTrcAHq/yzaAqflurIS5AFWhf8QUDyM+QwnwO8zyFU9VWFih4oPgcinQiLS3uPOQs78yGx+0QojibrS/f4LSQy2PAcrGcMASUfv5SAwCP3jkAOnuYmOBw30hMT4OQApafzS1bVdou2+dT9a9l9PiRZhclK1uWOceCwUqkUz3VooHjT71LJgM7HksS4wPWldxvJN4rPmi8n50TTc6sxKlv0MEMfOjiOKSbZgUkKI06vbQXUJ1YSgVFtKrYELFaTI11nuuxiUhqHkrECrMSZf+1UBE2D8ptiu2XQBxvGUMwfKNV5H73VwvGAXurSth9UtjSDsqmh3GAfCMMt/uwB+9m88eRMG3GaUKRf7ZBn20YUd6U/0Mf1+NrTeMuoljv7ZerH0QqfHm3YMLKLQ4RX3ao0C+g63BmMa8dccvRfK7yRLyh9qLsVuDQU/wIziNnGySxYnEcq/IONFxqSxCSI3MlgQDH0u0nOJvXXOMgkehPsv7DLgEUv2nuw6+nhTZV+2GywAa4747FAEriNf68ZayqqoGO6O+ZIJz6dy5fvBVrPimnc8rsrDLO6aWnphW3zF4Z5vn5YK0nPrr6ODxhO8kvMswcSNQaUMQIfbfx1U+uZYR/V7w0MesjHQPQplaSlp78vUqExdVRTcIIqL5qWu7AL9uYfHnopX53yRLI9CD8HnAc7znhbOht/n8W/ift5au1NMbwyQsLQ/hwLgTr0trINK8MLqs7Y0u26B+RI2JPRLm9H6VZdOqIZTQAdQ4gfGk+0Rgzkq872+BaRyGZ0wq83TBzfFvAOcY8VBeg0eQ4ZzogUAAqlS4waCnw7AeLzE1cyVN08iltMNCU1ExV1PE1zpAJyvuAv+ZAw4iWXmumkgmBzXAas8AOlChgYD8myi8XQJrityn7l+F+hXno9GpQkhTd17qZqRoTZaX8bJvWK8Ek0F38N2UT KE0Anrjd 3RO5PC/8os+WSN0MlEqI5dcKb5WeaGh2Yw/U5bhuiPWH6+Icq5845c9Kt52WPKfAYj6HI/MsNdzgCHHSJWCm8vskCJHhFdeUVpatI6gxbx67gnzS2DmDj3DbhET0cMSysMwaUOBVqSDas7K/x2T81gumISnV/aqGTDPpFPAmBAcLnNXhTS/OknLuu7ZanqyHEBuBU X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Zhaoyang Huang An VM_BUG_ON in step 9 of [1] could happen as the refcnt is dropped unproperly during the procedure of read_pages()->readahead_folio->folio_put. This is introduced by commit 9fd472af84ab ("mm: improve cleanup when ->readpages doesn't process all pages")'. key steps of[1] in brief: 2'. Thread_truncate get folio to its local fbatch by find_get_entry in step 2 7'. Last refcnt remained which is not as expect as from alloc_pages but from thread_truncate's local fbatch in step 7 8'. Thread_reclaim succeed to isolate the folio by the wrong refcnt(not the value but meaning) in step 8 9'. Thread_truncate hit the VM_BUG_ON in step 9 [1] Thread_readahead: 0. folio = filemap_alloc_folio(gfp_mask, 0); (refcount 1: alloc_pages) 1. ret = filemap_add_folio(mapping, folio, index + i, gfp_mask); (refcount 2: alloc_pages, page_cache) Thread_truncate: 2. folio = find_get_entries(&fbatch_truncate); (refcount 3: alloc_pages, page_cache, fbatch_truncate)) Thread_readahead: 3. Then we call read_pages() First we call ->readahead() which for some reason stops early. 4. Then we call readahead_folio() which calls folio_put() (refcount 2: page_cache, fbatch_truncate) 5. Then we call folio_get() (refcount 3: page_cache, fbatch_truncate, read_pages_temp) 6. Then we call filemap_remove_folio() (refcount 2: fbatch_truncate, read_pages_temp) 7. Then we call folio_unlock() and folio_put() (refcount 1: fbatch_truncate) Thread_reclaim: 8. collect the page from LRU and call shrink_inactive_list->isolate_lru_folios shrink_inactive_list { isolate_lru_folios { if (!folio_test_lru(folio)) //false bail out; if (!folio_try_get(folio)) //false bail out; } } (refcount 2: fbatch_truncate, reclaim_isolate) 9. call shrink_folio_list->__remove_mapping shrink_folio_list() { folio_try_lock(folio); __remove_mapping() { if (!folio_ref_freeze(2)) //false bail out; } folio_unlock(folio) list_add(folio, free_folios); } (folio has refcount 0) Thread_truncate: 10. Thread_truncate will hit the refcnt VM_BUG_ON(refcnt == 0) in release_pages->folio_put_testzero truncate_inode_pages_range { folio = find_get_entries(&fbatch_truncate); truncate_inode_pages(&fbatch_truncate); folio_fbatch_release(&fbatch_truncate); { folio_put_testzero(folio); //VM_BUG_ON here } } fix: commit 9fd472af84ab ("mm: improve cleanup when ->readpages doesn't process all pages")' Signed-off-by: Zhaoyang Huang --- patch v2: update commit message --- --- mm/readahead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/readahead.c b/mm/readahead.c index 130c0e7df99f..657736200a92 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -163,7 +163,7 @@ static void read_pages(struct readahead_control *rac) * may be used to size the next readahead, so make sure * they accurately reflect what happened. */ - while ((folio = readahead_folio(rac)) != NULL) { + while ((folio = __readahead_folio(rac)) != NULL) { unsigned long nr = folio_nr_pages(folio); folio_get(folio);