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