sync_file_range01.c revision 4548c6cf9bcdd96d8303caa4130ab638b61f8a30
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/* Standard Include Files */
85#include <sys/types.h>
86#include <sys/stat.h>
87#include <sys/utsname.h>
88#include <endian.h>
89#include <errno.h>
90#include <fcntl.h>
91#include <stdio.h>
92#include <stdlib.h>
93#include <unistd.h>
94
95/* Harness Specific Include Files. */
96#include "test.h"
97#include "usctest.h"
98#include "linux_syscall_numbers.h"
99
100#ifndef SYNC_FILE_RANGE_WAIT_BEFORE
101#define SYNC_FILE_RANGE_WAIT_BEFORE 1
102#define SYNC_FILE_RANGE_WRITE 2	//DUMMY VALUES
103#define SYNC_FILE_RANGE_WAIT_AFTER 4
104#endif
105
106#define SYNC_FILE_RANGE_INVALID 8
107
108/* Extern Global Variables */
109
110/* Global Variables */
111char *TCID = "sync_file_range01";	/* test program identifier.	  */
112char filename[255];		/* file used for testing */
113char spl_file[] = "/dev/null";
114int filed, sfd;			/* normal and special fds */
115int bfd = -1;			/* Bad file descriptor */
116
117struct test_data_t {
118	int *fd;
119	off64_t offset;
120	off64_t nbytes;
121	unsigned int flags;
122	int error;
123} test_data[] = {
124	{ &bfd, 0, 1, SYNC_FILE_RANGE_WRITE, EBADF},
125	{ &sfd, 0, 1, SYNC_FILE_RANGE_WAIT_AFTER, ESPIPE},
126	{ &filed, -1, 1, SYNC_FILE_RANGE_WAIT_BEFORE, EINVAL},
127	{ &filed, 0, -1, SYNC_FILE_RANGE_WRITE, EINVAL},
128	{ &filed, 0, 1, SYNC_FILE_RANGE_INVALID, EINVAL}
129};
130
131int TST_TOTAL = sizeof(test_data) / sizeof(test_data[0]);
132
133/* Extern Global Functions */
134/******************************************************************************/
135/*									    */
136/* Function:    cleanup						       */
137/*									    */
138/* Description: Performs all one time clean up for this test on successful    */
139/*	      completion,  premature exit or  failure. Closes all temporary */
140/*	      files, removes all temporary directories exits the test with  */
141/*	      appropriate return code by calling tst_exit() function.       */
142/*									    */
143/* Input:       None.							 */
144/*									    */
145/* Output:      None.							 */
146/*									    */
147/* Return:      On failure - Exits calling tst_exit(). Non '0' return code.   */
148/*	      On success - Exits calling tst_exit(). With '0' return code.  */
149/*									    */
150/******************************************************************************/
151extern void cleanup()
152{
153	/*
154	 * print timing stats if that option was specified.
155	 * print errno log if that option was specified.
156	 */
157	TEST_CLEANUP;
158
159	/* close the file we have open */
160	if (close(filed) == -1) {
161		tst_resm(TWARN|TERRNO, "close(%s) failed", filename);
162	}
163
164	tst_rmdir();
165}
166
167/* Local  Functions */
168/******************************************************************************/
169/*									    */
170/* Function:    setup							 */
171/*									    */
172/* Description: Performs all one time setup for this test. This function is   */
173/*	      typically used to capture signals, create temporary dirs      */
174/*	      and temporary files that may be used in the course of this    */
175/*	      test.							 */
176/*									    */
177/* Input:       None.							 */
178/*									    */
179/* Output:      None.							 */
180/*									    */
181/* Return:      On failure - Exits by calling cleanup().		      */
182/*	      On success - returns 0.				       */
183/*									    */
184/******************************************************************************/
185void setup()
186{
187
188	tst_sig(NOFORK, DEF_HANDLER, cleanup);
189
190	TEST_PAUSE;
191
192	tst_tmpdir();
193
194	sprintf(filename, "tmpfile_%d", getpid());
195	if ((filed = open(filename, O_RDWR | O_CREAT, 0700)) == -1) {
196		tst_brkm(TBROK|TERRNO, cleanup,
197			 "open(%s, O_RDWR|O_CREAT,0700) failed", filename);
198	}
199
200	sfd = open(spl_file, O_RDWR|O_CREAT, 0700);
201}
202
203/*****************************************************************************
204 * Wraper function to call sync_file_range system call
205 ******************************************************************************/
206static inline long syncfilerange(int fd, off64_t offset, off64_t nbytes,
207				 unsigned int flags)
208{
209
210#if (defined(__arm__) || defined(__powerpc__) || defined(__powerpc64__))
211#if (__WORDSIZE == 32)
212#if __BYTE_ORDER == __BIG_ENDIAN
213	return syscall(__NR_sync_file_range2, fd, flags, (int)(offset >> 32),
214		       (int)offset, (int)(nbytes >> 32), (int)nbytes);
215#elif __BYTE_ORDER == __LITTLE_ENDIAN
216	return syscall(__NR_sync_file_range2, fd, flags, (int)offset,
217		       (int)(offset >> 32), nbytes, (int)(nbytes >> 32));
218#endif
219#else
220	return syscall(__NR_sync_file_range2, fd, flags, offset, nbytes);
221#endif
222#else
223	return syscall(__NR_sync_file_range, fd, offset, nbytes, flags);
224#endif
225
226}
227
228/******************************************************************************/
229/*									    */
230/* Function:    main							  */
231/*									    */
232/* Description: Entry point to this test-case. It parses all the command line */
233/*	      inputs, calls the global setup and executes the test. It logs */
234/*	      the test status and results appropriately using the LTP API's */
235/*	      On successful completion or premature failure, cleanup() func */
236/*	      is called and test exits with an appropriate return code.     */
237/*									    */
238/* Input:       Describe input arguments to this test-case		    */
239/*	       -l - Number of iteration				     */
240/*	       -v - Prints verbose output				   */
241/*	       -V - Prints the version number			       */
242/*									    */
243/* Exit:       On failure - Exits by calling cleanup().		       */
244/*	     On success - exits with 0 exit value.			  */
245/*									    */
246/******************************************************************************/
247int main(int ac, char **av)
248{
249
250	int test_index = 0;
251	char *msg;
252
253	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
254		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
255
256#if defined(__powerpc__) || defined(__powerpc64__)	/* for PPC, kernel version > 2.6.21 needed */
257	if (tst_kvercmp(2, 16, 22) < 0) {
258		tst_brkm(TCONF, NULL, "System doesn't support execution of the test");
259	}
260#else
261	/* For other archs, need kernel version > 2.6.16 */
262
263	if (tst_kvercmp(2, 6, 17) < 0) {
264		tst_brkm(TCONF, NULL, "System doesn't support execution of the test");
265	}
266#endif
267
268	setup();
269
270	for (test_index = 0; test_index < TST_TOTAL; test_index++) {
271		TEST(syncfilerange
272		     (*(test_data[test_index].fd),
273		      test_data[test_index].offset,
274		      test_data[test_index].nbytes,
275		      test_data[test_index].flags));
276
277		if (TEST_RETURN != -1) {
278			tst_resm(TFAIL,
279				"call succeeded unexpectedly (%ld != -1)",
280				TEST_RETURN);
281			continue;
282		}
283
284		TEST_ERROR_LOG(TEST_ERRNO);
285
286		if (TEST_ERRNO == test_data[test_index].error) {
287			tst_resm(TPASS|TTERRNO, "got expected error");
288		} else {
289			tst_resm(TFAIL|TTERRNO, "got unexpected error; "
290				 "expected %d",
291				 test_data[test_index].error);
292		}
293
294	}
295
296	cleanup();
297	tst_exit();
298}
299