1 /****************************************************************************** 2 * fallocate03.c 3 * Mon Dec 24 2007 4 * Copyright (c) International Business Machines Corp., 2007 5 * Emali : sharyathi (at) in.ibm.com 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 the 17 * GNU Library 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 * OS Test - International Business Machines Corp. 2007. 27 * 28 * TEST IDENTIFIER : fallocate03 29 * 30 * EXECUTED BY : anyone 31 * 32 * TEST TITLE : fallocate 33 * 34 * TEST CASE TOTAL : 8 35 * 36 * CPU ARCHITECTURES : PPC,X86, X86_64 37 * 38 * AUTHOR : Sharyathi Nagesh 39 * 40 * CO-PILOT : 41 * 42 * DATE STARTED : 24/12/2007 43 * 44 * TEST CASES 45 * (Working of fallocate on a sparse file) 46 * 47 * 48 * INPUT SPECIFICATIONS 49 * No input needs to be specified 50 * fallocate() in-puts are specified through test_data 51 * 52 * OUTPUT SPECIFICATIONS 53 * Output describing whether test cases passed or failed. 54 * 55 * ENVIRONMENTAL NEEDS 56 * Test Needs to be executed on file system supporting ext4 57 * LTP {TMP} Needs to be set to such a folder 58 * 59 * SPECIAL PROCEDURAL REQUIREMENTS 60 * None 61 * 62 * DETAILED DESCRIPTION 63 * This is a test case for fallocate() system call. 64 * This test suite tests working of fallocate on sparse file 65 * fallocate is tested for different offsets 66 * 67 * Total 8 Test Cases :- 68 * Different offsets with in a sparse file is tested 69 * 70 * Setup: 71 * Setup file on which fallocate is to be called 72 * Set up a file with hole, created through lseek 73 * 74 * Test: 75 * Loop if the proper options are given 76 * Execute system call 77 * Check return code, if system call failed 78 * TEST fails, PASS the test otherwise 79 * 80 * Cleanup: 81 * Cleanup the temporary folder 82 * 83 *************************************************************************/ 84 85 #define _GNU_SOURCE 86 87 #include <stdio.h> 88 #include <stdlib.h> 89 #include <endian.h> 90 #include <errno.h> 91 #include <sys/stat.h> 92 #include <sys/types.h> //Can be done with out 93 #include <fcntl.h> 94 #include <unistd.h> 95 #include <inttypes.h> 96 #include <sys/utsname.h> 97 98 #include "test.h" 99 #include "safe_macros.h" 100 #include "lapi/fallocate.h" 101 102 #define BLOCKS_WRITTEN 12 103 #define HOLE_SIZE_IN_BLOCKS 12 104 #define DEFAULT_MODE 0 105 #define TRUE 0 106 107 void get_blocksize(int); 108 void populate_file(); 109 void file_seek(off_t); 110 111 char *TCID = "fallocate03"; 112 char fname[255]; 113 int fd; 114 struct test_data_t { 115 int mode; 116 loff_t offset; 117 loff_t len; 118 int error; 119 } test_data[] = { 120 { 121 DEFAULT_MODE, 2, 1, TRUE}, { 122 DEFAULT_MODE, BLOCKS_WRITTEN, 1, TRUE}, { 123 DEFAULT_MODE, BLOCKS_WRITTEN + HOLE_SIZE_IN_BLOCKS / 2 - 1, 1, TRUE}, 124 { 125 DEFAULT_MODE, BLOCKS_WRITTEN + HOLE_SIZE_IN_BLOCKS + 1, 1, TRUE}, { 126 FALLOC_FL_KEEP_SIZE, 2, 1, TRUE}, { 127 FALLOC_FL_KEEP_SIZE, BLOCKS_WRITTEN, 1, TRUE}, { 128 FALLOC_FL_KEEP_SIZE, 129 BLOCKS_WRITTEN + HOLE_SIZE_IN_BLOCKS / 2 + 1, 1, TRUE}, { 130 FALLOC_FL_KEEP_SIZE, BLOCKS_WRITTEN + HOLE_SIZE_IN_BLOCKS + 2, 131 1, TRUE} 132 }; 133 134 int TST_TOTAL = sizeof(test_data) / sizeof(test_data[0]); 135 int block_size; 136 int buf_size; 137 138 /****************************************************************************** 139 * Performs all one time clean up for this test on successful 140 * completion, premature exit or failure. Closes all temporary 141 * files, removes all temporary directories exits the test with 142 * appropriate return code by calling tst_exit() function. 143 ******************************************************************************/ 144 void cleanup(void) 145 { 146 /* Close all open file descriptors. */ 147 if (close(fd) == -1) 148 tst_resm(TWARN | TERRNO, "close(%s) failed", fname); 149 150 tst_rmdir(); 151 152 } 153 154 /***************************************************************************** 155 * Performs all one time setup for this test. This function is 156 * used to create temporary dirs and temporary files 157 * that may be used in the course of this test 158 ******************************************************************************/ 159 160 void setup(void) 161 { 162 /* Create temporary directories */ 163 TEST_PAUSE; 164 165 tst_tmpdir(); 166 167 sprintf(fname, "tfile_sparse_%d", getpid()); 168 fd = SAFE_OPEN(cleanup, fname, O_RDWR | O_CREAT, 0700); 169 get_blocksize(fd); 170 populate_file(); 171 file_seek(BLOCKS_WRITTEN + HOLE_SIZE_IN_BLOCKS); /* create holes */ 172 populate_file(); 173 file_seek(0); /* Rewind */ 174 } 175 176 /***************************************************************************** 177 * Gets the block size for the file system 178 ******************************************************************************/ 179 void get_blocksize(int fd) 180 { 181 struct stat file_stat; 182 183 if (fstat(fd, &file_stat) < 0) 184 tst_resm(TFAIL | TERRNO, 185 "fstat failed while getting block_size"); 186 187 block_size = (int)file_stat.st_blksize; 188 buf_size = block_size; 189 } 190 191 /***************************************************************************** 192 * Create a Hole in the file 193 ******************************************************************************/ 194 void file_seek(off_t offset) 195 { 196 offset *= block_size; 197 lseek(fd, offset, SEEK_SET); 198 } 199 200 /***************************************************************************** 201 * Writes data into the file 202 ******************************************************************************/ 203 void populate_file(void) 204 { 205 char buf[buf_size + 1]; 206 int index; 207 int blocks; 208 int data; 209 for (blocks = 0; blocks < BLOCKS_WRITTEN; blocks++) { 210 for (index = 0; index < buf_size; index++) 211 buf[index] = 'A' + (index % 26); 212 buf[buf_size] = '\0'; 213 if ((data = write(fd, buf, buf_size)) < 0) 214 tst_brkm(TBROK | TERRNO, cleanup, 215 "Unable to write to %s", fname); 216 } 217 } 218 219 /***************************************************************************** 220 * Main function that calls the system call with the appropriate parameters 221 ******************************************************************************/ 222 /* ac: number of command line parameters */ 223 /* av: pointer to the array of the command line parameters */ 224 int main(int ac, char **av) 225 { 226 int test_index = 0; 227 int lc; 228 229 /*************************************************************** 230 * parse standard options 231 ***************************************************************/ 232 tst_parse_opts(ac, av, NULL, NULL); 233 234 /* perform global test setup, call setup() function */ 235 setup(); 236 237 for (lc = 0; TEST_LOOPING(lc); lc++) { 238 /* reset tst_count in case we are looping */ 239 tst_count = 0; 240 for (test_index = 0; test_index < TST_TOTAL; test_index++) { 241 TEST(fallocate 242 (fd, test_data[test_index].mode, 243 test_data[test_index].offset * block_size, 244 test_data[test_index].len * block_size)); 245 246 /* check return code */ 247 if (TEST_RETURN != test_data[test_index].error) { 248 if (TEST_ERRNO == EOPNOTSUPP 249 || TEST_ERRNO == ENOSYS) { 250 tst_brkm(TCONF, cleanup, 251 "fallocate system call is not implemented"); 252 } 253 tst_resm(TFAIL | TTERRNO, 254 "fallocate(%s, %d, %" PRId64 ", %" 255 PRId64 ") failed", fname, 256 test_data[test_index].mode, 257 test_data[test_index].offset * 258 block_size, 259 test_data[test_index].len * 260 block_size); 261 } else { 262 tst_resm(TPASS, 263 "fallocate(%s, %d, %" PRId64 264 ", %" PRId64 ") returned %ld", 265 fname, 266 test_data[test_index].mode, 267 test_data[test_index].offset * 268 block_size, 269 test_data[test_index].len * 270 block_size, TEST_RETURN); 271 } 272 } 273 } 274 275 cleanup(); 276 tst_exit(); 277 } 278