1 /******************************************************************************
2 * sync_file_range01.c
3 * Copyright (c) International Business Machines Corp., 2008
4 * Email: bnpoorni@in.ibm.com
5 *****************************************************************************/
6
7 /******************************************************************************/
8 /* */
9 /* This program is free software; you can redistribute it and/or modify */
10 /* it under the terms of the GNU General Public License as published by */
11 /* the Free Software Foundation; either version 2 of the License, or */
12 /* (at your option) any later version. */
13 /* */
14 /* This program is distributed in the hope that it will be useful, */
15 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
16 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
17 /* the GNU General Public License for more details. */
18 /* */
19 /* You should have received a copy of the GNU General Public License */
20 /* along with this program; if not, write to the Free Software */
21 /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
22 /* */
23 /******************************************************************************/
24
25 /*****************************************************************************
26 * TEST IDENTIFIER : sync_file_range01 $
27 * $
28 * EXECUTED BY : anyone $
29 *
30 * TEST TITLE : Checks for Errors from sync_file_range()
31 *
32 * TEST CASE TOTAL : 5
33 *
34 * CPU ARCHITECTURES : All
35 *
36 * AUTHOR : B N Poornima
37 *
38 * DATE STARTED : 21/07/2008
39 *
40 * TEST CASES
41 * (Tests sync_file_range() for different test cases as reported in the man
42 * page)
43 *
44 * INPUT SPECIFICATIONS
45 * No input needs to be specified
46 * sync_file_data() in-puts are specified through test_data
47 *
48 * OUTPUT SPECIFICATIONS
49 * sync_file_data() error message matches with the expected error
50 * message.
51 *
52 * ENVIRONMENTAL NEEDS
53 * Kernel version 2.6.17 and above
54 * Kernel version 2.6.22 and above in case of PPC and PPC64
55 *
56 * SPECIAL PROCEDURAL REQUIREMENTS
57 * None
58 *
59 * DETAILED DESCRIPTION
60 * This is a test case for sync_file_range() system call.
61 * This test suite tests various error messages from the system call
62 * If the error message received matches with the expected
63 * test is considered passed else test fails
64 *
65 * Total 5 Test Cases :-
66 * Various error messages from the man page
67 *
68 * Setup:
69 * Setup files on which sync_file_range is to be called
70 *
71 * Test:
72 * Loop if the proper options are given.
73 * Execute system call
74 * Check return code.
75 * If error obtained matches with the expected error
76 * PASS the test, otherwise TEST FAILS
77 *
78 * Cleanup:
79 * Cleanup the temporary folder
80 *
81 ******************************************************************************/
82 #define _GNU_SOURCE
83
84 #include <sys/types.h>
85 #include <sys/stat.h>
86 #include <sys/utsname.h>
87 #include <endian.h>
88 #include <errno.h>
89 #include <fcntl.h>
90 #include <stdio.h>
91 #include <stdlib.h>
92 #include <unistd.h>
93
94 #include "test.h"
95 #include "lapi/syscalls.h"
96
97 #ifndef SYNC_FILE_RANGE_WAIT_BEFORE
98 #define SYNC_FILE_RANGE_WAIT_BEFORE 1
99 #define SYNC_FILE_RANGE_WRITE 2 //DUMMY VALUES
100 #define SYNC_FILE_RANGE_WAIT_AFTER 4
101 #endif
102
103 #define SYNC_FILE_RANGE_INVALID 8
104
105 char *TCID = "sync_file_range01";
106 char filename[255]; /* file used for testing */
107 char spl_file[] = "/dev/null";
108 int filed, sfd; /* normal and special fds */
109 int bfd = -1; /* Bad file descriptor */
110
111 struct test_data_t {
112 int *fd;
113 off64_t offset;
114 off64_t nbytes;
115 unsigned int flags;
116 int error;
117 } test_data[] = {
118 {
119 &bfd, 0, 1, SYNC_FILE_RANGE_WRITE, EBADF}, {
120 &sfd, 0, 1, SYNC_FILE_RANGE_WAIT_AFTER, ESPIPE}, {
121 &filed, -1, 1, SYNC_FILE_RANGE_WAIT_BEFORE, EINVAL}, {
122 &filed, 0, -1, SYNC_FILE_RANGE_WRITE, EINVAL}, {
123 &filed, 0, 1, SYNC_FILE_RANGE_INVALID, EINVAL}
124 };
125
126 int TST_TOTAL = sizeof(test_data) / sizeof(test_data[0]);
127
128 /* Extern Global Functions */
129 /******************************************************************************/
130 /* */
131 /* Function: cleanup */
132 /* */
133 /* Description: Performs all one time clean up for this test on successful */
134 /* completion, premature exit or failure. Closes all temporary */
135 /* files, removes all temporary directories exits the test with */
136 /* appropriate return code by calling tst_exit() function. */
137 /* */
138 /* Input: None. */
139 /* */
140 /* Output: None. */
141 /* */
142 /* Return: On failure - Exits calling tst_exit(). Non '0' return code. */
143 /* On success - Exits calling tst_exit(). With '0' return code. */
144 /* */
145 /******************************************************************************/
cleanup(void)146 void cleanup(void)
147 {
148
149 /* close the file we have open */
150 if (close(filed) == -1) {
151 tst_resm(TWARN | TERRNO, "close(%s) failed", filename);
152 }
153
154 tst_rmdir();
155 }
156
157 /* Local Functions */
158 /******************************************************************************/
159 /* */
160 /* Function: setup */
161 /* */
162 /* Description: Performs all one time setup for this test. This function is */
163 /* typically used to capture signals, create temporary dirs */
164 /* and temporary files that may be used in the course of this */
165 /* test. */
166 /* */
167 /* Input: None. */
168 /* */
169 /* Output: None. */
170 /* */
171 /* Return: On failure - Exits by calling cleanup(). */
172 /* On success - returns 0. */
173 /* */
174 /******************************************************************************/
setup(void)175 void setup(void)
176 {
177
178 tst_sig(NOFORK, DEF_HANDLER, cleanup);
179
180 TEST_PAUSE;
181
182 tst_tmpdir();
183
184 sprintf(filename, "tmpfile_%d", getpid());
185 if ((filed = open(filename, O_RDWR | O_CREAT, 0700)) == -1) {
186 tst_brkm(TBROK | TERRNO, cleanup,
187 "open(%s, O_RDWR|O_CREAT,0700) failed", filename);
188 }
189
190 sfd = open(spl_file, O_RDWR | O_CREAT, 0700);
191 }
192
193 /*****************************************************************************
194 * Wraper function to call sync_file_range system call
195 ******************************************************************************/
syncfilerange(int fd,off64_t offset,off64_t nbytes,unsigned int flags)196 static inline long syncfilerange(int fd, off64_t offset, off64_t nbytes,
197 unsigned int flags)
198 {
199 /* arm and powerpc */
200 #if (defined(__arm__) || defined(__powerpc__) || defined(__powerpc64__))
201 #if (__WORDSIZE == 32)
202 #if __BYTE_ORDER == __BIG_ENDIAN
203 return ltp_syscall(__NR_sync_file_range2, fd, flags,
204 (int)(offset >> 32), (int)offset, (int)(nbytes >> 32),
205 (int)nbytes);
206 #elif __BYTE_ORDER == __LITTLE_ENDIAN
207 return ltp_syscall(__NR_sync_file_range2, fd, flags, (int)offset,
208 (int)(offset >> 32), nbytes, (int)(nbytes >> 32));
209 #endif
210 #else
211 return ltp_syscall(__NR_sync_file_range2, fd, flags, offset, nbytes);
212 #endif
213
214 /* s390 */
215 #elif (defined(__s390__) || defined(__s390x__)) && __WORDSIZE == 32
216 return ltp_syscall(__NR_sync_file_range, fd, (int)(offset >> 32),
217 (int)offset, (int)(nbytes >> 32), (int)nbytes, flags);
218
219 /* mips */
220 #elif defined(__mips__) && __WORDSIZE == 32
221 #if __BYTE_ORDER == __BIG_ENDIAN
222 return ltp_syscall(__NR_sync_file_range, fd, 0, (int)(offset >> 32),
223 (int)offset, (int)(nbytes >> 32), (int)nbytes, flags);
224 #elif __BYTE_ORDER == __LITTLE_ENDIAN
225 return ltp_syscall(__NR_sync_file_range, fd, 0, (int)offset,
226 (int)(offset >> 32), (int)nbytes, (int)(nbytes >> 32), flags);
227 #endif
228
229 /* other */
230 #else
231 return ltp_syscall(__NR_sync_file_range, fd, offset, nbytes, flags);
232 #endif
233 }
234
235 /******************************************************************************/
236 /* */
237 /* Function: main */
238 /* */
239 /* Description: Entry point to this test-case. It parses all the command line */
240 /* inputs, calls the global setup and executes the test. It logs */
241 /* the test status and results appropriately using the LTP API's */
242 /* On successful completion or premature failure, cleanup() func */
243 /* is called and test exits with an appropriate return code. */
244 /* */
245 /* Input: Describe input arguments to this test-case */
246 /* -l - Number of iteration */
247 /* -v - Prints verbose output */
248 /* -V - Prints the version number */
249 /* */
250 /* Exit: On failure - Exits by calling cleanup(). */
251 /* On success - exits with 0 exit value. */
252 /* */
253 /******************************************************************************/
main(int ac,char ** av)254 int main(int ac, char **av)
255 {
256
257 int test_index = 0;
258
259 tst_parse_opts(ac, av, NULL, NULL);
260
261 #if defined(__powerpc__) || defined(__powerpc64__) /* for PPC, kernel version > 2.6.21 needed */
262 if (tst_kvercmp(2, 16, 22) < 0) {
263 tst_brkm(TCONF, NULL,
264 "System doesn't support execution of the test");
265 }
266 #else
267 /* For other archs, need kernel version > 2.6.16 */
268
269 if (tst_kvercmp(2, 6, 17) < 0) {
270 tst_brkm(TCONF, NULL,
271 "System doesn't support execution of the test");
272 }
273 #endif
274
275 setup();
276
277 for (test_index = 0; test_index < TST_TOTAL; test_index++) {
278 TEST(syncfilerange
279 (*(test_data[test_index].fd),
280 test_data[test_index].offset,
281 test_data[test_index].nbytes,
282 test_data[test_index].flags));
283
284 if (TEST_RETURN != -1) {
285 tst_resm(TFAIL,
286 "call succeeded unexpectedly (%ld != -1)",
287 TEST_RETURN);
288 continue;
289 }
290
291 if (TEST_ERRNO == test_data[test_index].error) {
292 tst_resm(TPASS | TTERRNO, "got expected error");
293 } else {
294 tst_resm(TFAIL | TTERRNO, "got unexpected error; "
295 "expected %d", test_data[test_index].error);
296 }
297
298 }
299
300 cleanup();
301 tst_exit();
302 }
303