sync_file_range01.c revision 43337a3cf6f8809647cf9fc6c0054241f44b1fb1
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    */
22/*                                                                            */
23/******************************************************************************/
24
25
26/*****************************************************************************
27 *    TEST IDENTIFIER  		: sync_file_range01
28 *
29 *    EXECUTED BY               : anyone
30 *
31 *    TEST TITLE                : Checks for Errors from sync_file_range()
32 *
33 *    TEST CASE TOTAL  		: 5
34 *
35 *    CPU ARCHITECTURES        	: All
36 *
37 *    AUTHOR                    : B N Poornima
38 *
39 *    DATE STARTED             : 21/07/2008
40 *
41 *    TEST CASES
42 *    (Tests sync_file_range() for different test cases as reported in the man
43 *      page)
44 *
45 *     INPUT SPECIFICATIONS
46 *             No input needs to be specified
47 *               sync_file_data() in-puts are specified through test_data
48 *
49 *     OUTPUT SPECIFICATIONS
50 *             sync_file_data() error message matches with the expected error
51 *		message.
52 *
53 *     ENVIRONMENTAL NEEDS
54 *		Kernel version 2.6.17 and above
55 *              Kernel version 2.6.22 and above in case of PPC and PPC64
56 *
57 *     SPECIAL PROCEDURAL REQUIREMENTS
58 *             None
59 *
60 *     DETAILED DESCRIPTION
61 *             This is a test case for sync_file_range() system call.
62 *             This test suite tests various error messages from the system call
63 *             If the error message received matches with the expected
64 *             test is considered passed else test fails
65 *
66 *             Total 5 Test Cases :-
67 *             Various error messages from the man page
68 *
69 *     Setup:
70 *             Setup files on which sync_file_range is to be called
71 *
72 *     Test:
73 *             Loop if the proper options are given.
74 *             Execute system call
75 *	       Check return code.
76 *             If error obtained matches with the expected error
77 *             PASS the test, otherwise TEST FAILS
78 *
79 *     Cleanup:
80 *             Cleanup the temporary folder
81 *
82 ******************************************************************************/
83#define _GNU_SOURCE
84
85/* Standard Include Files */
86#include <stdio.h>
87#include <stdlib.h>
88#include <errno.h>
89#include <sys/stat.h>
90#include <sys/types.h>
91#include <fcntl.h>
92#include <sys/utsname.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
101#if defined(__powerpc__) || defined(__powerpc64__)
102 #ifndef __NR_sync_file_range2
103        #define __NR_sync_file_range2 -1  //DUMMY VALUE
104        int arch_support = 0;    //Architecure is not supported
105 #else
106        int arch_support = 1;   //Architecture is supported
107 #endif
108#else
109   #ifndef __NR_sync_file_range
110        #define __NR_sync_file_range -1 //DUMMY Value
111        int arch_support = 0;
112   #else
113        int arch_support = 1;
114   #endif
115#endif
116
117
118#ifndef SYNC_FILE_RANGE_WAIT_BEFORE
119#define SYNC_FILE_RANGE_WAIT_BEFORE 1
120#define SYNC_FILE_RANGE_WRITE 2			//DUMMY VALUES
121#define SYNC_FILE_RANGE_WAIT_AFTER 4
122#endif
123
124#define SYNC_FILE_RANGE_INVALID 8
125
126/* Extern Global Variables */
127extern int  Tst_count;               /* counter for tst_xxx routines.         */
128extern char *TESTDIR;                /* temporary dir created by tst_tmpdir() */
129
130/* Global Variables */
131char *TCID     = "sync_file_range01";  /* test program identifier.          */
132char filename[255];  			/* file used for testing */
133char spl_file[] = "/dev/null";
134int filed, sfd;  			/* normal and special fds */
135int bfd = -1;     			/* Bad file descriptor */
136
137struct test_data_t
138{
139        int *fd;
140        off64_t offset;
141        off64_t nbytes;
142        unsigned int flags;
143        int error;
144} test_data[] = {
145		  {&bfd, 0, 1, SYNC_FILE_RANGE_WRITE, EBADF},
146		  {&sfd, 0, 1, SYNC_FILE_RANGE_WAIT_AFTER, ESPIPE},
147		  {&filed, -1, 1, SYNC_FILE_RANGE_WAIT_BEFORE, EINVAL},
148		  {&filed, 0, -1, SYNC_FILE_RANGE_WRITE, EINVAL},
149		  {&filed, 0, 1, SYNC_FILE_RANGE_INVALID, EINVAL}
150		 };
151
152int TST_TOTAL = sizeof(test_data) / sizeof(test_data[0]);
153
154
155
156
157/* Extern Global Functions */
158/******************************************************************************/
159/*                                                                            */
160/* Function:    cleanup                                                       */
161/*                                                                            */
162/* Description: Performs all one time clean up for this test on successful    */
163/*              completion,  premature exit or  failure. Closes all temporary */
164/*              files, removes all temporary directories exits the test with  */
165/*              appropriate return code by calling tst_exit() function.       */
166/*                                                                            */
167/* Input:       None.                                                         */
168/*                                                                            */
169/* Output:      None.                                                         */
170/*                                                                            */
171/* Return:      On failure - Exits calling tst_exit(). Non '0' return code.   */
172/*              On success - Exits calling tst_exit(). With '0' return code.  */
173/*                                                                            */
174/******************************************************************************/
175extern void
176cleanup()
177{
178    /*
179     * print timing stats if that option was specified.
180     * print errno log if that option was specified.
181     */
182    TEST_CLEANUP;
183
184    /* close the file we have open */
185    if (close(filed) == -1) {
186       tst_resm(TWARN, "close(%s) Failed, errno=%d : %s", filename, errno, strerror(errno));
187    }
188
189    /* Remove tmp dir and all files in it */
190    tst_rmdir();
191
192    /* exit with return code appropriate for results */
193    tst_exit();
194
195	tst_exit();
196}
197
198
199/* Local  Functions */
200/******************************************************************************/
201/*                                                                            */
202/* Function:    setup                                                         */
203/*                                                                            */
204/* Description: Performs all one time setup for this test. This function is   */
205/*              typically used to capture signals, create temporary dirs      */
206/*              and temporary files that may be used in the course of this    */
207/*              test.                                                         */
208/*                                                                            */
209/* Input:       None.                                                         */
210/*                                                                            */
211/* Output:      None.                                                         */
212/*                                                                            */
213/* Return:      On failure - Exits by calling cleanup().                      */
214/*              On success - returns 0.                                       */
215/*                                                                            */
216/******************************************************************************/
217void
218setup()
219{
220/* capture signals */
221    tst_sig(NOFORK, DEF_HANDLER, cleanup);
222
223    /* Pause if that option was specified */
224    TEST_PAUSE;
225
226    /* make a temp directory and cd to it */
227    tst_tmpdir();
228
229    sprintf(filename,"tmpfile_%d",getpid());
230    if ((filed = open(filename,O_RDWR|O_CREAT,0700)) == -1) {
231       tst_brkm(TBROK, cleanup,
232                "open(%s, O_RDWR|O_CREAT,0700) Failed, errno=%d : %s",
233                filename, errno, strerror(errno));
234
235	sfd = open(spl_file, O_RDWR|O_CREAT, 0700);
236
237    }
238
239return;
240}
241
242/*****************************************************************************
243 * Wraper function to call sync_file_range system call
244 ******************************************************************************/
245static inline long syncfilerange(int fd, off64_t offset, off64_t nbytes, unsigned int flags)
246{
247
248	#if (defined(__powerpc64__) || defined(__powerpc__)) && (__WORDSIZE==32)
249
250	       	  return syscall(__NR_sync_file_range2, fd, flags, (int)(offset >>32), \
251					(int)offset, (int)(nbytes >>32), (int)nbytes);
252
253	#elif (defined(__powerpc64__) || defined(__powerpc__)) && (__WORDSIZE==64)
254
255		  return syscall(__NR_sync_file_range2, fd, flags, offset, nbytes);
256	#else
257
258		  return syscall(__NR_sync_file_range, fd, offset, nbytes, flags);
259	#endif
260
261	return 0;
262}
263
264
265
266
267
268/******************************************************************************/
269/*                                                                            */
270/* Function:    main                                                          */
271/*                                                                            */
272/* Description: Entry point to this test-case. It parses all the command line */
273/*              inputs, calls the global setup and executes the test. It logs */
274/*              the test status and results appropriately using the LTP API's */
275/*              On successful completion or premature failure, cleanup() func */
276/*              is called and test exits with an appropriate return code.     */
277/*                                                                            */
278/* Input:       Describe input arguments to this test-case                    */
279/*               -l - Number of iteration                                     */
280/*               -v - Prints verbose output                                   */
281/*               -V - Prints the version number                               */
282/*                                                                            */
283/* Exit:       On failure - Exits by calling cleanup().                       */
284/*             On success - exits with 0 exit value.                          */
285/*                                                                            */
286/******************************************************************************/
287int
288main(int   ac,    	/* number of command line parameters                      */
289        char **av)   	/* pointer to the array of the command line parameters.   */
290{
291
292 int test_index = 0;
293        int lc;
294	char *msg;
295
296 /***************************************************************
297              parse standard options
298  ********************************************************************/
299        if ( (msg=parse_opts(ac, av, (option_t *) NULL, NULL)) != (char *) NULL )
300                tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg);
301
302
303#if defined(__powerpc__) || defined(__powerpc64__)     /* for PPC, kernel version > 2.6.21 needed */
304                if ( !arch_support || (tst_kvercmp(2,16,22) < 0)) {
305                        tst_resm(TCONF, "System doesn't support execution of the test");
306                        tst_exit();
307                }
308#else
309        /* For other archs, need kernel version > 2.6.16 */
310
311        if ( !arch_support || (tst_kvercmp(2,6,17) < 0)) {
312                tst_resm(TCONF, "System doesn't support execution of the test");
313                tst_exit();
314        }
315
316#endif
317
318/* perform global test setup, call setup() function. */
319setup();
320
321for (lc=0; TEST_LOOPING(lc); lc++) {
322                /* reset Tst_count in case we are looping. */
323                Tst_count=0;
324
325                for(test_index = 0 ; test_index < TST_TOTAL; test_index ++)
326                {
327	   	  TEST(syncfilerange(*(test_data[test_index].fd), test_data[test_index].offset, \
328		        test_data[test_index].nbytes, test_data[test_index].flags));
329
330
331			 if (TEST_RETURN != -1) {
332                                tst_resm(TFAIL, "call succeeded unexpectedly");
333                                continue;
334                        }
335
336                        TEST_ERROR_LOG(TEST_ERRNO);
337
338                        if (TEST_ERRNO == test_data[test_index].error) {
339                                tst_resm(TPASS, "expected failure - "
340                                         "errno = %d : %s", TEST_ERRNO,
341                                         strerror(TEST_ERRNO));
342                        } else {
343                                tst_resm(TFAIL, "unexpected error - %d : %s - "
344                                         "expected %d", TEST_ERRNO,
345                                         strerror(TEST_ERRNO), test_data[test_index].error);
346                        }
347                }
348
349	}
350
351cleanup();
352return 0;
353}
354