From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A247B33D4EC for ; Mon, 14 Sep 2026 03:52:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789357930; cv=none; b=VhNSB6OOGm8EiNxmNxnyJ7NZ1cXbRoCrD2sKxMXDNmmkPAPc7cTqIhQf3sZHv/+EDHFf/TQZxcBzfrR9aJEthbIhXAeIWKoB2ifxEQE/geEJlKDP0PWiiXGFadD20f58b1/Pd0EBzdEhOO5ssMBUNxJSbHpLvSzq86Xl85Mb9oA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789357930; c=relaxed/simple; bh=0+ce3+Is85s676N+otssyzk9OIUqhTinrVaxPx2ATwQ=; h=Date:To:From:Subject:Message-Id; b=HAtcDhAhNc2sEal7UPcMFOa6Y6jaBc0nW6w+hQA4aGr8DAm4+89dvnF/TgxtPTDojixJ1bgHG2hGB7hXNoJ0DsY4oMxx6eN4QdfZiOT3H89VN9aybme2X3pMcOroz+PgsKYOv5zZVXtJutzJWSOU8ApaEOiYz5Op4vlGydWtYlo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b=L9DwV+06; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b="L9DwV+06" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 39ED61F000FF; Mon, 14 Sep 2026 03:52:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux-foundation.org; s=korg; t=1789357928; bh=AyNXNebNEHVK5dmXLfIv0YwV6iqgJTLV0vTQE+P7Xpo=; h=Date:To:From:Subject; b=L9DwV+06Gil8FFtuycdoAMpe04asQ+n8BJ58OqNYhrqsoNtyKcu6LArRz209XHkjg /ucGccXuLrKJZx/e/0MjOoSmokw612zJ/YwlGtMmzd5PU8qiveJQu+l6QLUiXC9/8W 8cIiaNC/yvlV9g+AIYFZj2JIvJlH9vjxLBdyDQJM= Date: Sun, 13 Sep 2026 20:52:07 -0700 To: mm-commits@vger.kernel.org,zbestahu@gmail.com,xiang@kernel.org,willy@infradead.org,jefflexu@linux.alibaba.com,jack@suse.cz,hongbohbli@tencent.com,guochunhai@vivo.com,dhavale@google.com,david@kernel.org,chao@kernel.org,ziy@nvidia.com,akpm@linux-foundation.org From: Andrew Morton Subject: + erofs-mm-pagemap-add-readahead_folio_last-to-avoid-folio-private.patch added to mm-new branch Message-Id: <20260914035208.39ED61F000FF@smtp.kernel.org> Precedence: bulk X-Mailing-List: mm-commits@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: The patch titled Subject: erofs: mm/pagemap: add readahead_folio_last() to avoid folio->private has been added to the -mm mm-new branch. Its filename is erofs-mm-pagemap-add-readahead_folio_last-to-avoid-folio-private.patch This patch will shortly appear at https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/erofs-mm-pagemap-add-readahead_folio_last-to-avoid-folio-private.patch This patch will later appear in the mm-new branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Note, mm-new is a provisional staging ground for work-in-progress patches, and acceptance into mm-new is a notification for others take notice and to finish up reviews. Please do not hesitate to respond to review feedback and post updated versions to replace or incrementally fixup patches in mm-new. The mm-new branch of mm.git is not included in linux-next If a few days of testing in mm-new is successful, the patch will me moved into mm.git's mm-unstable branch, which is included in linux-next Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next via various branches at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm and is updated there most days ------------------------------------------------------ From: Zi Yan Subject: erofs: mm/pagemap: add readahead_folio_last() to avoid folio->private Date: Sun, 13 Sep 2026 22:24:06 -0400 erofs needs to traverse readahead folios in reverse order to achieve maximum performance by 1. reading all folios from readahead_folio(); 2. storing the prior folio pointer in folio->private; 3. traverse from the last folio to the first one. Add readahead_folio_last() to achieve the same function without using folio->private. __readahead_advance() helper shares readahead_control adjustment code among __readahead_folio(), readahead_folio_last(), and __readahead_batch() by checking new private member, _forward, of readahead_control. It prepares for a future commit that replaces PG_private checks with !folio->private checks. After switching the checks, erofs's use of folio->private without bumping folio refcount can cause unexpected outcomes, e.g., in filemap_release_folio(), try_to_free_buffers() becomes reachable. No functional change intended. Assisted-by: LLM Link: https://lore.kernel.org/20260913-remove-pg_private-v4-8-848550f7574e@nvidia.com Signed-off-by: Zi Yan Signed-off-by: Andrew Morton Acked-by: David Hildenbrand (Arm) Cc: Yue Hu Cc: Jeffle Xu Cc: Sandeep Dhavale Cc: Hongbo Li Cc: Chunhai Guo Cc: Gao Xiang Cc: Chao Yu Cc: "Matthew Wilcox (Oracle)" Cc: Jan Kara --- fs/erofs/zdata.c | 13 +------- include/linux/pagemap.h | 60 ++++++++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 18 deletions(-) --- a/fs/erofs/zdata.c~erofs-mm-pagemap-add-readahead_folio_last-to-avoid-folio-private +++ a/fs/erofs/zdata.c @@ -1898,21 +1898,14 @@ static void z_erofs_readahead(struct rea struct inode *realinode = erofs_real_inode(sharedinode, &need_iput); Z_EROFS_DEFINE_FRONTEND(f, realinode, sharedinode, readahead_pos(rac)); unsigned int nrpages = readahead_count(rac); - struct folio *head = NULL, *folio; + struct folio *folio; int err; trace_erofs_readahead(realinode, readahead_index(rac), nrpages, false); z_erofs_pcluster_readmore(&f, rac, true); - while ((folio = readahead_folio(rac))) { - folio->private = head; - head = folio; - } - - /* traverse in reverse order for best metadata I/O performance */ - while (head) { - folio = head; - head = folio_get_private(folio); + /* traverse from last to first for best metadata I/O performance */ + while ((folio = readahead_folio_last(rac))) { err = z_erofs_scan_folio(&f, folio, true); if (err && err != -EINTR) erofs_err(realinode->i_sb, "readahead error at folio %lu @ nid %llu", --- a/include/linux/pagemap.h~erofs-mm-pagemap-add-readahead_folio_last-to-avoid-folio-private +++ a/include/linux/pagemap.h @@ -1415,6 +1415,7 @@ struct readahead_control { bool dropbehind; bool _workingset; unsigned long _pflags; + bool _forward; }; #define DEFINE_READAHEAD(ractl, f, r, m, i) \ @@ -1479,18 +1480,29 @@ void page_cache_async_readahead(struct a page_cache_async_ra(&ractl, folio, req_count); } +/* + * Adjust readahead_control to ensure next folio comes from + * [_index, _index + _nr_pages) afterwards and reset _batch_count. + */ +static inline void __readahead_advance(struct readahead_control *rac) +{ + if (rac->_forward) + rac->_index += rac->_batch_count; + + rac->_nr_pages -= rac->_batch_count; + rac->_batch_count = 0; +} + static inline struct folio *__readahead_folio(struct readahead_control *ractl) { struct folio *folio; BUG_ON(ractl->_batch_count > ractl->_nr_pages); - ractl->_nr_pages -= ractl->_batch_count; - ractl->_index += ractl->_batch_count; + __readahead_advance(ractl); + ractl->_forward = true; - if (!ractl->_nr_pages) { - ractl->_batch_count = 0; + if (!ractl->_nr_pages) return NULL; - } folio = xa_load(&ractl->mapping->i_pages, ractl->_index); VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); @@ -1516,6 +1528,39 @@ static inline struct folio *readahead_fo return folio; } +/** + * readahead_folio_last - Get the next folio to read, from the tail. + * @ractl: The current readahead request. + * + * Like readahead_folio(), but walks the range back-to-front. The folio is + * returned locked with its refcount dropped; the caller unlocks it once I/O + * completes. Compound folios are returned once, at their head index. + * + * Context: The folio is locked. + * Return: A pointer to the next folio, or %NULL when done. + */ +static inline struct folio *readahead_folio_last(struct readahead_control *ractl) +{ + struct folio *folio; + + /* Drop the previously returned batch from the remaining range. */ + __readahead_advance(ractl); + ractl->_forward = false; + + if (!ractl->_nr_pages) + return NULL; + + /* xa_load() follows sibling entries, so a tail index returns the head */ + folio = xa_load(&ractl->mapping->i_pages, + ractl->_index + ractl->_nr_pages - 1); + VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio); + + ractl->_batch_count = folio_nr_pages(folio); + + folio_put(folio); + return folio; +} + static inline unsigned int __readahead_batch(struct readahead_control *rac, struct page **array, unsigned int array_sz) { @@ -1524,9 +1569,8 @@ static inline unsigned int __readahead_b struct folio *folio; BUG_ON(rac->_batch_count > rac->_nr_pages); - rac->_nr_pages -= rac->_batch_count; - rac->_index += rac->_batch_count; - rac->_batch_count = 0; + __readahead_advance(rac); + rac->_forward = true; xas_set(&xas, rac->_index); rcu_read_lock(); _ Patches currently in -mm which might be from ziy@nvidia.com are mm-zsmalloc-replace-pg_private-with-pointer-comparison.patch perf-ring_buffer-stop-using-pg_private-as-aux-page-high-order-marker.patch xen-grant-table-stop-setting-pg_private-on-pages-for-grant-mapping.patch fscrypt-stop-setting-pg_private-on-bounce-page.patch mm-hugetlb-use-direct-assignment-instead-of-folio_change_private.patch f2fs-stop-using-pg_private.patch f2fs-convert-the-private-flag-helpers-to-folio-only.patch erofs-mm-pagemap-add-readahead_folio_last-to-avoid-folio-private.patch erofs-use-folio_attach-detach_private-instead-of-direct-assignment.patch mm-page-flags-check-page-folio-private-instead-of-pg_private.patch treewide-remove-folio_set-clear_private-usage.patch ceph-replace-pageprivate-with-page_private.patch md-md-bitmap-replace-pageprivate-with-page_private.patch buffer-replace-page_buffer-with-page_private-and-delete-it.patch treewide-remove-pageprivate-and-pg_private-from-comments-and-docs.patch mm-page-flags-remove-pg_private.patch usb-gadgetfs-do-not-warn-about-excessively-large-memory-allocations.patch