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