From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 735643F0A97 for ; Fri, 15 May 2026 12:44:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778849055; cv=none; b=CV2nIbFGbHrJmA1H72HdrZUYS1SUmuK7Zy/BiS8XHCb6QMqqd3jDmZFnCLoQ37EWLdhgNkqnXFq03u9YriG65xz6oygPOw2fsUGCcHlJC25JYSXmkMLdKHMgEIL6ip9GpcmKt2rU1227IILTPCoEzuCRDYV28et0ra+a0lHAOcg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778849055; c=relaxed/simple; bh=pKCi71Z6wpwZHcbxRpLd291FtXxerfgoDfFWucFuDHE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YIYKcXiIlxyyRFOn/PFJXNKaSpRJkJWSFZBDtT9ucyCivW5zOqn9JJUpQr9Gm7BtzJ1qmisECGIHgQrtLqsRXgwtcqosyTRgGlulQSCcuuejYDrx59D1rp1ZQE5+1NYKeEw4wPddeAE54vIJqHbOAzJXXPYiWOPFH1N6SXlTPR8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Xa3xFwEE; arc=none smtp.client-ip=209.85.128.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Xa3xFwEE" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-48d102471a4so89509305e9.2 for ; Fri, 15 May 2026 05:44:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778849050; x=1779453850; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=44OAkEa1iWy3QKChD7zwC9IwZGlw448V09DhbTLSUUQ=; b=Xa3xFwEEObX22iV8X2F0WK5ukjMZrelmBsppBKVSu60Q+Tn3ZN39zTyvGOf9FFIBA4 2w846V5wzRw4TAMlOfgAxzGmM51sI6dIeDsSC5l/ty+x/351XTgyDXE+jLMYZJqsft9V f6Cghw9ZAQfjiX81FT9JCQgzTK2gOXNwwIQ9E9zb/n4VUL2E6eczu2R0/JjfE8/6UUkp RvIHN5t6aY0n0QJVvJhX010WJmML0bEakof5eLcnqzJrHn3iHTjle1I7Qp/RZ+s6H7Kx AQMpI/2If0WFgzrXiSssNuIliqFk7zRxUWUrwVzOehwhXq1z8lnb+Uf9CnsoxdAY+GkQ JCcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778849050; x=1779453850; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=44OAkEa1iWy3QKChD7zwC9IwZGlw448V09DhbTLSUUQ=; b=gPGMg5NgPR5fGTHrnFbBl3RUNegti4aucO15Uayah3j2Sk4Q/43JSVHmYPGur/3OEf ioPcNuz1WZZK/plGHRd4U+PTM5FwrBVDMESIemCw/p4+GmOEJmykzkrWxe2QMvWWTldf 07kFrW31BU9dCak0pz7mg+dFp50nQccx29rGjLfh1kYuc5NjW2uZkfxfb8gUzPyoa/Lh RLRnrwu3R55RQiOOAO/xBZCLOU+XfJab7dCZpEqd9+PWUK67uUqUs8AHG1ZNKSJqdn+m D5EjKrMJeMZZsYR/44eIIKdSqvFgUHpQdnwjqdyAAzqSF5VkmOGwiNUgtIAFBAi3P7/Y a9vA== X-Gm-Message-State: AOJu0YztKWE4sn7G3TDLjuIgpzmZ9w/DjFS+vQhvfJyHC5S01W7oaVEo QoqDTfSBim5+mXvfEwJCKup2XGl0enWVMxupnKOApzw1gIK49cijXb9CC0+p2Q== X-Gm-Gg: Acq92OEi+csrvqt4Epj8mtQMPaf6/fxDCTho4G98iRLiTNqXpnA2QinRiWwrgJKiS/q r3FQSUVC3Yyh++og27Y7C3B6LFAYAQTwLp26iNC/H9p5ne0A+f2JUXxjgCksM8yZ4ro4fNTv4tx 7+qXJOyeZqjkjx1xB13evPxUnNNUWhWsPCv8ZP+Fht17EB8H9ivUG8vauBjlZPF9SGC0U67zmBt pHz4Z4mUCHnLl2pPmp1kXx5N/m2ylGgy7yIjzIq/ccQW1bqUO8P1KQsOSGpi3r4vbYZB0yO1mGv e0xbupLb2kLfmfC+2tOpKRHZkA3W1tTxrG7otzxPcSIr5c3wT1LnneZdPWvsAoReTvfKVg6XcjQ TUznKyTyDhDrUAVPI7lTNSZgCV+CNIPtsadPMaJMc7ToFrKPXaCRIz17EP5Um+0i+YGwKZZRCAV 0m61fVhiHbtpH+uSDP6w4= X-Received: by 2002:a05:600c:8901:b0:48e:526e:1040 with SMTP id 5b1f17b1804b1-48fe63021f9mr43573385e9.23.1778849050237; Fri, 15 May 2026 05:44:10 -0700 (PDT) Received: from fedora ([156.207.183.142]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fe4c8344asm100188115e9.1.2026.05.15.05.44.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2026 05:44:09 -0700 (PDT) From: Ahmed Elaidy To: stable@vger.kernel.org Cc: linux-mm@kvack.org, akpm@linux-foundation.org, ljs@kernel.org, avagin@gmail.com, Lorenzo Stoakes , "David Hildenbrand (Red Hat)" , Jann Horn , Liam Howlett , Michal Hocko , Mike Rapoport , Pedro Falcato , Suren Baghdasaryan , Vlastimil Babka , Cyrill Gorcunov , Ahmed Elaidy Subject: [PATCH v4 9/9] testing/selftests/mm: add soft-dirty merge self-test Date: Fri, 15 May 2026 15:42:19 +0300 Message-ID: <20260515124218.151966-11-elaidya225@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260515124218.151966-2-elaidya225@gmail.com> References: <20260515124218.151966-2-elaidya225@gmail.com> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Lorenzo Stoakes Assert that we correctly merge VMAs containing VM_SOFTDIRTY flags now that we correctly handle these as sticky. In order to do so, we have to account for the fact the pagemap interface checks soft dirty PTEs and additionally that newly merged VMAs are marked VM_SOFTDIRTY. We do this by using use unfaulted anon VMAs, establishing one and clearing references on that one, before establishing another and merging the two before checking that soft-dirty is propagated as expected. We check that this functions correctly with mremap() and mprotect() as sample cases, because VMA merge of adjacent newly mapped VMAs will automatically be made soft-dirty due to existing logic which does so. We are therefore exercising other means of merging VMAs. Link: https://lkml.kernel.org/r/d5a0f735783fb4f30a604f570ede02ccc5e29be9.1763399675.git.ljs@kernel.org Signed-off-by: Lorenzo Stoakes Cc: Andrey Vagin Cc: David Hildenbrand (Red Hat) Cc: Jann Horn Cc: Liam Howlett Cc: Michal Hocko Cc: Mike Rapoport Cc: Pedro Falcato Cc: Suren Baghdasaryan Cc: Vlastimil Babka Cc: Cyrill Gorcunov Signed-off-by: Andrew Morton (cherry picked from commit c7ba92bcfea34f6b4afc744c3b65c8f7420fefe0) Signed-off-by: Ahmed Elaidy Cc: stable@vger.kernel.org # 6.18.x --- tools/testing/selftests/mm/soft-dirty.c | 127 +++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/mm/soft-dirty.c b/tools/testing/selftests/mm/soft-dirty.c index 4ee4db3750c1..c3a9585de98c 100644 --- a/tools/testing/selftests/mm/soft-dirty.c +++ b/tools/testing/selftests/mm/soft-dirty.c @@ -184,6 +184,130 @@ static void test_mprotect(int pagemap_fd, int pagesize, bool anon) close(test_fd); } +static void test_merge(int pagemap_fd, int pagesize) +{ + char *reserved, *map, *map2; + + /* + * Reserve space for tests: + * + * ---padding to --- + * | avoid adj. | + * v merge v + * |---|---|---|---|---| + * | | 1 | 2 | 3 | | + * |---|---|---|---|---| + */ + reserved = mmap(NULL, 5 * pagesize, PROT_NONE, + MAP_ANON | MAP_PRIVATE, -1, 0); + if (reserved == MAP_FAILED) + ksft_exit_fail_msg("mmap failed\n"); + munmap(reserved, 4 * pagesize); + + /* + * Establish initial VMA: + * + * S/D + * |---|---|---|---|---| + * | | 1 | | | | + * |---|---|---|---|---| + */ + map = mmap(&reserved[pagesize], pagesize, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); + if (map == MAP_FAILED) + ksft_exit_fail_msg("mmap failed\n"); + + /* This will clear VM_SOFTDIRTY too. */ + clear_softdirty(); + + /* + * Now place a new mapping which will be marked VM_SOFTDIRTY. Away from + * map: + * + * - S/D + * |---|---|---|---|---| + * | | 1 | | 2 | | + * |---|---|---|---|---| + */ + map2 = mmap(&reserved[3 * pagesize], pagesize, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); + if (map2 == MAP_FAILED) + ksft_exit_fail_msg("mmap failed\n"); + + /* + * Now remap it immediately adjacent to map, if the merge correctly + * propagates VM_SOFTDIRTY, we should then observe the VMA as a whole + * being marked soft-dirty: + * + * merge + * S/D + * |---|-------|---|---| + * | | 1 | | | + * |---|-------|---|---| + */ + map2 = mremap(map2, pagesize, pagesize, MREMAP_FIXED | MREMAP_MAYMOVE, + &reserved[2 * pagesize]); + if (map2 == MAP_FAILED) + ksft_exit_fail_msg("mremap failed\n"); + ksft_test_result(pagemap_is_softdirty(pagemap_fd, map) == 1, + "Test %s-anon soft-dirty after remap merge 1st pg\n", + __func__); + ksft_test_result(pagemap_is_softdirty(pagemap_fd, map2) == 1, + "Test %s-anon soft-dirty after remap merge 2nd pg\n", + __func__); + + munmap(map, 2 * pagesize); + + /* + * Now establish another VMA: + * + * S/D + * |---|---|---|---|---| + * | | 1 | | | | + * |---|---|---|---|---| + */ + map = mmap(&reserved[pagesize], pagesize, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); + if (map == MAP_FAILED) + ksft_exit_fail_msg("mmap failed\n"); + + /* Clear VM_SOFTDIRTY... */ + clear_softdirty(); + /* ...and establish incompatible adjacent VMA: + * + * - S/D + * |---|---|---|---|---| + * | | 1 | 2 | | | + * |---|---|---|---|---| + */ + map2 = mmap(&reserved[2 * pagesize], pagesize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); + if (map2 == MAP_FAILED) + ksft_exit_fail_msg("mmap failed\n"); + + /* + * Now mprotect() VMA 1 so it's compatible with 2 and therefore merges: + * + * merge + * S/D + * |---|-------|---|---| + * | | 1 | | | + * |---|-------|---|---| + */ + if (mprotect(map, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC)) + ksft_exit_fail_msg("mprotect failed\n"); + + ksft_test_result(pagemap_is_softdirty(pagemap_fd, map) == 1, + "Test %s-anon soft-dirty after mprotect merge 1st pg\n", + __func__); + ksft_test_result(pagemap_is_softdirty(pagemap_fd, map2) == 1, + "Test %s-anon soft-dirty after mprotect merge 2nd pg\n", + __func__); + + munmap(map, 2 * pagesize); +} + static void test_mprotect_anon(int pagemap_fd, int pagesize) { test_mprotect(pagemap_fd, pagesize, true); @@ -204,7 +328,7 @@ int main(int argc, char **argv) if (!softdirty_supported()) ksft_exit_skip("soft-dirty is not support\n"); - ksft_set_plan(15); + ksft_set_plan(19); pagemap_fd = open(PAGEMAP_FILE_PATH, O_RDONLY); if (pagemap_fd < 0) ksft_exit_fail_msg("Failed to open %s\n", PAGEMAP_FILE_PATH); @@ -216,6 +340,7 @@ int main(int argc, char **argv) test_hugepage(pagemap_fd, pagesize); test_mprotect_anon(pagemap_fd, pagesize); test_mprotect_file(pagemap_fd, pagesize); + test_merge(pagemap_fd, pagesize); close(pagemap_fd); -- 2.54.0