subrata_modak | b1ef993 | 2008-08-18 10:37:42 +0000 | [diff] [blame] | 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 */ |
| 127 | extern int Tst_count; /* counter for tst_xxx routines. */ |
| 128 | extern char *TESTDIR; /* temporary dir created by tst_tmpdir() */ |
| 129 | |
| 130 | /* Global Variables */ |
| 131 | char *TCID = "sync_file_range01"; /* test program identifier. */ |
| 132 | char filename[255]; /* file used for testing */ |
| 133 | char spl_file[] = "/dev/null"; |
| 134 | int filed, sfd; /* normal and special fds */ |
| 135 | int bfd = -1; /* Bad file descriptor */ |
| 136 | |
| 137 | struct 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 | |
| 152 | int 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 | /******************************************************************************/ |
| 175 | extern void |
| 176 | cleanup() |
| 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 | /******************************************************************************/ |
| 217 | void |
| 218 | setup() |
| 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 | |
| 239 | return; |
| 240 | } |
| 241 | |
| 242 | /***************************************************************************** |
| 243 | * Wraper function to call sync_file_range system call |
| 244 | ******************************************************************************/ |
| 245 | static inline long syncfilerange(int fd, off64_t offset, off64_t nbytes, unsigned int flags) |
| 246 | { |
| 247 | |
| 248 | #if defined(__powerpc64__) && (__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__) && (__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 | /******************************************************************************/ |
| 287 | int |
| 288 | main(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 | /* This test needs kernel version > 2.6.16 */ |
| 303 | |
| 304 | if ( !arch_support || (tst_kvercmp(2,6,17) < 0)) { |
| 305 | tst_resm(TCONF, "System doesn't support execution of the test"); |
| 306 | tst_exit(); |
| 307 | } |
| 308 | |
| 309 | |
| 310 | /* perform global test setup, call setup() function. */ |
| 311 | setup(); |
| 312 | |
| 313 | for (lc=0; TEST_LOOPING(lc); lc++) { |
| 314 | /* reset Tst_count in case we are looping. */ |
| 315 | Tst_count=0; |
| 316 | |
| 317 | for(test_index = 0 ; test_index < TST_TOTAL; test_index ++) |
| 318 | { |
| 319 | TEST(syncfilerange(*(test_data[test_index].fd), test_data[test_index].offset, \ |
| 320 | test_data[test_index].nbytes, test_data[test_index].flags)); |
| 321 | |
| 322 | |
| 323 | if (TEST_RETURN != -1) { |
| 324 | tst_resm(TFAIL, "call succeeded unexpectedly"); |
| 325 | continue; |
| 326 | } |
| 327 | |
| 328 | TEST_ERROR_LOG(TEST_ERRNO); |
| 329 | |
| 330 | if (TEST_ERRNO == test_data[test_index].error) { |
| 331 | tst_resm(TPASS, "expected failure - " |
| 332 | "errno = %d : %s", TEST_ERRNO, |
| 333 | strerror(TEST_ERRNO)); |
| 334 | } else { |
| 335 | tst_resm(TFAIL, "unexpected error - %d : %s - " |
| 336 | "expected %d", TEST_ERRNO, |
| 337 | strerror(TEST_ERRNO), test_data[test_index].error); |
| 338 | } |
| 339 | } |
| 340 | |
| 341 | } |
| 342 | |
| 343 | cleanup(); |
| 344 | return(0); |
| 345 | } |