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 <inttypes.h>
100 #include <sys/utsname.h>
101
102 #include "test.h"
103 #include "safe_macros.h"
104 #include "lapi/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 = SAFE_OPEN(cleanup, fname_mode1, O_RDWR | O_CREAT, 0700);
150 get_blocksize(fd_mode1);
151 populate_files(fd_mode1);
152
153 sprintf(fname_mode2, "tfile_mode2_%d", getpid());
154 fd_mode2 = SAFE_OPEN(cleanup, fname_mode2, O_RDWR | O_CREAT, 0700);
155 populate_files(fd_mode2);
156 }
157
158 /*****************************************************************************
159 * Gets the block size for the file system
160 ******************************************************************************/
get_blocksize(int fd)161 void get_blocksize(int fd)
162 {
163 struct stat file_stat;
164
165 if (fstat(fd, &file_stat) < 0)
166 tst_resm(TFAIL | TERRNO,
167 "fstat failed while getting block_size");
168
169 block_size = file_stat.st_blksize;
170 buf_size = block_size;
171 }
172
173 /*****************************************************************************
174 * Writes data into the file
175 ******************************************************************************/
176
populate_files(int fd)177 void populate_files(int fd)
178 {
179 char buf[buf_size + 1];
180 int index;
181 int blocks;
182 int data;
183
184 for (blocks = 0; blocks < BLOCKS_WRITTEN; blocks++) {
185 for (index = 0; index < buf_size; index++)
186 buf[index] = 'A' + (index % 26);
187 buf[buf_size] = '\0';
188 if ((data = write(fd, buf, buf_size)) == -1)
189 tst_brkm(TBROK | TERRNO, cleanup, "write failed");
190 }
191 }
192
main(int ac,char ** av)193 int main(int ac, char **av)
194 {
195 loff_t expected_size;
196 int lc;
197
198 tst_parse_opts(ac, av, NULL, NULL);
199
200 setup();
201
202 for (lc = 0; TEST_LOOPING(lc); lc++) {
203 tst_count = 0;
204
205 expected_size = BLOCKS_WRITTEN * block_size + block_size;
206 runtest(0, fd_mode1, expected_size);
207
208 expected_size = BLOCKS_WRITTEN * block_size;
209 runtest(FALLOC_FL_KEEP_SIZE, fd_mode2, expected_size);
210 }
211
212 cleanup();
213 tst_exit();
214 }
215
216 /*****************************************************************************
217 * Calls the system call, with appropriate parameters and writes data
218 ******************************************************************************/
runtest(int mode,int fd,loff_t expected_size)219 void runtest(int mode, int fd, loff_t expected_size)
220 {
221 loff_t offset;
222 loff_t len = block_size;
223 loff_t write_offset, lseek_offset;
224 offset = lseek(fd, 0, SEEK_END);
225 struct stat file_stat;
226 errno = 0;
227
228 TEST(fallocate(fd, mode, offset, len));
229 /* check return code */
230 if (TEST_RETURN != 0) {
231 if (TEST_ERRNO == EOPNOTSUPP || TEST_ERRNO == ENOSYS) {
232 tst_brkm(TCONF, cleanup,
233 "fallocate system call is not implemented");
234 }
235 tst_resm(TFAIL | TTERRNO,
236 "fallocate(%d, %d, %" PRId64 ", %" PRId64 ") failed",
237 fd, mode, offset, len);
238 return;
239 } else {
240 tst_resm(TPASS,
241 "fallocate(%d, %d, %" PRId64 ", %" PRId64
242 ") returned %ld", fd, mode, offset, len,
243 TEST_RETURN);
244 }
245
246 if (fstat(fd, &file_stat) < 0)
247 tst_resm(TFAIL | TERRNO, "fstat failed after fallocate()");
248
249 if (file_stat.st_size != expected_size)
250 tst_resm(TFAIL | TTERRNO,
251 "fstat test fails on fallocate (%d, %d, %" PRId64 ", %"
252 PRId64 ") Failed on mode", fd, mode, offset, len);
253
254 write_offset = random() % len;
255 lseek_offset = lseek(fd, write_offset, SEEK_CUR);
256 if (lseek_offset != offset + write_offset) {
257 tst_resm(TFAIL | TTERRNO,
258 "lseek fails in fallocate(%d, %d, %" PRId64 ", %"
259 PRId64 ") failed on mode", fd, mode, offset, len);
260 return;
261 }
262 //Write a character to file at random location
263 TEST(write(fd, "A", 1));
264 /* check return code */
265 if (TEST_RETURN == -1) {
266 tst_resm(TFAIL | TTERRNO,
267 "write fails in fallocate(%d, %d, %" PRId64 ", %"
268 PRId64 ") failed", fd, mode, offset, len);
269 } else {
270 tst_resm(TPASS,
271 "write operation on fallocated(%d, %d, %"
272 PRId64 ", %" PRId64 ") returned %ld", fd, mode,
273 offset, len, TEST_RETURN);
274 }
275 }
276