Home | History | Annotate | Download | only in fallocate
      1 /******************************************************************************
      2  *				 fallocate01.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	: 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 
    108 void get_blocksize(int);
    109 void populate_files(int fd);
    110 void runtest(int, int, loff_t);
    111 
    112 char *TCID = "fallocate01";
    113 char fname_mode1[255], fname_mode2[255];	/* Files used for testing */
    114 int fd_mode1, fd_mode2;
    115 int TST_TOTAL = 2;
    116 loff_t block_size;
    117 int 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 ******************************************************************************/
    125 void 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  ******************************************************************************/
    140 void 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  ******************************************************************************/
    166 void 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 
    182 void 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 
    198 int 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  ******************************************************************************/
    224 void 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