]> granicus.if.org Git - strace/blob - tests/move_pages.c
5912d8b661846c23ed8045065e80b94839aaf779
[strace] / tests / move_pages.c
1 /*
2  * Check decoding of move_pages syscall.
3  *
4  * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
5  * Copyright (c) 2016-2017 The strace developers.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "tests.h"
32 #include <asm/unistd.h>
33
34 #ifdef __NR_move_pages
35
36 # include <errno.h>
37 # include <stdio.h>
38 # include <unistd.h>
39
40 # define MAX_STRLEN 3
41
42 static void
43 print_page_array(const void **const pages,
44                  const unsigned long count,
45                  const unsigned int offset)
46 {
47         if (!count) {
48                 printf("%s", pages ? "[]" : "NULL");
49                 return;
50         }
51         if (count <= offset) {
52                 printf("%p", pages);
53                 return;
54         }
55         printf("[");
56         unsigned long i;
57         for (i = 0; i < count; ++i) {
58                 if (i)
59                         printf(", ");
60                 if (i + offset < count) {
61                         if (i >= MAX_STRLEN) {
62                                 printf("...");
63                                 break;
64                         }
65                 } else {
66                         printf("... /* %p */", pages + i);
67                         break;
68                 }
69                 const void *const addr = pages[i];
70                 if (addr)
71                         printf("%p", addr);
72                 else
73                         printf("NULL");
74         }
75         printf("]");
76 }
77
78 static void
79 print_node_array(const int *const nodes,
80                  const unsigned long count,
81                  const unsigned int offset)
82 {
83         if (!count) {
84                 printf("%s", nodes ? "[]" : "NULL");
85                 return;
86         }
87         if (count <= offset) {
88                 printf("%p", nodes);
89                 return;
90         }
91         printf("[");
92         unsigned long i;
93         for (i = 0; i < count; ++i) {
94                 if (i)
95                         printf(", ");
96                 if (i + offset < count) {
97                         if (i >= MAX_STRLEN) {
98                                 printf("...");
99                                 break;
100                         }
101                 } else {
102                         printf("... /* %p */", nodes + i);
103                         break;
104                 }
105                 printf("%d", nodes[i]);
106         }
107         printf("]");
108 }
109
110 static void
111 print_status_array(const int *const status, const unsigned long count)
112 {
113         if (!count) {
114                 printf("%s", status ? "[]" : "NULL");
115                 return;
116         }
117         printf("[");
118         unsigned long i;
119         for (i = 0; i < count; ++i) {
120                 if (i)
121                         printf(", ");
122                 if (i >= MAX_STRLEN) {
123                         printf("...");
124                         break;
125                 }
126                 if (status[i] >= 0) {
127                         printf("%d", status[i]);
128                 } else {
129                         errno = -status[i];
130                         printf("-%s", errno2name());
131                 }
132         }
133         printf("]");
134 }
135
136 static void
137 print_stat_pages(const unsigned long pid, const unsigned long count,
138                  const void **const pages, int *const status)
139 {
140         const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL;
141
142         long rc = syscall(__NR_move_pages,
143                           pid, count, pages, NULL, status, flags);
144         const char *errstr = sprintrc(rc);
145         printf("move_pages(%d, %lu, ", (int) pid, count);
146         print_page_array(pages, count, 0);
147         printf(", NULL, ");
148         if (rc) {
149                 if (count)
150                         printf("%p", status);
151                 else
152                         printf("[]");
153         } else {
154                 print_status_array(status, count);
155         }
156         printf(", MPOL_MF_MOVE) = %s\n", errstr);
157 }
158
159 static void
160 print_move_pages(const unsigned long pid,
161                  unsigned long count,
162                  const unsigned int offset,
163                  const void **const pages,
164                  int *const nodes,
165                  int *const status)
166 {
167         const unsigned long flags = (unsigned long) 0xfacefeed00000004ULL;
168         count += offset;
169
170         long rc = syscall(__NR_move_pages,
171                           pid, count, pages, nodes, status, flags);
172         const char *errstr = sprintrc(rc);
173         printf("move_pages(%d, %lu, ", (int) pid, count);
174         print_page_array(pages, count, offset);
175         printf(", ");
176         print_node_array(nodes, count, offset);
177         printf(", ");
178         if (count)
179                 printf("%p", status);
180         else
181                 printf("[]");
182         printf(", MPOL_MF_MOVE_ALL) = %s\n", errstr);
183 }
184
185 int
186 main(void)
187 {
188         const unsigned long pid =
189                 (unsigned long) 0xfacefeed00000000ULL | getpid();
190         unsigned long count = 1;
191         const unsigned page_size = get_page_size();
192         const void *const page = tail_alloc(page_size);
193         const void *const efault = page + page_size;
194         TAIL_ALLOC_OBJECT_VAR_PTR(const void *, pages);
195         TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes);
196         TAIL_ALLOC_OBJECT_VAR_PTR(int, status);
197
198         print_stat_pages(pid, 0, pages, status);
199         print_move_pages(pid, 0, 0, pages, nodes, status);
200         print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1);
201
202         *pages = page;
203         print_stat_pages(pid, count, pages, status);
204         *nodes = 0xdeadbee1;
205         print_move_pages(pid, count, 0, pages, nodes, status);
206         print_move_pages(pid, count, 1, pages, nodes, status);
207
208         ++count;
209         --status;
210         *(--pages) = efault;
211         print_stat_pages(pid, count, pages, status);
212         *(--nodes) = 0xdeadbee2;
213         print_move_pages(pid, count, 0, pages, nodes, status);
214         print_move_pages(pid, count, 1, pages, nodes, status);
215
216         ++count;
217         --status;
218         *(--pages) = nodes;
219         print_stat_pages(pid, count, pages, status);
220         *(--nodes) = 0xdeadbee3;
221         print_move_pages(pid, count, 0, pages, nodes, status);
222         print_move_pages(pid, count, 1, pages, nodes, status);
223
224         ++count;
225         --status;
226         *(--pages) = status;
227         print_stat_pages(pid, count, pages, status);
228         *(--nodes) = 0xdeadbee4;
229         print_move_pages(pid, count, 0, pages, nodes, status);
230         print_move_pages(pid, count, 1, pages, nodes, status);
231
232         puts("+++ exited with 0 +++");
233         return 0;
234 }
235
236 #else
237
238 SKIP_MAIN_UNDEFINED("__NR_move_pages")
239
240 #endif