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