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