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