Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tools/testing/vma: add VMA sticky userland tests

Modify existing merge new/existing userland VMA tests to assert that
sticky VMA flags behave as expected.

We do so by generating every possible permutation of VMAs being
manipulated being sticky/not sticky and asserting that VMA flags with this
property retain are retained upon merge.

Link: https://lkml.kernel.org/r/5e2c7244485867befd052f8afc8188be6a4be670.1763460113.git.lorenzo.stoakes@oracle.com
Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Andrei Vagin <avagin@gmail.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry Song <baohua@kernel.org>
Cc: David Hildenbrand (Red Hat) <david@kernel.org>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Jann Horn <jannh@google.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Nico Pache <npache@redhat.com>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Lorenzo Stoakes and committed by
Andrew Morton
29bef05e 49e14dab

+79 -10
+79 -10
tools/testing/vma/vma.c
··· 48 48 #define ASSERT_EQ(_val1, _val2) ASSERT_TRUE((_val1) == (_val2)) 49 49 #define ASSERT_NE(_val1, _val2) ASSERT_TRUE((_val1) != (_val2)) 50 50 51 + #define IS_SET(_val, _flags) ((_val & _flags) == _flags) 52 + 51 53 static struct task_struct __current; 52 54 53 55 struct task_struct *get_current(void) ··· 444 442 return true; 445 443 } 446 444 447 - static bool test_merge_new(void) 445 + static bool __test_merge_new(bool is_sticky, bool a_is_sticky, bool b_is_sticky, bool c_is_sticky) 448 446 { 449 447 vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE; 450 448 struct mm_struct mm = {}; ··· 472 470 struct vm_area_struct *vma, *vma_a, *vma_b, *vma_c, *vma_d; 473 471 bool merged; 474 472 473 + if (is_sticky) 474 + vm_flags |= VM_STICKY; 475 + 475 476 /* 476 477 * 0123456789abc 477 478 * AA B CC 478 479 */ 479 480 vma_a = alloc_and_link_vma(&mm, 0, 0x2000, 0, vm_flags); 480 481 ASSERT_NE(vma_a, NULL); 482 + if (a_is_sticky) 483 + vm_flags_set(vma_a, VM_STICKY); 481 484 /* We give each VMA a single avc so we can test anon_vma duplication. */ 482 485 INIT_LIST_HEAD(&vma_a->anon_vma_chain); 483 486 list_add(&dummy_anon_vma_chain_a.same_vma, &vma_a->anon_vma_chain); 484 487 485 488 vma_b = alloc_and_link_vma(&mm, 0x3000, 0x4000, 3, vm_flags); 486 489 ASSERT_NE(vma_b, NULL); 490 + if (b_is_sticky) 491 + vm_flags_set(vma_b, VM_STICKY); 487 492 INIT_LIST_HEAD(&vma_b->anon_vma_chain); 488 493 list_add(&dummy_anon_vma_chain_b.same_vma, &vma_b->anon_vma_chain); 489 494 490 495 vma_c = alloc_and_link_vma(&mm, 0xb000, 0xc000, 0xb, vm_flags); 491 496 ASSERT_NE(vma_c, NULL); 497 + if (c_is_sticky) 498 + vm_flags_set(vma_c, VM_STICKY); 492 499 INIT_LIST_HEAD(&vma_c->anon_vma_chain); 493 500 list_add(&dummy_anon_vma_chain_c.same_vma, &vma_c->anon_vma_chain); 494 501 ··· 532 521 ASSERT_EQ(vma->anon_vma, &dummy_anon_vma); 533 522 ASSERT_TRUE(vma_write_started(vma)); 534 523 ASSERT_EQ(mm.map_count, 3); 524 + if (is_sticky || a_is_sticky || b_is_sticky) 525 + ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY)); 535 526 536 527 /* 537 528 * Merge to PREVIOUS VMA. ··· 551 538 ASSERT_EQ(vma->anon_vma, &dummy_anon_vma); 552 539 ASSERT_TRUE(vma_write_started(vma)); 553 540 ASSERT_EQ(mm.map_count, 3); 541 + if (is_sticky || a_is_sticky) 542 + ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY)); 554 543 555 544 /* 556 545 * Merge to NEXT VMA. ··· 572 557 ASSERT_EQ(vma->anon_vma, &dummy_anon_vma); 573 558 ASSERT_TRUE(vma_write_started(vma)); 574 559 ASSERT_EQ(mm.map_count, 3); 560 + if (is_sticky) /* D uses is_sticky. */ 561 + ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY)); 575 562 576 563 /* 577 564 * Merge BOTH sides. ··· 592 575 ASSERT_EQ(vma->anon_vma, &dummy_anon_vma); 593 576 ASSERT_TRUE(vma_write_started(vma)); 594 577 ASSERT_EQ(mm.map_count, 2); 578 + if (is_sticky || a_is_sticky) 579 + ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY)); 595 580 596 581 /* 597 582 * Merge to NEXT VMA. ··· 612 593 ASSERT_EQ(vma->anon_vma, &dummy_anon_vma); 613 594 ASSERT_TRUE(vma_write_started(vma)); 614 595 ASSERT_EQ(mm.map_count, 2); 596 + if (is_sticky || c_is_sticky) 597 + ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY)); 615 598 616 599 /* 617 600 * Merge BOTH sides. ··· 631 610 ASSERT_EQ(vma->anon_vma, &dummy_anon_vma); 632 611 ASSERT_TRUE(vma_write_started(vma)); 633 612 ASSERT_EQ(mm.map_count, 1); 613 + if (is_sticky || a_is_sticky || c_is_sticky) 614 + ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY)); 634 615 635 616 /* 636 617 * Final state. ··· 658 635 ASSERT_EQ(count, 1); 659 636 660 637 mtree_destroy(&mm.mm_mt); 638 + return true; 639 + } 640 + 641 + static bool test_merge_new(void) 642 + { 643 + int i, j, k, l; 644 + 645 + /* Generate every possible permutation of sticky flags. */ 646 + for (i = 0; i < 2; i++) 647 + for (j = 0; j < 2; j++) 648 + for (k = 0; k < 2; k++) 649 + for (l = 0; l < 2; l++) 650 + ASSERT_TRUE(__test_merge_new(i, j, k, l)); 651 + 661 652 return true; 662 653 } 663 654 ··· 1011 974 return true; 1012 975 } 1013 976 1014 - static bool test_merge_existing(void) 977 + static bool __test_merge_existing(bool prev_is_sticky, bool middle_is_sticky, bool next_is_sticky) 1015 978 { 1016 979 vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE; 980 + vm_flags_t prev_flags = vm_flags; 981 + vm_flags_t next_flags = vm_flags; 1017 982 struct mm_struct mm = {}; 1018 983 VMA_ITERATOR(vmi, &mm, 0); 1019 984 struct vm_area_struct *vma, *vma_prev, *vma_next; ··· 1027 988 .close = dummy_close, 1028 989 }; 1029 990 struct anon_vma_chain avc = {}; 991 + 992 + if (prev_is_sticky) 993 + prev_flags |= VM_STICKY; 994 + if (middle_is_sticky) 995 + vm_flags |= VM_STICKY; 996 + if (next_is_sticky) 997 + next_flags |= VM_STICKY; 1030 998 1031 999 /* 1032 1000 * Merge right case - partial span. ··· 1047 1001 */ 1048 1002 vma = alloc_and_link_vma(&mm, 0x2000, 0x6000, 2, vm_flags); 1049 1003 vma->vm_ops = &vm_ops; /* This should have no impact. */ 1050 - vma_next = alloc_and_link_vma(&mm, 0x6000, 0x9000, 6, vm_flags); 1004 + vma_next = alloc_and_link_vma(&mm, 0x6000, 0x9000, 6, next_flags); 1051 1005 vma_next->vm_ops = &vm_ops; /* This should have no impact. */ 1052 1006 vmg_set_range_anon_vma(&vmg, 0x3000, 0x6000, 3, vm_flags, &dummy_anon_vma); 1053 1007 vmg.middle = vma; ··· 1065 1019 ASSERT_TRUE(vma_write_started(vma)); 1066 1020 ASSERT_TRUE(vma_write_started(vma_next)); 1067 1021 ASSERT_EQ(mm.map_count, 2); 1022 + if (middle_is_sticky || next_is_sticky) 1023 + ASSERT_TRUE(IS_SET(vma_next->vm_flags, VM_STICKY)); 1068 1024 1069 1025 /* Clear down and reset. */ 1070 1026 ASSERT_EQ(cleanup_mm(&mm, &vmi), 2); ··· 1082 1034 * NNNNNNN 1083 1035 */ 1084 1036 vma = alloc_and_link_vma(&mm, 0x2000, 0x6000, 2, vm_flags); 1085 - vma_next = alloc_and_link_vma(&mm, 0x6000, 0x9000, 6, vm_flags); 1037 + vma_next = alloc_and_link_vma(&mm, 0x6000, 0x9000, 6, next_flags); 1086 1038 vma_next->vm_ops = &vm_ops; /* This should have no impact. */ 1087 1039 vmg_set_range_anon_vma(&vmg, 0x2000, 0x6000, 2, vm_flags, &dummy_anon_vma); 1088 1040 vmg.middle = vma; ··· 1095 1047 ASSERT_EQ(vma_next->anon_vma, &dummy_anon_vma); 1096 1048 ASSERT_TRUE(vma_write_started(vma_next)); 1097 1049 ASSERT_EQ(mm.map_count, 1); 1050 + if (middle_is_sticky || next_is_sticky) 1051 + ASSERT_TRUE(IS_SET(vma_next->vm_flags, VM_STICKY)); 1098 1052 1099 1053 /* Clear down and reset. We should have deleted vma. */ 1100 1054 ASSERT_EQ(cleanup_mm(&mm, &vmi), 1); ··· 1111 1061 * 0123456789 1112 1062 * PPPPPPV 1113 1063 */ 1114 - vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags); 1064 + vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, prev_flags); 1115 1065 vma_prev->vm_ops = &vm_ops; /* This should have no impact. */ 1116 1066 vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, vm_flags); 1117 1067 vma->vm_ops = &vm_ops; /* This should have no impact. */ ··· 1131 1081 ASSERT_TRUE(vma_write_started(vma_prev)); 1132 1082 ASSERT_TRUE(vma_write_started(vma)); 1133 1083 ASSERT_EQ(mm.map_count, 2); 1084 + if (prev_is_sticky || middle_is_sticky) 1085 + ASSERT_TRUE(IS_SET(vma_prev->vm_flags, VM_STICKY)); 1134 1086 1135 1087 /* Clear down and reset. */ 1136 1088 ASSERT_EQ(cleanup_mm(&mm, &vmi), 2); ··· 1147 1095 * 0123456789 1148 1096 * PPPPPPP 1149 1097 */ 1150 - vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags); 1098 + vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, prev_flags); 1151 1099 vma_prev->vm_ops = &vm_ops; /* This should have no impact. */ 1152 1100 vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, vm_flags); 1153 1101 vmg_set_range_anon_vma(&vmg, 0x3000, 0x7000, 3, vm_flags, &dummy_anon_vma); ··· 1162 1110 ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma); 1163 1111 ASSERT_TRUE(vma_write_started(vma_prev)); 1164 1112 ASSERT_EQ(mm.map_count, 1); 1113 + if (prev_is_sticky || middle_is_sticky) 1114 + ASSERT_TRUE(IS_SET(vma_prev->vm_flags, VM_STICKY)); 1165 1115 1166 1116 /* Clear down and reset. We should have deleted vma. */ 1167 1117 ASSERT_EQ(cleanup_mm(&mm, &vmi), 1); ··· 1178 1124 * 0123456789 1179 1125 * PPPPPPPPPP 1180 1126 */ 1181 - vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags); 1127 + vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, prev_flags); 1182 1128 vma_prev->vm_ops = &vm_ops; /* This should have no impact. */ 1183 1129 vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, vm_flags); 1184 - vma_next = alloc_and_link_vma(&mm, 0x7000, 0x9000, 7, vm_flags); 1130 + vma_next = alloc_and_link_vma(&mm, 0x7000, 0x9000, 7, next_flags); 1185 1131 vmg_set_range_anon_vma(&vmg, 0x3000, 0x7000, 3, vm_flags, &dummy_anon_vma); 1186 1132 vmg.prev = vma_prev; 1187 1133 vmg.middle = vma; ··· 1194 1140 ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma); 1195 1141 ASSERT_TRUE(vma_write_started(vma_prev)); 1196 1142 ASSERT_EQ(mm.map_count, 1); 1143 + if (prev_is_sticky || middle_is_sticky || next_is_sticky) 1144 + ASSERT_TRUE(IS_SET(vma_prev->vm_flags, VM_STICKY)); 1197 1145 1198 1146 /* Clear down and reset. We should have deleted prev and next. */ 1199 1147 ASSERT_EQ(cleanup_mm(&mm, &vmi), 1); ··· 1215 1159 * PPPVVVVVNNN 1216 1160 */ 1217 1161 1218 - vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags); 1162 + vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, prev_flags); 1219 1163 vma = alloc_and_link_vma(&mm, 0x3000, 0x8000, 3, vm_flags); 1220 - vma_next = alloc_and_link_vma(&mm, 0x8000, 0xa000, 8, vm_flags); 1164 + vma_next = alloc_and_link_vma(&mm, 0x8000, 0xa000, 8, next_flags); 1221 1165 1222 1166 vmg_set_range(&vmg, 0x4000, 0x5000, 4, vm_flags); 1223 1167 vmg.prev = vma; ··· 1256 1200 ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE); 1257 1201 1258 1202 ASSERT_EQ(cleanup_mm(&mm, &vmi), 3); 1203 + 1204 + return true; 1205 + } 1206 + 1207 + static bool test_merge_existing(void) 1208 + { 1209 + int i, j, k; 1210 + 1211 + /* Generate every possible permutation of sticky flags. */ 1212 + for (i = 0; i < 2; i++) 1213 + for (j = 0; j < 2; j++) 1214 + for (k = 0; k < 2; k++) 1215 + ASSERT_TRUE(__test_merge_existing(i, j, k)); 1259 1216 1260 1217 return true; 1261 1218 }