From mboxrd@z Thu Jan 1 00:00:00 1970 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 6215FC25B75 for ; Tue, 7 May 2024 08:44:13 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id F1D696B00A1; Tue, 7 May 2024 04:44:12 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id EA5EB6B00A3; Tue, 7 May 2024 04:44:12 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D46706B00A4; Tue, 7 May 2024 04:44:12 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id B459D6B00A1 for ; Tue, 7 May 2024 04:44:12 -0400 (EDT) Received: from smtpin07.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 3C77E1A0635 for ; Tue, 7 May 2024 08:44:12 +0000 (UTC) X-FDA: 82090962744.07.EAD11B3 Received: from mail-ua1-f54.google.com (mail-ua1-f54.google.com [209.85.222.54]) by imf05.hostedemail.com (Postfix) with ESMTP id 74276100004 for ; Tue, 7 May 2024 08:44:10 +0000 (UTC) Authentication-Results: imf05.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b="XzdR/R8Y"; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf05.hostedemail.com: domain of 21cnbao@gmail.com designates 209.85.222.54 as permitted sender) smtp.mailfrom=21cnbao@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1715071450; 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:in-reply-to:references:references:dkim-signature; bh=ODRMoOSN1diJVx7KLKg7xNhRk1uFo6RCS+/6a6GHJH4=; b=8VIZiMC9nZEjsIR8uJ1znT2RGat/Q9MCG9rUEM1lWTSOS3eYadoSnM4QovvEoQqRSJFDkA 8j02jkvbw4WgARexI4R1fYEex3Q2Va+Jx4ymisrJsUzvnG/PIF+U21nrXemu7IAA+CX+GG iZJZ9zQIHL+MpnwjdBItQzVJ3YmN+HA= ARC-Authentication-Results: i=1; imf05.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b="XzdR/R8Y"; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf05.hostedemail.com: domain of 21cnbao@gmail.com designates 209.85.222.54 as permitted sender) smtp.mailfrom=21cnbao@gmail.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1715071450; a=rsa-sha256; cv=none; b=d3LxD6PxXgrXXcaKTevh3TmoA8S7Qvk+EmxybCHM4wS6OFVj7p21B0bPrW45Ret1tcig3G aNmSwlBi+UrsRVQiTnQstnxdtkFgf+6CJAvsCGzy2XYS2LJzxOIazgzFLdDz+WYw5X8INo EF3rej8v57tn/6bBKivh0hh6vvD/qIw= Received: by mail-ua1-f54.google.com with SMTP id a1e0cc1a2514c-7f81be2539bso27343241.3 for ; Tue, 07 May 2024 01:44:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1715071449; x=1715676249; darn=kvack.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=ODRMoOSN1diJVx7KLKg7xNhRk1uFo6RCS+/6a6GHJH4=; b=XzdR/R8YFdVOjjCv/+5SdHe4/mcnFox2fmz8vWsssBeycZavPcQFnC0iisVcbeTPsv FMT36rIEVIcAjm2ihuJmpAEVTUFhaTz5+WWiZ61hSsr28xtB3b4igccfpUi+iHXNeXlP VEmJ9ARFjxrjEPhFV+FHWISSJH9pXkMC/ZXzaLJw87UI5G4BD5YJnWDeacY5rn2VJpDY KkWXc7/Jtooac0xVfgJ/arUx+5Lr/hN7fkbvw9BWMYMgdO/HFz9vwO5gTkWZAWYD8l98 LaACuOMMjKlnyApjxcvuEvL9vfVo0A9xiZ6xBnDc90htpz0XaEYNURpOxbQY3121ncR7 j4IA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715071449; x=1715676249; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ODRMoOSN1diJVx7KLKg7xNhRk1uFo6RCS+/6a6GHJH4=; b=AABirMQt0oGwvM5U8mGxptnYQAyzbyTpgMiyG82HXNUZRzCz2z31JdiJi3iZFBaIUO 7iiWnXOgDV7o6zH/aVurY+/dGv712jSCmOCZn/1b7S/A/ev1n3AHv7VlF6sqyXHUu5Zy sg4Nt98tKvNG+IIR8cjRBHIbWbu1FPWjqCCYo56aQqL9CgkjqDrFYLVXGgZa0ofpey2U OCzIHYLc8siT1rphNe6cev4HN+VBul6/GenS9IPxt7n4CsZTwxm8vOMs9+ZpIdS55vhC 5lewbbtPkCqYMK9d4qtVxbFucFFWhCFYKZYeLclEpTO9Ispuuq8fW01zz0XWRg3AF4Wp ndRQ== X-Forwarded-Encrypted: i=1; AJvYcCUz8jpTZbsp/+mrBB6n1NeMMaKZ9gxnYlXfAPzBlPGsFGxAdYdeQ/039ztbdi3e1R70P42j7iMJiQm/aTO8WvIyIak= X-Gm-Message-State: AOJu0YweIUspkZdG0Ehq4Jmk7yLrdzJr4AJI/HTMTByZl95mVDW4nQ/h KxUGMSSP/nxaFW8UGALLlTZwYgoybFxgN22/YWuDQCaPVzbYt/f4JvmfJq5jtNTLwf+xznTFKcA nY4DHTkNepZpRJL27okoFslw8Zxp88N3CHc0= X-Google-Smtp-Source: AGHT+IFRm+u1TMMF+DSEq8KB/DMop4tTV3wwnpZvVMbdJ1AZSLjQbshG5zuMLlHHYPrX4Jn3rNflzz46PobqEQA0YzQ= X-Received: by 2002:a67:f315:0:b0:47b:dffe:107 with SMTP id p21-20020a67f315000000b0047bdffe0107mr10250410vsf.1.1715071449431; Tue, 07 May 2024 01:44:09 -0700 (PDT) MIME-Version: 1.0 References: <20240503005023.174597-1-21cnbao@gmail.com> <20240503005023.174597-7-21cnbao@gmail.com> <0b4d4d4b-91d8-4fd5-af4e-aebe9ee08b89@arm.com> <5b770715-7516-42a8-9ea0-3f61572d92af@redhat.com> <7dc2084e-d8b1-42f7-b854-38981839f82e@redhat.com> In-Reply-To: <7dc2084e-d8b1-42f7-b854-38981839f82e@redhat.com> From: Barry Song <21cnbao@gmail.com> Date: Tue, 7 May 2024 20:43:57 +1200 Message-ID: Subject: Re: [PATCH v3 6/6] mm: swap: entirely map large folios found in swapcache To: David Hildenbrand Cc: Ryan Roberts , akpm@linux-foundation.org, linux-mm@kvack.org, baolin.wang@linux.alibaba.com, chrisl@kernel.org, hanchuanhua@oppo.com, hannes@cmpxchg.org, hughd@google.com, kasong@tencent.com, linux-kernel@vger.kernel.org, surenb@google.com, v-songbaohua@oppo.com, willy@infradead.org, xiang@kernel.org, ying.huang@intel.com, yosryahmed@google.com, yuzhao@google.com, ziy@nvidia.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Rspamd-Server: rspam01 X-Stat-Signature: 91i7hfzq5ybjpsnwpjwp8pbzfp7fksex X-Rspam-User: X-Rspamd-Queue-Id: 74276100004 X-HE-Tag: 1715071450-610060 X-HE-Meta: U2FsdGVkX1+g0XPGZ/Q1HXu3T1fRpgu2uuQKxuege+2h2ygh5a6uwc2LWFOal6byNaiczi/Ua/3O0foynjKJMmz7QWJ+4ugJQDKrwhsSuDorp43+RDZB7CSi5C19ImFdL3KWp802BxOg00tYDPALLtP4q3Suy/ZaId5GWbSC0pBS0ZdEX/7tg5ltE2AvLb8AQUMlEJZdQi9K4DTjZK3L9ys96mm/o14JimbeUP1AEK3TbVOpZfzyBMWNzS+E6CE8wiMJ7JVn0LnJLBEUiH+v9Ii3V8xM/3slNkl/OT/mUaShVSodrngM1NJQUUIHjT4TMf0aUWg8ZAHjfQoQINeeOdexGlxXeCmbWeJH4FfqrIqlbSrP/yaNqCLKQCRhKDgrJLzqC9WC6EP6kOJ8kjbxO8n+qdpeUP0lkvAc4yo1Iu1s8p+aFJyoUkO58q9pqG5DlIo2C2XNRZBBLYih9Jg8N+W3akFlLs8ywRUNhf//6yBhE8oqz/qOXuwgcrRd2FEFe+NtpRxcBCmRl0RxPjRdGJWp8vTlSQ0Q5xlsPfGxwkKa4F0SjsFHnh15qt+cRd9+s8u8hBe+ZmPDH9blSwO+00rorUp6V1IwVclvLTMHqO/aqAGYbQIl64JPvqinCiRvxiWRtui2NQJ24SojJ41hl+pli5GldHPQrLcRc9xJHnuBRL/198h6tpbdjw0gLPiyl36mo9CZcncbnuidFk7ds/IT1ZEt0kg7X+cFRu15RNRuRd4a+AjUFGYr41F1RwWHlBYo3htdZIuGGktVeS7MN9cOPXgU7gj9CFJwTbX7uYTQdP43aKnnNvmS2WkDVDktbIw2DNdRzv8qiU+hWQgBi7inUsFdHh6tns98Mg7DebHTiFgjZYH4SIn+VscnNdyb7djDQ3//QKTu+cZCmW/+1bQDFzoSRITvFAMEud/bhvUmgb4ZR1GDueAdgEKE/pbPxhxiVBktr90Tt6jZd1j huW/rkzi c9d7amH8QmMSm76fREUGEEB7B0x1i4wp6iA4JWA0sknVEeXasHlUxxZrdX8uMQ7uO3agY39d8/0ic6kI9iSymmgWZuE09XofM7hoXL9AltcRnDPLtOtHPSnTpUE69+k6FDmC11/c5xr1fjs/2MbXuJVUmXeh5nasTfqEye1JCxJbnuwFORW4PiNxzj/RHlr7pQC2nyelCp/hiXuziXGPPuoL4GbbyNVUqBpcrj9M8dq7OUx/7+qvM5LJV+U7dsUmOMau2QMklMa7/x5YWNbDQMl6xYsqbcOz4qCJtvmkVCc23KQiGRgIIKGeIHXKiY5z2PdEn5uYFfuGiZqU5IBGETqD3WyAtPwfdZm11v+okgJTa6zLjbhX/e6xOkfTHEGly3whlZcv7zwJ7ItZm2JUlVuC9MdYHxGwRHH8f/mkJ0aWk+8gdeohyvJNB55cLdkme/Act1JRReSvkqSEfJ7zGVpnIk+YRHF3tYIxmo76Wn4POwUDgPL6T5UIxAjiJZ8VObvSw2al4LoPsr48= 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: On Tue, May 7, 2024 at 8:24=E2=80=AFPM David Hildenbrand = wrote: > > On 07.05.24 00:58, Barry Song wrote: > > On Tue, May 7, 2024 at 1:16=E2=80=AFAM David Hildenbrand wrote: > >> > >> On 06.05.24 14:58, Barry Song wrote: > >>> On Tue, May 7, 2024 at 12:38=E2=80=AFAM Barry Song <21cnbao@gmail.com= > wrote: > >>>> > >>>> On Tue, May 7, 2024 at 12:07=E2=80=AFAM David Hildenbrand wrote: > >>>>> > >>>>> On 04.05.24 01:23, Barry Song wrote: > >>>>>> On Fri, May 3, 2024 at 6:50=E2=80=AFPM Ryan Roberts wrote: > >>>>>>> > >>>>>>> On 03/05/2024 01:50, Barry Song wrote: > >>>>>>>> From: Chuanhua Han > >>>>>>>> > >>>>>>>> When a large folio is found in the swapcache, the current implem= entation > >>>>>>>> requires calling do_swap_page() nr_pages times, resulting in nr_= pages > >>>>>>>> page faults. This patch opts to map the entire large folio at on= ce to > >>>>>>>> minimize page faults. Additionally, redundant checks and early e= xits > >>>>>>>> for ARM64 MTE restoring are removed. > >>>>>>>> > >>>>>>>> Signed-off-by: Chuanhua Han > >>>>>>>> Co-developed-by: Barry Song > >>>>>>>> Signed-off-by: Barry Song > >>>>>>> > >>>>>>> With the suggested changes below: > >>>>>>> > >>>>>>> Reviewed-by: Ryan Roberts > >>>>>>> > >>>>>>>> --- > >>>>>>>> mm/memory.c | 60 ++++++++++++++++++++++++++++++++++++++++++-= ---------- > >>>>>>>> 1 file changed, 48 insertions(+), 12 deletions(-) > >>>>>>>> > >>>>>>>> diff --git a/mm/memory.c b/mm/memory.c > >>>>>>>> index 22e7c33cc747..940fdbe69fa1 100644 > >>>>>>>> --- a/mm/memory.c > >>>>>>>> +++ b/mm/memory.c > >>>>>>>> @@ -3968,6 +3968,10 @@ vm_fault_t do_swap_page(struct vm_fault *= vmf) > >>>>>>>> pte_t pte; > >>>>>>>> vm_fault_t ret =3D 0; > >>>>>>>> void *shadow =3D NULL; > >>>>>>>> + int nr_pages =3D 1; > >>>>>>>> + unsigned long page_idx =3D 0; > >>>>>>>> + unsigned long address =3D vmf->address; > >>>>>>>> + pte_t *ptep; > >>>>>>> > >>>>>>> nit: Personally I'd prefer all these to get initialised just befo= re the "if > >>>>>>> (folio_test_large()..." block below. That way it is clear they ar= e fresh (incase > >>>>>>> any logic between here and there makes an adjustment) and its cle= ar that they > >>>>>>> are only to be used after that block (the compiler will warn if u= sing an > >>>>>>> uninitialized value). > >>>>>> > >>>>>> right. I agree this will make the code more readable. > >>>>>> > >>>>>>> > >>>>>>>> > >>>>>>>> if (!pte_unmap_same(vmf)) > >>>>>>>> goto out; > >>>>>>>> @@ -4166,6 +4170,36 @@ vm_fault_t do_swap_page(struct vm_fault *= vmf) > >>>>>>>> goto out_nomap; > >>>>>>>> } > >>>>>>>> > >>>>>>>> + ptep =3D vmf->pte; > >>>>>>>> + if (folio_test_large(folio) && folio_test_swapcache(folio)= ) { > >>>>>>>> + int nr =3D folio_nr_pages(folio); > >>>>>>>> + unsigned long idx =3D folio_page_idx(folio, page); > >>>>>>>> + unsigned long folio_start =3D vmf->address - idx *= PAGE_SIZE; > >>>>>>>> + unsigned long folio_end =3D folio_start + nr * PAG= E_SIZE; > >>>>>>>> + pte_t *folio_ptep; > >>>>>>>> + pte_t folio_pte; > >>>>>>>> + > >>>>>>>> + if (unlikely(folio_start < max(vmf->address & PMD_= MASK, vma->vm_start))) > >>>>>>>> + goto check_folio; > >>>>>>>> + if (unlikely(folio_end > pmd_addr_end(vmf->address= , vma->vm_end))) > >>>>>>>> + goto check_folio; > >>>>>>>> + > >>>>>>>> + folio_ptep =3D vmf->pte - idx; > >>>>>>>> + folio_pte =3D ptep_get(folio_ptep); > >>>>>>>> + if (!pte_same(folio_pte, pte_move_swp_offset(vmf->= orig_pte, -idx)) || > >>>>>>>> + swap_pte_batch(folio_ptep, nr, folio_pte) !=3D= nr) > >>>>>>>> + goto check_folio; > >>>>>>>> + > >>>>>>>> + page_idx =3D idx; > >>>>>>>> + address =3D folio_start; > >>>>>>>> + ptep =3D folio_ptep; > >>>>>>>> + nr_pages =3D nr; > >>>>>>>> + entry =3D folio->swap; > >>>>>>>> + page =3D &folio->page; > >>>>>>>> + } > >>>>>>>> + > >>>>>>>> +check_folio: > >>>>>>> > >>>>>>> Is this still the correct label name, given the checks are now ab= ove the new > >>>>>>> block? Perhaps "one_page" or something like that? > >>>>>> > >>>>>> not quite sure about this, as the code after one_page can be multi= ple_pages. > >>>>>> On the other hand, it seems we are really checking folio after "ch= eck_folio" > >>>>>> :-) > >>>>>> > >>>>>> > >>>>>> BUG_ON(!folio_test_anon(folio) && folio_test_mappedtodisk(folio)); > >>>>>> BUG_ON(folio_test_anon(folio) && PageAnonExclusive(page)); > >>>>>> > >>>>>> /* > >>>>>> * Check under PT lock (to protect against concurrent fork() sharin= g > >>>>>> * the swap entry concurrently) for certainly exclusive pages. > >>>>>> */ > >>>>>> if (!folio_test_ksm(folio)) { > >>>>>> > >>>>>> > >>>>>>> > >>>>>>>> + > >>>>>>>> /* > >>>>>>>> * PG_anon_exclusive reuses PG_mappedtodisk for anon pa= ges. A swap pte > >>>>>>>> * must never point at an anonymous page in the swapcac= he that is > >>>>>>>> @@ -4225,12 +4259,13 @@ vm_fault_t do_swap_page(struct vm_fault = *vmf) > >>>>>>>> * We're already holding a reference on the page but ha= ven't mapped it > >>>>>>>> * yet. > >>>>>>>> */ > >>>>>>>> - swap_free_nr(entry, 1); > >>>>>>>> + swap_free_nr(entry, nr_pages); > >>>>>>>> if (should_try_to_free_swap(folio, vma, vmf->flags)) > >>>>>>>> folio_free_swap(folio); > >>>>>>>> > >>>>>>>> - inc_mm_counter(vma->vm_mm, MM_ANONPAGES); > >>>>>>>> - dec_mm_counter(vma->vm_mm, MM_SWAPENTS); > >>>>>>>> + folio_ref_add(folio, nr_pages - 1); > >>>>>>>> + add_mm_counter(vma->vm_mm, MM_ANONPAGES, nr_pages); > >>>>>>>> + add_mm_counter(vma->vm_mm, MM_SWAPENTS, -nr_pages); > >>>>>>>> pte =3D mk_pte(page, vma->vm_page_prot); > >>>>>>>> > >>>>>>>> /* > >>>>>>>> @@ -4240,34 +4275,35 @@ vm_fault_t do_swap_page(struct vm_fault = *vmf) > >>>>>>>> * exclusivity. > >>>>>>>> */ > >>>>>>>> if (!folio_test_ksm(folio) && > >>>>>>>> - (exclusive || folio_ref_count(folio) =3D=3D 1)) { > >>>>>>>> + (exclusive || (folio_ref_count(folio) =3D=3D nr_pages = && > >>>>>>>> + folio_nr_pages(folio) =3D=3D nr_pages))= ) { > >>>>>>> > >>>>>>> I think in practice there is no change here? If nr_pages > 1 then= the folio is > >>>>>>> in the swapcache, so there is an extra ref on it? I agree with th= e change for > >>>>>>> robustness sake. Just checking my understanding. > >>>>>> > >>>>>> This is the code showing we are reusing/(mkwrite) a folio either > >>>>>> 1. we meet a small folio and we are the only one hitting the small= folio > >>>>>> 2. we meet a large folio and we are the only one hitting the large= folio > >>>>>> > >>>>>> any corner cases besides the above two seems difficult. for exampl= e, > >>>>>> > >>>>>> while we hit a large folio in swapcache but if we can't entirely m= ap it > >>>>>> (nr_pages=3D=3D1) due to partial unmap, we will have folio_ref_cou= nt(folio) > >>>>>> =3D=3D nr_pages =3D=3D 1 > >>>>> > >>>>> No, there would be other references from the swapcache and > >>>>> folio_ref_count(folio) > 1. See my other reply. > >>>> > >>>> right. can be clearer by: > >>> > >>> Wait, do we still need folio_nr_pages(folio) =3D=3D nr_pages even if = we use > >>> folio_ref_count(folio) =3D=3D 1 and moving folio_ref_add(folio, nr_pa= ges - 1)? > >> > >> I don't think that we will "need" it. > >> > >>> > >>> one case is that we have a large folio with 16 PTEs, and we unmap > >>> 15 swap PTE entries, thus we have only one swap entry left. Then > >>> we hit the large folio in swapcache. but we have only one PTE thus w= e will > >>> map only one PTE. lacking folio_nr_pages(folio) =3D=3D nr_pages, we r= euse the > >>> large folio for one PTE. with it, do_wp_page() will migrate the large > >>> folio to a small one? > >> > >> We will set PAE bit and do_wp_page() will unconditionally reuse that p= age. > >> > >> Note that this is the same as if we had pte_swp_exclusive() set and > >> would have run into "exclusive=3Dtrue" here. > >> > >> If we'd want a similar "optimization" as we have in > >> wp_can_reuse_anon_folio(), you'd want something like > >> > >> exclusive || (folio_ref_count(folio) =3D=3D 1 && > >> (!folio_test_large(folio) || nr_pages > 1) > > > > I feel like > > > > A : !folio_test_large(folio) || nr_pages > 1 > > > > equals > > > > B: folio_nr_pages(folio) =3D=3D nr_pages > > > > if folio is small, folio_test_large(folio) is false, both A and B will= be true; > > if folio is large, and we map the whole large folio, A will be true > > because of nr_pages > 1; > > B is also true; > > if folio is large, and we map single one PTE, A will be false; > > B is also false, because nr_pages =3D=3D 1 but folio_nr_pages(folio) >= 1; > > > > right? > > Let's assume a single subpage of a large folio is no longer mapped. > Then, we'd have: > > nr_pages =3D=3D folio_nr_pages(folio) - 1. > > You could simply map+reuse most of the folio without COWing. yes. This is good but the pte which is no longer mapped could be anyone within the nr_pages PTEs. so it could be quite tricky for set_ptes. > > Once we support COW reuse of PTE-mapped THP we'd do the same. Here, it's > just easy to detect that the folio is exclusive (folio_ref_count(folio) > =3D=3D 1 before mapping anything). > > If you really want to mimic what do_wp_page() currently does, you should > have: > > exclusive || (folio_ref_count(folio) =3D=3D 1 && !folio_test_large(folio)= ) I actually dislike the part that do_wp_page() handles the reuse of a large folio which is entirely mapped. For example, A forks B, B exit, we write A's large folio, we get nr_pages CoW of small folios. Ideally, we can reuse the whole folios for writing. > > Personally, I think we should keep it simple here and use: > > exclusive || folio_ref_count(folio) =3D=3D 1 I feel this is still better than exclusive || (folio_ref_count(folio) =3D=3D 1 && !folio_test_large(folio)) as we reuse the whole large folio. the do_wp_page() behaviour doesn't have this. > > IMHO, that's as clear as it gets. I agree this is clear. But I wonder if there is a possibility to optimize. Using your instance, "Let's assume a single subpage of a large folio is no longer mapped." For a large folio with 16 PTEs and in case we have unmapped one of them. Thus, we have 15 swap entries left. The first PTE which gets page faults will reuse the whole large folio havin= g "exclusive || folio_ref_count(folio) =3D=3D 1" only. The left 14 will allocate 14 small folios(swapcache has been dropped), thus, we use 16 + 14 =3D 30 pages memory. with either A : !folio_test_large(folio) || nr_pages > 1 or B: folio_nr_pages(folio) =3D=3D nr_pages We consume 15 pages. > > -- > Cheers, > > David / dhildenb Thanks Barry