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 "lapi/fallocate.h" 100 101 #define BLOCKS_WRITTEN 12 102 #define HOLE_SIZE_IN_BLOCKS 12 103 #define DEFAULT_MODE 0 104 #define TRUE 0 105 106 void get_blocksize(int); 107 void populate_file(); 108 void file_seek(off_t); 109 110 char *TCID = "fallocate03"; 111 char fname[255]; 112 int fd; 113 struct test_data_t { 114 int mode; 115 loff_t offset; 116 loff_t len; 117 int error; 118 } test_data[] = { 119 { 120 DEFAULT_MODE, 2, 1, TRUE}, { 121 DEFAULT_MODE, BLOCKS_WRITTEN, 1, TRUE}, { 122 DEFAULT_MODE, BLOCKS_WRITTEN + HOLE_SIZE_IN_BLOCKS / 2 - 1, 1, TRUE}, 123 { 124 DEFAULT_MODE, BLOCKS_WRITTEN + HOLE_SIZE_IN_BLOCKS + 1, 1, TRUE}, { 125 FALLOC_FL_KEEP_SIZE, 2, 1, TRUE}, { 126 FALLOC_FL_KEEP_SIZE, BLOCKS_WRITTEN, 1, TRUE}, { 127 FALLOC_FL_KEEP_SIZE, 128 BLOCKS_WRITTEN + HOLE_SIZE_IN_BLOCKS / 2 + 1, 1, TRUE}, { 129 FALLOC_FL_KEEP_SIZE, BLOCKS_WRITTEN + HOLE_SIZE_IN_BLOCKS + 2, 130 1, TRUE} 131 }; 132 133 int TST_TOTAL = sizeof(test_data) / sizeof(test_data[0]); 134 int block_size; 135 int buf_size; 136 137 /****************************************************************************** 138 * 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 void cleanup(void) 144 { 145 /* Close all open file descriptors. */ 146 if (close(fd) == -1) 147 tst_resm(TWARN | TERRNO, "close(%s) failed", fname); 148 149 tst_rmdir(); 150 151 } 152 153 /***************************************************************************** 154 * Performs all one time setup for this test. This function is 155 * used to create temporary dirs and temporary files 156 * that may be used in the course of this test 157 ******************************************************************************/ 158 159 void setup(void) 160 { 161 /* Create temporary directories */ 162 TEST_PAUSE; 163 164 tst_tmpdir(); 165 166 sprintf(fname, "tfile_sparse_%d", getpid()); 167 fd = open(fname, O_RDWR | O_CREAT, 0700); 168 if (fd == -1) 169 tst_brkm(TBROK | TERRNO, cleanup, "open(%s) failed", fname); 170 get_blocksize(fd); 171 populate_file(); 172 file_seek(BLOCKS_WRITTEN + HOLE_SIZE_IN_BLOCKS); /* create holes */ 173 populate_file(); 174 file_seek(0); /* Rewind */ 175 } 176 177 /***************************************************************************** 178 * Gets the block size for the file system 179 ******************************************************************************/ 180 void get_blocksize(int fd) 181 { 182 struct stat file_stat; 183 184 if (fstat(fd, &file_stat) < 0) 185 tst_resm(TFAIL | TERRNO, 186 "fstat failed while getting block_size"); 187 188 block_size = (int)file_stat.st_blksize; 189 buf_size = block_size; 190 } 191 192 /***************************************************************************** 193 * Create a Hole in the file 194 ******************************************************************************/ 195 void file_seek(off_t offset) 196 { 197 offset *= block_size; 198 lseek(fd, offset, SEEK_SET); 199 } 200 201 /***************************************************************************** 202 * Writes data into the file 203 ******************************************************************************/ 204 void populate_file(void) 205 { 206 char buf[buf_size + 1]; 207 int index; 208 int blocks; 209 int data; 210 for (blocks = 0; blocks < BLOCKS_WRITTEN; blocks++) { 211 for (index = 0; index < buf_size; index++) 212 buf[index] = 'A' + (index % 26); 213 buf[buf_size] = '\0'; 214 if ((data = write(fd, buf, buf_size)) < 0) 215 tst_brkm(TBROK | TERRNO, cleanup, 216 "Unable to write to %s", fname); 217 } 218 } 219 220 /***************************************************************************** 221 * Main function that calls the system call with the appropriate parameters 222 ******************************************************************************/ 223 /* ac: number of command line parameters */ 224 /* av: pointer to the array of the command line parameters */ 225 int main(int ac, char **av) 226 { 227 int test_index = 0; 228 int lc; 229 230 /*************************************************************** 231 * parse standard options 232 ***************************************************************/ 233 tst_parse_opts(ac, av, NULL, NULL); 234 235 /* perform global test setup, call setup() function */ 236 setup(); 237 238 for (lc = 0; TEST_LOOPING(lc); lc++) { 239 /* reset tst_count in case we are looping */ 240 tst_count = 0; 241 for (test_index = 0; test_index < TST_TOTAL; test_index++) { 242 TEST(fallocate 243 (fd, test_data[test_index].mode, 244 test_data[test_index].offset * block_size, 245 test_data[test_index].len * block_size)); 246 247 /* check return code */ 248 if (TEST_RETURN != test_data[test_index].error) { 249 if (TEST_ERRNO == EOPNOTSUPP 250 || TEST_ERRNO == ENOSYS) { 251 tst_brkm(TCONF, cleanup, 252 "fallocate system call is not implemented"); 253 } 254 tst_resm(TFAIL | TTERRNO, 255 "fallocate(%s, %d, %" PRId64 ", %" 256 PRId64 ") failed", fname, 257 test_data[test_index].mode, 258 test_data[test_index].offset * 259 block_size, 260 test_data[test_index].len * 261 block_size); 262 } else { 263 tst_resm(TPASS, 264 "fallocate(%s, %d, %" PRId64 265 ", %" PRId64 ") returned %ld", 266 fname, 267 test_data[test_index].mode, 268 test_data[test_index].offset * 269 block_size, 270 test_data[test_index].len * 271 block_size, TEST_RETURN); 272 } 273 } 274 } 275 276 cleanup(); 277 tst_exit(); 278 } 279