From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out30-112.freemail.mail.aliyun.com (out30-112.freemail.mail.aliyun.com [115.124.30.112]) (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 5A3C73D7D67 for ; Tue, 24 Mar 2026 08:22:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.112 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774340573; cv=none; b=BydzDQoUIaaPwgNaqAxJ9CLqawEniG4jASR8unKvW7c/rmKxrQahEh+2QMNEWNozgO13r4TPGl5v+uAcBUFONCh4FTypr5dWUIewLgV6nX7x4JZu82QTaNkyd8D/sJA9D2pEs0C2ZnRdfcgztcyEEX5OZ+W9NlEh3bA6C9LDrSc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774340573; c=relaxed/simple; bh=FE606MEqDuq40JDI76EgN1+ovBWy3B0vb8tpOIDsH90=; h=From:To:Cc:Subject:In-Reply-To:References:Date:Message-ID: MIME-Version:Content-Type; b=Mjut3ZHrKPYLDpaq8SFCvjJt8SbB+7U4Yn5LY63gKJjsxZe3gYtDSmtLK0PSacBk2B+xTeiF9xriLV9nJ6vMnCMSFBGH9juk0gDAJll1twj0RY+2wc907RkW6zlmlltE8IOfmuv/w0nTIfpck3U8G14Cz5wVIsGlMWNNm2QRveI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=H98pEyBb; arc=none smtp.client-ip=115.124.30.112 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="H98pEyBb" DKIM-Signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1774340560; h=From:To:Subject:Date:Message-ID:MIME-Version:Content-Type; bh=nBJkqxYu+t3pfuHu+5NDgnAbi4EbO8D0s9eWWjl7kao=; b=H98pEyBbkZoA34WdPez15FBdaTHO3vNsTWsMguqCQwkVcmiiM2yga1gu0uwiDaqRSyzR4+BEI8QrbcexxtkOinFSQz9st9npEEzcI3B4Kdml/e8WRWttcp44k5sWz10Ad46jg3zOSXrXJzCJmPlCQsPPv/8f6n28pWLctsyIsGQ= X-Alimail-AntiSpam:AC=PASS;BC=-1|-1;BR=01201311R411e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=maildocker-contentspam033032089153;MF=ying.huang@linux.alibaba.com;NM=1;PH=DS;RN=39;SR=0;TI=SMTPD_---0X.dt9XJ_1774340555; Received: from DESKTOP-5N7EMDA(mailfrom:ying.huang@linux.alibaba.com fp:SMTPD_---0X.dt9XJ_1774340555 cluster:ay36) by smtp.aliyun-inc.com; Tue, 24 Mar 2026 16:22:37 +0800 From: "Huang, Ying" To: Shivank Garg Cc: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: Re: [RFC PATCH v4 2/6] mm/migrate: skip data copy for already-copied folios In-Reply-To: <20260309120725.308854-8-shivankg@amd.com> (Shivank Garg's message of "Mon, 9 Mar 2026 12:07:25 +0000") References: <20260309120725.308854-3-shivankg@amd.com> <20260309120725.308854-8-shivankg@amd.com> Date: Tue, 24 Mar 2026 16:22:35 +0800 Message-ID: <87wlz1zlf8.fsf@DESKTOP-5N7EMDA> User-Agent: Gnus/5.13 (Gnus v5.13) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=ascii Shivank Garg writes: > Add a PAGE_ALREADY_COPIED flag to the dst->private migration state. > When set, __migrate_folio() skips folio_mc_copy() and performs > metadata-only migration. All callers currently pass > already_copied=false. The batch-copy path enables it in a later patch. > > Move the dst->private state enum earlier in the file so > __migrate_folio() and move_to_new_folio() can see PAGE_ALREADY_COPIED. > > Signed-off-by: Shivank Garg > --- > mm/migrate.c | 52 +++++++++++++++++++++++++++++++--------------------- > 1 file changed, 31 insertions(+), 21 deletions(-) > > diff --git a/mm/migrate.c b/mm/migrate.c > index 1bf2cf8c44dd..1d8c1fb627c9 100644 > --- a/mm/migrate.c > +++ b/mm/migrate.c > @@ -848,6 +848,18 @@ void folio_migrate_flags(struct folio *newfolio, struct folio *folio) > } > EXPORT_SYMBOL(folio_migrate_flags); > > +/* > + * To record some information during migration, we use unused private > + * field of struct folio of the newly allocated destination folio. > + * This is safe because nobody is using it except us. > + */ > +enum { > + PAGE_WAS_MAPPED = BIT(0), > + PAGE_WAS_MLOCKED = BIT(1), > + PAGE_ALREADY_COPIED = BIT(2), > + PAGE_OLD_STATES = PAGE_WAS_MAPPED | PAGE_WAS_MLOCKED | PAGE_ALREADY_COPIED, > +}; > + > /************************************************************ > * Migration functions > ***********************************************************/ > @@ -857,14 +869,20 @@ static int __migrate_folio(struct address_space *mapping, struct folio *dst, > enum migrate_mode mode) > { > int rc, expected_count = folio_expected_ref_count(src) + 1; > + bool already_copied = ((unsigned long)dst->private & PAGE_ALREADY_COPIED); > + > + if (already_copied) > + dst->private = NULL; > > /* Check whether src does not have extra refs before we do more work */ > if (folio_ref_count(src) != expected_count) > return -EAGAIN; > > - rc = folio_mc_copy(dst, src); > - if (unlikely(rc)) > - return rc; > + if (!already_copied) { > + rc = folio_mc_copy(dst, src); > + if (unlikely(rc)) > + return rc; > + } > > rc = __folio_migrate_mapping(mapping, dst, src, expected_count); > if (rc) > @@ -1088,7 +1106,7 @@ static int fallback_migrate_folio(struct address_space *mapping, > * 0 - success > */ > static int move_to_new_folio(struct folio *dst, struct folio *src, > - enum migrate_mode mode) > + enum migrate_mode mode, bool already_copied) > { > struct address_space *mapping = folio_mapping(src); > int rc = -EAGAIN; > @@ -1096,6 +1114,9 @@ static int move_to_new_folio(struct folio *dst, struct folio *src, > VM_BUG_ON_FOLIO(!folio_test_locked(src), src); > VM_BUG_ON_FOLIO(!folio_test_locked(dst), dst); > > + if (already_copied) > + dst->private = (void *)(unsigned long)PAGE_ALREADY_COPIED; > + IMHO, this appears to be an unusual way to pass arguments to a function. Why not adjust the parameters of migrate_folio()? How about turning enum migrate_mode into a bitmask (migrate_flags)? > if (!mapping) > rc = migrate_folio(mapping, dst, src, mode); > else if (mapping_inaccessible(mapping)) > @@ -1127,17 +1148,6 @@ static int move_to_new_folio(struct folio *dst, struct folio *src, > return rc; > } > > -/* > - * To record some information during migration, we use unused private > - * field of struct folio of the newly allocated destination folio. > - * This is safe because nobody is using it except us. > - */ > -enum { > - PAGE_WAS_MAPPED = BIT(0), > - PAGE_WAS_MLOCKED = BIT(1), > - PAGE_OLD_STATES = PAGE_WAS_MAPPED | PAGE_WAS_MLOCKED, > -}; > - > static void __migrate_folio_record(struct folio *dst, > int old_page_state, > struct anon_vma *anon_vma) > @@ -1353,7 +1363,7 @@ static int migrate_folio_unmap(new_folio_t get_new_folio, > static int migrate_folio_move(free_folio_t put_new_folio, unsigned long private, > struct folio *src, struct folio *dst, > enum migrate_mode mode, enum migrate_reason reason, > - struct list_head *ret) > + struct list_head *ret, bool already_copied) > { > int rc; > int old_page_state = 0; > @@ -1371,7 +1381,7 @@ static int migrate_folio_move(free_folio_t put_new_folio, unsigned long private, > goto out_unlock_both; > } > > - rc = move_to_new_folio(dst, src, mode); > + rc = move_to_new_folio(dst, src, mode, already_copied); > if (rc) > goto out; > > @@ -1519,7 +1529,7 @@ static int unmap_and_move_huge_page(new_folio_t get_new_folio, > } > > if (!folio_mapped(src)) > - rc = move_to_new_folio(dst, src, mode); > + rc = move_to_new_folio(dst, src, mode, false); > > if (page_was_mapped) > remove_migration_ptes(src, !rc ? dst : src, ttu); > @@ -1703,7 +1713,7 @@ static void migrate_folios_move(struct list_head *src_folios, > struct list_head *ret_folios, > struct migrate_pages_stats *stats, > int *retry, int *thp_retry, int *nr_failed, > - int *nr_retry_pages) > + int *nr_retry_pages, bool already_copied) > { > struct folio *folio, *folio2, *dst, *dst2; > bool is_thp; > @@ -1720,7 +1730,7 @@ static void migrate_folios_move(struct list_head *src_folios, > > rc = migrate_folio_move(put_new_folio, private, > folio, dst, mode, > - reason, ret_folios); > + reason, ret_folios, already_copied); > /* > * The rules are: > * 0: folio will be freed > @@ -1977,7 +1987,7 @@ static int migrate_pages_batch(struct list_head *from, > migrate_folios_move(&unmap_folios, &dst_folios, > put_new_folio, private, mode, reason, > ret_folios, stats, &retry, &thp_retry, > - &nr_failed, &nr_retry_pages); > + &nr_failed, &nr_retry_pages, false); > } > nr_failed += retry; > stats->nr_thp_failed += thp_retry; --- Best Regards, Huang, Ying