1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2001 Silicon Graphics, Inc.
11 #include <lib/errtest.h>
17 /*---------------------------------------------------------------------------
19 Test program used to test the DMAPI function dm_punch_hole(). The
22 test_hole [-v] [-s sid] pathname
26 is the path to a specific copy of ls, important only for its size
28 is the path to the test filesystem
30 is the session ID whose events you you are interested in.
32 ----------------------------------------------------------------------------*/
35 extern char *sys_errlist[];
46 fprintf(stderr, "usage:\t%s [-v] [-s sid] ls_path directoryname\n",
57 dm_sessid_t sid = DM_NO_SESSION;
58 char *pathname = NULL;
60 dm_off_t offset = 0, end;
62 dm_extent_t extent[20];
67 dm_token_t test_token;
75 dm_off_t blocksize = 5;
81 Progname = strrchr(argv[0], '/');
88 /* Crack and validate the command line options. */
90 while ((opt = getopt(argc, argv, "vs:")) != EOF) {
102 if (optind + 2 != argc)
104 ls_path = argv[optind];
105 pathname = argv[optind+1];
107 if (dm_init_service(&name) == -1) {
108 fprintf(stdout, "Can't initialize the DMAPI\n");
111 if (sid == DM_NO_SESSION)
112 find_test_session(&sid);
114 /* Get the directory handle. */
116 if (dm_path_to_handle(pathname, &hanp, &hlen)) {
118 "ERROR: can't get handle for directory %s\n", pathname);
122 printf("Hole test beginning...\n");
123 sprintf(filename, "%s/VeryLongUnlikelyFilename.HOLETEST", pathname);
124 sprintf(command, "cp %s %s \n", ls_path, filename);
127 if (dm_path_to_handle(filename, &hanp, &hlen)) {
128 fprintf(stdout, "can't get handle for %s\n; aborting test",
131 sprintf(command, "rm %s \n", filename);
133 fprintf(stdout, "\tHole test aborted.\n");
135 dm_handle_free(hanp, hlen);
139 /* ## Get the block size using a length-1 probe. ## */
140 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 1, 0,
144 fprintf(stdout, "Error: block size appears to be 0!\n");
146 sprintf(command, "rm %s \n", filename);
148 fprintf(stdout, "\tHole test aborted.\n");
150 dm_handle_free(hanp, hlen);
155 * The kernel always rounds the offset up to the next block
156 * size, so we can only probes up to the previous to last block.
158 end = (29604 / blocksize) * blocksize;
160 /* Check that dm_probe_hole returns an extent from the next
161 * highest multiple of the block size, to the end of the file
163 for (offset = 0; offset < end; offset++) {
164 if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
166 fprintf(stdout, "dm_probe_hole failed on pass %lld (%s)\n",
167 (long long)offset, ERR_NAME);
172 "Error: hole did not extend to end of file!\n");
174 if (blocksize*(roff/blocksize) != roff) {
176 "Error: offset not a multiple of block size!\n");
181 /* Be sure dm_punch_hole doesn't change the time stamp,
182 * and verify that dm_get_allocinfo shows a hole
183 * followed by an extent to the end of the file.
185 for(offset = 28672; offset > 0; offset-=blocksize) {
186 if (stat(filename, &buf)){
188 "Error: unable to stat the test file; %s (1st)\n",
192 if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
194 fprintf(stdout, "dm_probe_hole failed, %s\n",
198 if (roff != offset) {
200 "Error: presumed offset was not %lld.\n",
203 if (dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN,
205 fprintf(stdout, "dm_punch_hole failed, %s\n",
209 if (stat(filename, &checkbuf)){
211 "Error: unable to stat the test file. (2nd)\n");
215 /* COMPARE BUF AND CHECKBUF! */
217 if ((buf.st_atime == checkbuf.st_atime) &&
218 (buf.st_mtime == checkbuf.st_mtime) &&
219 (buf.st_ctime == checkbuf.st_ctime))
221 if ((buf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
222 (buf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
223 (buf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
224 (buf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
225 (buf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
226 (buf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
231 "\tTime stamp unchanged by hole from offset %lld.\n",
232 (long long)(offset));
237 "Error: punch_hole changed file's time stamp.\n");
240 if ((dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN,
241 &ex_off, 1, extent, &nelem) == 1) &&
242 (extent->ex_type == DM_EXTENT_RES) &&
243 (dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN,
244 &ex_off, 1, extent, &nelem) == 0) &&
245 (extent->ex_type == DM_EXTENT_HOLE)) {
246 if (extent->ex_offset == roff){
248 fprintf(stdout, "\tVerified hole at %lld\n",
249 (long long)(extent->ex_offset));
253 fprintf(stdout, "\tError: get_allocinfo found hole at %lld\n",
254 (long long)(extent->ex_offset));
258 fprintf(stdout, "\tError: get_allocinfo did not find an "
259 "extent followed by a hole!\n");
263 /*------------------------*\
264 |* ## Errno subtests ## *|
265 \*------------------------*/
266 fprintf(stdout, "\t(beginning errno subtests...)\n");
267 /*---------------------------------------------------------*/
269 "probe (from past EOF)",
270 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 30000, length,
272 /*---------------------------------------------------------*/
274 "probe (to past EOF)",
275 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 15000, 150000,
277 /*---------------------------------------------------------*/
278 SHAREDTEST("probe", hanp, hlen, test_token,
279 dm_probe_hole(sid, hanp, hlen, test_token,
281 /*---------------------------------------------------------*/
282 EXCLTEST("punch", hanp, hlen, test_token,
283 dm_punch_hole(sid, hanp, hlen, test_token, 0, 0))
284 /*---------------------------------------------------------*/
286 * No idea where that EAGAIN should come from, it's never
287 * returned from the kernel.
294 dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN,
297 /*---------------------------------------------------------*/
298 if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
300 "Cannot create a test handle (%s); skipping EBADF test\n",
304 ((char *) test_vp)[hlen/2]++;
307 dm_probe_hole(sid, test_vp, hlen, DM_NO_TOKEN,
312 dm_punch_hole(sid, test_vp, hlen, DM_NO_TOKEN,
315 dm_handle_free(test_vp, hlen);
316 /*---------------------------------------------------------*/
318 "probe (null handle)",
319 dm_probe_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length,
323 dm_probe_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length,
324 &roff, (dm_size_t*)(-1000)))
327 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
328 (dm_off_t*)(-1000), &rlen))
329 /*---------------------------------------------------------*/
332 dm_punch_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length))
333 /*---------------------------------------------------------*/
335 "probe (bad session)",
336 dm_probe_hole(-100, hanp, hlen, DM_NO_TOKEN, offset, length,
338 /*---------------------------------------------------------*/
341 dm_probe_hole(sid, hanp, hlen, 0, offset, length,
343 /*---------------------------------------------------------*/
345 "probe (bad token 2)",
346 dm_probe_hole(sid, hanp, hlen, 0, offset, length,
348 /*---------------------------------------------------------*/
349 fprintf(stdout, "\t(errno subtests complete)\n");
352 sprintf(command, "rm %s \n", filename);
354 printf("Hole test complete.\n");
356 dm_handle_free(hanp, hlen);