cmd/xfsprogs/libdm/dmapi_tests/README 1.1 Renamed to cmd/xfstests/dmapi/README
[xfstests-dev.git] / dmapi / src / suite2 / src / test_hole.c
1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3  * 
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  * 
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  * 
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  * 
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  * 
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  * 
26  * http://www.sgi.com 
27  * 
28  * For further information regarding this notice, see: 
29  * 
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32
33 #include <sys/types.h>
34 #include <sys/stat.h>
35
36 #include <lib/hsm.h>
37 #include <lib/errtest.h>
38
39 #ifdef linux
40 #include <string.h>
41 #endif
42
43 /*---------------------------------------------------------------------------
44
45 Test program used to test the DMAPI function dm_punch_hole().  The
46 command line is:
47
48         test_hole [-v] [-s sid] pathname
49
50 where 
51    ls_path
52       is the path to a specific copy of ls, important only for its size
53    pathname 
54       is the path to the test filesystem
55    sid
56       is the session ID whose events you you are interested in.
57
58 ----------------------------------------------------------------------------*/
59
60 #ifndef linux
61 extern  char    *sys_errlist[];
62 #endif
63 extern  int     optind;
64 extern  char    *optarg;
65
66 char    *Progname;
67
68
69 static void
70 usage(void)
71 {
72         int     i;
73
74         fprintf(stderr, "usage:\t%s [-v] [-s sid] ls_path directoryname\n",
75                 Progname);
76         exit(1);
77 }
78
79
80 int
81 main(
82         int     argc, 
83         char    **argv)
84 {
85         dm_sessid_t     sid = DM_NO_SESSION;
86         char            *pathname = NULL;
87         char            *ls_path = NULL;
88         dm_off_t        offset = 0;
89         dm_off_t        ex_off = 0;
90         dm_extent_t     extent[20];
91         u_int           nelem;
92         dm_size_t       length = 0;
93         void            *hanp;
94         size_t          hlen;
95         dm_token_t      test_token;
96         char            *name;
97         int             opt;
98         int             i;
99         int             Vflag = 0;
100         char            filename[128];
101         char            command[128];
102         dm_off_t        roff;
103         dm_size_t       rlen;
104         dm_off_t        blocksize = 5; 
105         void            *test_vp;
106         struct stat    buf;
107         struct stat    checkbuf;
108
109
110         if (Progname = strrchr(argv[0], '/')) {
111                 Progname++;
112         } else {
113                 Progname = argv[0];
114         }
115
116         /* Crack and validate the command line options. */
117
118         while ((opt = getopt(argc, argv, "vs:")) != EOF) {
119                 switch (opt) {
120                 case 'v':
121                         Vflag++;
122                         break;
123                 case 's':
124                         sid = atol(optarg);
125                         break;
126                 case '?':
127                         usage();
128                 }
129         }
130         if (optind + 2 != argc)
131                 usage();
132         ls_path = argv[optind];
133         pathname = argv[optind+1];
134
135         if (dm_init_service(&name) == -1)  {
136                 fprintf(stdout, "Can't inititalize the DMAPI\n");
137                 exit(1);
138         }
139         if (sid == DM_NO_SESSION)
140                 find_test_session(&sid);
141
142         /* Get the directory handle. */
143
144         if (dm_path_to_handle(pathname, &hanp, &hlen)) {
145                 fprintf(stdout, 
146                      "ERROR: can't get handle for directory %s\n", pathname);
147                 exit(1);
148         }
149         
150         printf("Hole test beginning...\n");
151         sprintf(filename, "%s/VeryLongUnlikelyFilename.HOLETEST", pathname);
152         sprintf(command, "cp %s %s \n", ls_path, filename); 
153         system(command);
154
155         if (dm_path_to_handle(filename, &hanp, &hlen)) {
156           fprintf(stdout, "can't get handle for %s\n; aborting test",
157                   filename);
158           
159           sprintf(command, "rm %s \n", filename); 
160           system(command);
161           fprintf(stdout, "\tHole test aborted.\n");
162           
163           dm_handle_free(hanp, hlen);
164           exit(1);
165         }
166    
167         /*   ## Get the block size using a length-1 probe. ##   */
168         dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 1, 0,
169                       &blocksize, &rlen);
170         
171         if (blocksize==0) {
172           fprintf(stdout, "Error: block size appears to be 0!\n");
173           
174           sprintf(command, "rm %s \n", filename); 
175           system(command);
176           fprintf(stdout, "\tHole test aborted.\n");
177           
178           dm_handle_free(hanp, hlen);
179           exit(1);
180         }
181
182         /* Check that dm_probe_hole returns an extent from the next
183          * highest multiple of the block size, to the end of the file
184          */
185         i = 0;
186         for (offset = 0; offset < 29604; offset++) { 
187           if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
188                             &roff, &rlen)) {
189             fprintf(stdout, "dm_probe_hole failed on pass %lld (%s)\n",
190                     (long long)offset, ERR_NAME);
191           }
192           else {
193             if (rlen != 0) {
194                 fprintf(stdout, 
195                         "Error: hole did not extend to end of file!\n");
196             }
197             if (blocksize*(roff/blocksize) != roff) {
198                 fprintf(stdout,
199                         "Error: offset not a multiple of block size!\n");
200             }
201           }
202         }
203         
204         /* Be sure dm_punch_hole doesn't change the time stamp, 
205          * and verify that dm_get_allocinfo shows a hole
206          * followed by an extent to the end of the file.
207          */
208         for(offset = 28672; offset > 0; offset-=blocksize) {
209           if (stat(filename, &buf)){
210             fprintf(stdout, 
211                     "Error: unable to stat the test file; %s (1st)\n", 
212                     filename);
213             continue;
214           }
215           if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
216                             &roff, &rlen)) {
217             fprintf(stdout, "dm_probe_hole failed, %s\n",
218                     ERR_NAME);
219             continue;
220           }
221           if (roff != offset) {
222             fprintf(stdout, 
223                     "Error: presumed offset was not %lld.\n",
224                     (long long)(roff));
225           }
226           if (dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN,
227                             roff, length)) {
228             fprintf(stdout, "dm_punch_hole failed, %s\n",
229                     ERR_NAME);
230             continue;
231           }
232           if (stat(filename, &checkbuf)){
233             fprintf(stdout, 
234                     "Error: unable to stat the test file. (2nd)\n");
235             continue;
236           }
237           else {
238             /* COMPARE BUF AND CHECKBUF! */
239 #ifdef linux
240             if ((buf.st_atime == checkbuf.st_atime) &&
241                 (buf.st_mtime == checkbuf.st_mtime) &&
242                 (buf.st_ctime == checkbuf.st_ctime))
243 #else
244             if ((buf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
245                 (buf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
246                 (buf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
247                 (buf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
248                 (buf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
249                 (buf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
250 #endif
251            {
252               if (Vflag) {
253                 fprintf(stdout, 
254                         "\tTime stamp unchanged by hole from offset %lld.\n",
255                         (long long)(offset));
256               }
257             }
258             else {
259               fprintf(stdout,
260                       "Error: punch_hole changed file's time stamp.\n");
261             }
262             ex_off=0;
263             if ((dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN, 
264                                   &ex_off, 1, extent, &nelem) == 1) &&
265                 (extent->ex_type == DM_EXTENT_RES) &&
266                 (dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN,
267                                   &ex_off, 1, extent, &nelem) == 0) &&
268                 (extent->ex_type == DM_EXTENT_HOLE)) {
269               if (extent->ex_offset == roff){
270                 if (Vflag) {
271                   fprintf(stdout, "\tVerified hole at %lld\n", 
272                           (long long)(extent->ex_offset));
273                 }
274               }
275               else {
276                 fprintf(stdout, "\tError: get_allocinfo found hole at %lld\n",
277                         (long long)(extent->ex_offset));
278               }
279             }
280             else {
281                 fprintf(stdout, "\tError: get_allocinfo did not find an "
282                         "extent followed by a hole!\n");
283             }
284           }
285         }
286         /*------------------------*\
287         |*  ## Errno subtests ##  *|
288         \*------------------------*/
289         fprintf(stdout, "\t(beginning errno subtests...)\n");
290         /*---------------------------------------------------------*/
291         ERRTEST(E2BIG,
292                 "probe (from past EOF)",
293                 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 30000, length,
294                               &roff, &rlen))
295         /*---------------------------------------------------------*/
296         /* PROBLEM: No error is produced.  
297         /* off+len >= filesize should produce E2BIG...
298         ERRTEST(E2BIG,
299                 "probe (to past EOF)",
300                 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 15000, 150000,
301                               &roff, &rlen))
302         /*---------------------------------------------------------*/
303         SHAREDTEST("probe", hanp, hlen, test_token, 
304                  dm_probe_hole(sid, hanp, hlen, test_token, 
305                                0, 0, &roff, &rlen)) 
306         /*---------------------------------------------------------*/
307         EXCLTEST("punch", hanp, hlen, test_token, 
308                    dm_punch_hole(sid, hanp, hlen, test_token, 0, 0)) 
309         /*---------------------------------------------------------*/
310         ERRTEST(EAGAIN,
311                 "punch",
312                 dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN,
313                               1, length))       
314         /*---------------------------------------------------------*/
315         if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
316           fprintf(stderr, 
317                   "Cannot create a test handle (%s); skipping EBADF test\n",
318                   ERR_NAME);
319         }
320         else {
321          ((char *) test_vp)[hlen/2]++;
322           ERRTEST(EBADF,
323                   "probe",
324                   dm_probe_hole(sid, test_vp, hlen, DM_NO_TOKEN,
325                                 offset, length,
326                                 &roff, &rlen))
327           ERRTEST(EBADF,
328                   "punch",
329                   dm_punch_hole(sid, test_vp, hlen, DM_NO_TOKEN,
330                                 offset, length))
331         }
332         dm_handle_free(test_vp, hlen);
333         /*---------------------------------------------------------*/
334         ERRTEST(EFAULT,
335                 "probe (null handle)",
336                 dm_probe_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length,
337                                 &roff, &rlen))
338         ERRTEST(EFAULT,
339                 "probe (bad rlen)",
340                 dm_probe_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length,
341                                 &roff, (dm_size_t*)(-1000)))
342         ERRTEST(EFAULT,
343                 "probe (bad roff)",
344                 dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
345                                 (dm_off_t*)(-1000), &rlen))
346         /*---------------------------------------------------------*/
347         ERRTEST(EFAULT,
348                 "punch",
349                 dm_punch_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length))
350         /*---------------------------------------------------------*/
351         ERRTEST(EINVAL,
352                 "probe (bad session)",
353                 dm_probe_hole(-100, hanp, hlen, DM_NO_TOKEN, offset, length,
354                                 &roff, &rlen))
355         /*---------------------------------------------------------*/
356         ERRTEST(EINVAL, 
357                 "probe (bad token)",
358                 dm_probe_hole(sid, hanp, hlen, 0, offset, length,
359                                 &roff, &rlen))
360         /*---------------------------------------------------------*/
361         ERRTEST(EINVAL, 
362                 "probe (bad token 2)",
363                 dm_probe_hole(sid, hanp, hlen, 0, offset, length,
364                                 &roff, &rlen))
365         /*---------------------------------------------------------*/
366         fprintf(stdout, "\t(errno subtests complete)\n");
367                 
368
369         sprintf(command, "rm %s \n", filename); 
370         system(command);
371         printf("Hole test complete.\n");
372
373         dm_handle_free(hanp, hlen);
374         exit(0);
375 }
376