• 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 "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 ******************************************************************************/
cleanup(void)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 
setup(void)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  ******************************************************************************/
get_blocksize(int fd)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  ******************************************************************************/
file_seek(off_t offset)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  ******************************************************************************/
populate_file(void)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 */
main(int ac,char ** av)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