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 <fcntl.h> 97#include <sys/syscall.h> 98#include <unistd.h> 99#include <inttypes.h> 100#include <sys/utsname.h> 101 102#include "test.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 = open(fname_mode1, O_RDWR | O_CREAT, 0700); 149 if (fd_mode1 == -1) 150 tst_brkm(TBROK | TERRNO, cleanup, "open(%s, O_RDWR) failed", 151 fname_mode1); 152 get_blocksize(fd_mode1); 153 populate_files(fd_mode1); 154 155 sprintf(fname_mode2, "tfile_mode2_%d", getpid()); 156 fd_mode2 = open(fname_mode2, O_RDWR | O_CREAT, 0700); 157 if (fd_mode2 == -1) 158 tst_brkm(TBROK | TERRNO, cleanup, "open(%s, O_RDWR) failed", 159 fname_mode2); 160 populate_files(fd_mode2); 161} 162 163/***************************************************************************** 164 * Gets the block size for the file system 165 ******************************************************************************/ 166void get_blocksize(int fd) 167{ 168 struct stat file_stat; 169 170 if (fstat(fd, &file_stat) < 0) 171 tst_resm(TFAIL | TERRNO, 172 "fstat failed while getting block_size"); 173 174 block_size = file_stat.st_blksize; 175 buf_size = block_size; 176} 177 178/***************************************************************************** 179 * Writes data into the file 180 ******************************************************************************/ 181 182void populate_files(int fd) 183{ 184 char buf[buf_size + 1]; 185 int index; 186 int blocks; 187 int data; 188 189 for (blocks = 0; blocks < BLOCKS_WRITTEN; blocks++) { 190 for (index = 0; index < buf_size; index++) 191 buf[index] = 'A' + (index % 26); 192 buf[buf_size] = '\0'; 193 if ((data = write(fd, buf, buf_size)) == -1) 194 tst_brkm(TBROK | TERRNO, cleanup, "write failed"); 195 } 196} 197 198int main(int ac, char **av) 199{ 200 loff_t expected_size; 201 int lc; 202 203 tst_parse_opts(ac, av, NULL, NULL); 204 205 setup(); 206 207 for (lc = 0; TEST_LOOPING(lc); lc++) { 208 tst_count = 0; 209 210 expected_size = BLOCKS_WRITTEN * block_size + block_size; 211 runtest(0, fd_mode1, expected_size); 212 213 expected_size = BLOCKS_WRITTEN * block_size; 214 runtest(FALLOC_FL_KEEP_SIZE, fd_mode2, expected_size); 215 } 216 217 cleanup(); 218 tst_exit(); 219} 220 221/***************************************************************************** 222 * Calls the system call, with appropriate parameters and writes data 223 ******************************************************************************/ 224void runtest(int mode, int fd, loff_t expected_size) 225{ 226 loff_t offset; 227 loff_t len = block_size; 228 loff_t write_offset, lseek_offset; 229 offset = lseek(fd, 0, SEEK_END); 230 struct stat file_stat; 231 errno = 0; 232 233 TEST(fallocate(fd, mode, offset, len)); 234 /* check return code */ 235 if (TEST_RETURN != 0) { 236 if (TEST_ERRNO == EOPNOTSUPP || TEST_ERRNO == ENOSYS) { 237 tst_brkm(TCONF, cleanup, 238 "fallocate system call is not implemented"); 239 } 240 tst_resm(TFAIL | TTERRNO, 241 "fallocate(%d, %d, %" PRId64 ", %" PRId64 ") failed", 242 fd, mode, offset, len); 243 return; 244 } else { 245 tst_resm(TPASS, 246 "fallocate(%d, %d, %" PRId64 ", %" PRId64 247 ") returned %ld", fd, mode, offset, len, 248 TEST_RETURN); 249 } 250 251 if (fstat(fd, &file_stat) < 0) 252 tst_resm(TFAIL | TERRNO, "fstat failed after fallocate()"); 253 254 if (file_stat.st_size != expected_size) 255 tst_resm(TFAIL | TTERRNO, 256 "fstat test fails on fallocate (%d, %d, %" PRId64 ", %" 257 PRId64 ") Failed on mode", fd, mode, offset, len); 258 259 write_offset = random() % len; 260 lseek_offset = lseek(fd, write_offset, SEEK_CUR); 261 if (lseek_offset != offset + write_offset) { 262 tst_resm(TFAIL | TTERRNO, 263 "lseek fails in fallocate(%d, %d, %" PRId64 ", %" 264 PRId64 ") failed on mode", fd, mode, offset, len); 265 return; 266 } 267 //Write a character to file at random location 268 TEST(write(fd, "A", 1)); 269 /* check return code */ 270 if (TEST_RETURN == -1) { 271 tst_resm(TFAIL | TTERRNO, 272 "write fails in fallocate(%d, %d, %" PRId64 ", %" 273 PRId64 ") failed", fd, mode, offset, len); 274 } else { 275 tst_resm(TPASS, 276 "write operation on fallocated(%d, %d, %" 277 PRId64 ", %" PRId64 ") returned %ld", fd, mode, 278 offset, len, TEST_RETURN); 279 } 280} 281