1/****************************************************************************** 2 * fallocate01.c 3 * Mon Dec 24 2007 4 * Copyright (c) International Business Machines Corp., 2007 5 * Emali : sharyathi@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 : fallocate01 29 * 30 * EXECUTED BY : anyone 31 * 32 * TEST TITLE : Basic test for fallocate() 33 * 34 * TEST CASE TOTAL : 2 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 under 2 modes) 46 * 1) DEFAULT 2)FALLOC_FL_KEEP_SIZE 47 * 48 * INPUT SPECIFICATIONS 49 * No input needs to be specified 50 * fallocate() in puts are generated randomly 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 basic working of fallocate under different modes 65 * It trys to fallocate memory blocks and write into that block 66 * 67 * Total 2 Test Cases :- 68 * (1) Test Case for DEFAULT MODE 69 * (2) Test Case for FALLOC_FL_KEEP_SIZE 70 * 71 * Setup: 72 * Setup file on which fallocate is to be called 73 * Set up 2 files for each mode 74 * 75 * Test: 76 * Loop if the proper options are given. 77 * Execute system call 78 * Check return code, if system call did fail 79 * lseek to some random location with in allocate block 80 * write data into the locattion Report if any error encountered 81 * PASS the test otherwise 82 * 83 * Cleanup: 84 * Cleanup the temporary folder 85 * 86*************************************************************************/ 87 88#define _GNU_SOURCE 89 90#include <stdio.h> 91#include <stdlib.h> 92#include <endian.h> 93#include <errno.h> 94#include <sys/stat.h> 95#include <sys/types.h> 96#include <sys/syscall.h> 97#include <unistd.h> 98#include <inttypes.h> 99#include <sys/utsname.h> 100 101#include "test.h" 102#include "safe_macros.h" 103#include "lapi/fallocate.h" 104#include "lapi/fcntl.h" 105 106#define BLOCKS_WRITTEN 12 107 108void get_blocksize(int); 109void populate_files(int fd); 110void runtest(int, int, loff_t); 111 112char *TCID = "fallocate01"; 113char fname_mode1[255], fname_mode2[255]; /* Files used for testing */ 114int fd_mode1, fd_mode2; 115int TST_TOTAL = 2; 116loff_t block_size; 117int buf_size; 118 119/****************************************************************************** 120 * Performs all one time clean up for this test on successful 121 * completion, premature exit or failure. Closes all temporary 122 * files, removes all temporary directories exits the test with 123 * appropriate return code by calling tst_exit() function. 124******************************************************************************/ 125void cleanup(void) 126{ 127 128 if (close(fd_mode1) == -1) 129 tst_resm(TWARN | TERRNO, "close(%s) failed", fname_mode1); 130 if (close(fd_mode2) == -1) 131 tst_resm(TWARN | TERRNO, "close(%s) failed", fname_mode2); 132 tst_rmdir(); 133} 134 135/***************************************************************************** 136 * Performs all one time setup for this test. This function is 137 * used to create temporary dirs and temporary files 138 * that may be used in the course of this test 139 ******************************************************************************/ 140void setup(void) 141{ 142 /* Create temporary directories */ 143 TEST_PAUSE; 144 145 tst_tmpdir(); 146 147 sprintf(fname_mode1, "tfile_mode1_%d", getpid()); 148 fd_mode1 = SAFE_OPEN(cleanup, fname_mode1, O_RDWR | O_CREAT, 0700); 149 get_blocksize(fd_mode1); 150 populate_files(fd_mode1); 151 152 sprintf(fname_mode2, "tfile_mode2_%d", getpid()); 153 fd_mode2 = SAFE_OPEN(cleanup, fname_mode2, O_RDWR | O_CREAT, 0700); 154 populate_files(fd_mode2); 155} 156 157/***************************************************************************** 158 * Gets the block size for the file system 159 ******************************************************************************/ 160void get_blocksize(int fd) 161{ 162 struct stat file_stat; 163 164 if (fstat(fd, &file_stat) < 0) 165 tst_resm(TFAIL | TERRNO, 166 "fstat failed while getting block_size"); 167 168 block_size = file_stat.st_blksize; 169 buf_size = block_size; 170} 171 172/***************************************************************************** 173 * Writes data into the file 174 ******************************************************************************/ 175 176void populate_files(int fd) 177{ 178 char buf[buf_size + 1]; 179 int index; 180 int blocks; 181 int data; 182 183 for (blocks = 0; blocks < BLOCKS_WRITTEN; blocks++) { 184 for (index = 0; index < buf_size; index++) 185 buf[index] = 'A' + (index % 26); 186 buf[buf_size] = '\0'; 187 if ((data = write(fd, buf, buf_size)) == -1) 188 tst_brkm(TBROK | TERRNO, cleanup, "write failed"); 189 } 190} 191 192int main(int ac, char **av) 193{ 194 loff_t expected_size; 195 int lc; 196 197 tst_parse_opts(ac, av, NULL, NULL); 198 199 setup(); 200 201 for (lc = 0; TEST_LOOPING(lc); lc++) { 202 tst_count = 0; 203 204 expected_size = BLOCKS_WRITTEN * block_size + block_size; 205 runtest(0, fd_mode1, expected_size); 206 207 expected_size = BLOCKS_WRITTEN * block_size; 208 runtest(FALLOC_FL_KEEP_SIZE, fd_mode2, expected_size); 209 } 210 211 cleanup(); 212 tst_exit(); 213} 214 215/***************************************************************************** 216 * Calls the system call, with appropriate parameters and writes data 217 ******************************************************************************/ 218void runtest(int mode, int fd, loff_t expected_size) 219{ 220 loff_t offset; 221 loff_t len = block_size; 222 loff_t write_offset, lseek_offset; 223 offset = lseek(fd, 0, SEEK_END); 224 struct stat file_stat; 225 errno = 0; 226 227 TEST(fallocate(fd, mode, offset, len)); 228 /* check return code */ 229 if (TEST_RETURN != 0) { 230 if (TEST_ERRNO == EOPNOTSUPP || TEST_ERRNO == ENOSYS) { 231 tst_brkm(TCONF, cleanup, 232 "fallocate system call is not implemented"); 233 } 234 tst_resm(TFAIL | TTERRNO, 235 "fallocate(%d, %d, %" PRId64 ", %" PRId64 ") failed", 236 fd, mode, offset, len); 237 return; 238 } else { 239 tst_resm(TPASS, 240 "fallocate(%d, %d, %" PRId64 ", %" PRId64 241 ") returned %ld", fd, mode, offset, len, 242 TEST_RETURN); 243 } 244 245 if (fstat(fd, &file_stat) < 0) 246 tst_resm(TFAIL | TERRNO, "fstat failed after fallocate()"); 247 248 if (file_stat.st_size != expected_size) 249 tst_resm(TFAIL | TERRNO, 250 "fstat test fails on fallocate (%d, %d, %" PRId64 ", %" 251 PRId64 ") Failed on mode", fd, mode, offset, len); 252 253 write_offset = random() % len; 254 lseek_offset = lseek(fd, write_offset, SEEK_CUR); 255 if (lseek_offset != offset + write_offset) { 256 tst_resm(TFAIL | TERRNO, 257 "lseek fails in fallocate(%d, %d, %" PRId64 ", %" 258 PRId64 ") failed on mode", fd, mode, offset, len); 259 return; 260 } 261 //Write a character to file at random location 262 TEST(write(fd, "A", 1)); 263 /* check return code */ 264 if (TEST_RETURN == -1) { 265 tst_resm(TFAIL | TTERRNO, 266 "write fails in fallocate(%d, %d, %" PRId64 ", %" 267 PRId64 ") failed", fd, mode, offset, len); 268 } else { 269 tst_resm(TPASS, 270 "write operation on fallocated(%d, %d, %" 271 PRId64 ", %" PRId64 ") returned %ld", fd, mode, 272 offset, len, TEST_RETURN); 273 } 274} 275