Home | History | Annotate | Download | only in fallocate
      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