2 * Copyright (c) 2000-2001 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <sys/types.h>
23 #include <lib/errtest.h>
29 /*---------------------------------------------------------------------------
31 Test program used to test the DMAPI function dm_punch_hole(). The
34 test_hole [-v] [-s sid] pathname
38 is the path to a specific copy of ls, important only for its size
40 is the path to the test filesystem
42 is the session ID whose events you you are interested in.
44 ----------------------------------------------------------------------------*/
47 extern char *sys_errlist[];
58 fprintf(stderr, "usage:\t%s [-v] [-s sid] ls_path directoryname\n",
69 dm_sessid_t sid = DM_NO_SESSION;
70 char *pathname = NULL;
72 dm_off_t offset = 0, end;
74 dm_extent_t extent[20];
79 dm_token_t test_token;
87 dm_off_t blocksize = 5;
93 Progname = strrchr(argv[0], '/');
100 /* Crack and validate the command line options. */
102 while ((opt = getopt(argc, argv, "vs:")) != EOF) {
114 if (optind + 2 != argc)
116 ls_path = argv[optind];
117 pathname = argv[optind+1];
119 if (dm_init_service(&name) == -1) {
120 fprintf(stdout, "Can't initialize the DMAPI\n");
123 if (sid == DM_NO_SESSION)
124 find_test_session(&sid);
126 /* Get the directory handle. */
128 if (dm_path_to_handle(pathname, &hanp, &hlen)) {
130 "ERROR: can't get handle for directory %s\n", pathname);
134 printf("Hole test beginning...\n");
135 sprintf(filename, "%s/VeryLongUnlikelyFilename.HOLETEST", pathname);
136 sprintf(command, "cp %s %s \n", ls_path, filename);
139 if (dm_path_to_handle(filename, &hanp, &hlen)) {
140 fprintf(stdout, "can't get handle for %s\n; aborting test",
143 sprintf(command, "rm %s \n", filename);
145 fprintf(stdout, "\tHole test aborted.\n");
147 dm_handle_free(hanp, hlen);
151 /* ## Get the block size using a length-1 probe. ## */
152 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 1, 0,
156 fprintf(stdout, "Error: block size appears to be 0!\n");
158 sprintf(command, "rm %s \n", filename);
160 fprintf(stdout, "\tHole test aborted.\n");
162 dm_handle_free(hanp, hlen);
167 * The kernel always rounds the offset up to the next block
168 * size, so we can only probes up to the previous to last block.
170 end = (29604 / blocksize) * blocksize;
172 /* Check that dm_probe_hole returns an extent from the next
173 * highest multiple of the block size, to the end of the file
175 for (offset = 0; offset < end; offset++) {
176 if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
178 fprintf(stdout, "dm_probe_hole failed on pass %lld (%s)\n",
179 (long long)offset, ERR_NAME);
184 "Error: hole did not extend to end of file!\n");
186 if (blocksize*(roff/blocksize) != roff) {
188 "Error: offset not a multiple of block size!\n");
193 /* Be sure dm_punch_hole doesn't change the time stamp,
194 * and verify that dm_get_allocinfo shows a hole
195 * followed by an extent to the end of the file.
197 for(offset = 28672; offset > 0; offset-=blocksize) {
198 if (stat(filename, &buf)){
200 "Error: unable to stat the test file; %s (1st)\n",
204 if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
206 fprintf(stdout, "dm_probe_hole failed, %s\n",
210 if (roff != offset) {
212 "Error: presumed offset was not %lld.\n",
215 if (dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN,
217 fprintf(stdout, "dm_punch_hole failed, %s\n",
221 if (stat(filename, &checkbuf)){
223 "Error: unable to stat the test file. (2nd)\n");
227 /* COMPARE BUF AND CHECKBUF! */
229 if ((buf.st_atime == checkbuf.st_atime) &&
230 (buf.st_mtime == checkbuf.st_mtime) &&
231 (buf.st_ctime == checkbuf.st_ctime))
233 if ((buf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
234 (buf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
235 (buf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
236 (buf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
237 (buf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
238 (buf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
243 "\tTime stamp unchanged by hole from offset %lld.\n",
244 (long long)(offset));
249 "Error: punch_hole changed file's time stamp.\n");
252 if ((dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN,
253 &ex_off, 1, extent, &nelem) == 1) &&
254 (extent->ex_type == DM_EXTENT_RES) &&
255 (dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN,
256 &ex_off, 1, extent, &nelem) == 0) &&
257 (extent->ex_type == DM_EXTENT_HOLE)) {
258 if (extent->ex_offset == roff){
260 fprintf(stdout, "\tVerified hole at %lld\n",
261 (long long)(extent->ex_offset));
265 fprintf(stdout, "\tError: get_allocinfo found hole at %lld\n",
266 (long long)(extent->ex_offset));
270 fprintf(stdout, "\tError: get_allocinfo did not find an "
271 "extent followed by a hole!\n");
275 /*------------------------*\
276 |* ## Errno subtests ## *|
277 \*------------------------*/
278 fprintf(stdout, "\t(beginning errno subtests...)\n");
279 /*---------------------------------------------------------*/
281 "probe (from past EOF)",
282 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 30000, length,
284 /*---------------------------------------------------------*/
286 "probe (to past EOF)",
287 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 15000, 150000,
289 /*---------------------------------------------------------*/
290 SHAREDTEST("probe", hanp, hlen, test_token,
291 dm_probe_hole(sid, hanp, hlen, test_token,
293 /*---------------------------------------------------------*/
294 EXCLTEST("punch", hanp, hlen, test_token,
295 dm_punch_hole(sid, hanp, hlen, test_token, 0, 0))
296 /*---------------------------------------------------------*/
298 * No idea where that EAGAIN should come from, it's never
299 * returned from the kernel.
306 dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN,
309 /*---------------------------------------------------------*/
310 if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
312 "Cannot create a test handle (%s); skipping EBADF test\n",
316 ((char *) test_vp)[hlen/2]++;
319 dm_probe_hole(sid, test_vp, hlen, DM_NO_TOKEN,
324 dm_punch_hole(sid, test_vp, hlen, DM_NO_TOKEN,
327 dm_handle_free(test_vp, hlen);
328 /*---------------------------------------------------------*/
330 "probe (null handle)",
331 dm_probe_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length,
335 dm_probe_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length,
336 &roff, (dm_size_t*)(-1000)))
339 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
340 (dm_off_t*)(-1000), &rlen))
341 /*---------------------------------------------------------*/
344 dm_punch_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length))
345 /*---------------------------------------------------------*/
347 "probe (bad session)",
348 dm_probe_hole(-100, hanp, hlen, DM_NO_TOKEN, offset, length,
350 /*---------------------------------------------------------*/
353 dm_probe_hole(sid, hanp, hlen, 0, offset, length,
355 /*---------------------------------------------------------*/
357 "probe (bad token 2)",
358 dm_probe_hole(sid, hanp, hlen, 0, offset, length,
360 /*---------------------------------------------------------*/
361 fprintf(stdout, "\t(errno subtests complete)\n");
364 sprintf(command, "rm %s \n", filename);
366 printf("Hole test complete.\n");
368 dm_handle_free(hanp, hlen);