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