Fixed merge problems
[xfstests-dev.git] / src / alloc.c
1 /*
2  * Copyright (c) 2000-2003 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 "global.h"
34
35 /*
36  * Block I/O parameterization.  A basic block (BB) is the lowest size of
37  * filesystem allocation, and must equal 512.  Length units given to bio
38  * routines are in BB's.
39  */
40
41 /* Assume that if we have BTOBB, then we have the rest */
42 #ifndef BTOBB
43 #define BBSHIFT         9
44 #define BBSIZE          (1<<BBSHIFT)
45 #define BBMASK          (BBSIZE-1)
46 #define BTOBB(bytes)    (((__u64)(bytes) + BBSIZE - 1) >> BBSHIFT)
47 #define BTOBBT(bytes)   ((__u64)(bytes) >> BBSHIFT)
48 #define BBTOB(bbs)      ((bbs) << BBSHIFT)
49 #define OFFTOBBT(bytes) ((__u64)(bytes) >> BBSHIFT)
50
51 #define SEEKLIMIT32     0x7fffffff
52 #define BBSEEKLIMIT32   BTOBBT(SEEKLIMIT32)
53 #define SEEKLIMIT       0x7fffffffffffffffLL
54 #define BBSEEKLIMIT     OFFTOBBT(SEEKLIMIT)
55 #endif
56
57 #ifndef OFFTOBB
58 #define OFFTOBB(bytes)  (((__u64)(bytes) + BBSIZE - 1) >> BBSHIFT)
59 #define BBTOOFF(bbs)    ((__u64)(bbs) << BBSHIFT)
60 #endif
61
62 #define FSBTOBB(f)      (OFFTOBBT(FSBTOOFF(f)))
63 #define BBTOFSB(b)      (OFFTOFSB(BBTOOFF(b)))
64 #define OFFTOFSB(o)     ((o) / blocksize)
65 #define FSBTOOFF(f)     ((f) * blocksize)
66
67 void usage(void)
68 {
69     printf("usage: alloc [-b blocksize] [-d dir] [-f file] [-n] [-r] [-t]\n"
70            "flags:\n"
71            "    -n - non-interractive mode\n"
72            "    -r - real time file\n"
73            "    -t - truncate on open\n"
74            "\n"  
75            "commands:\n"  
76            "    r   [offset] [length] - reserve\n"
77            "    u   [offset] [length] - unreserve\n"
78            "    a   [offset] [length] - alloc      *** identical to free\n"
79            "    f   [offset] [length] - free       *** identical to alloc\n" 
80            "    m/p [offset] [length] - print map\n"
81            "    s                     - sync file\n"
82            "    t   [offset]          - truncate\n"
83            "    q                     - quit\n"
84            "    h/?                   - this help\n");
85            
86 }
87
88 int             fd = -1;
89 int             blocksize;
90 char            *filename;
91
92 /* params are in bytes */
93 void map(off64_t off, off64_t len)
94 {
95     struct getbmap      bm[2];
96     
97     bzero(bm, sizeof(bm));
98
99     bm[0].bmv_count = 2;
100     bm[0].bmv_offset = OFFTOBB(off);
101     if (len==(off64_t)-1) { /* unsigned... */
102         bm[0].bmv_length = -1;
103         printf("    MAP off=%lld, len=%lld [%lld-]\n", 
104                 (long long)off, (long long)len,
105                 (long long)BBTOFSB(bm[0].bmv_offset));
106     } else {
107         bm[0].bmv_length = OFFTOBB(len);
108         printf("    MAP off=%lld, len=%lld [%lld,%lld]\n", 
109                 (long long)off, (long long)len,
110                 (long long)BBTOFSB(bm[0].bmv_offset),
111                 (long long)BBTOFSB(bm[0].bmv_length));
112     }
113     
114     printf("        [ofs,count]: start..end\n");
115     for (;;) {
116 #ifdef XFS_IOC_GETBMAP
117             if (xfsctl(filename, fd, XFS_IOC_GETBMAP, bm) < 0) {
118 #else
119 #ifdef F_GETBMAP
120             if (fcntl(fd, F_GETBMAP, bm) < 0) {
121 #else
122 bozo!
123 #endif
124 #endif
125                     perror("getbmap");
126                     break;
127             }
128
129             if (bm[0].bmv_entries == 0)
130                     break;
131
132             printf("        [%lld,%lld]: ",
133                     (long long)BBTOFSB(bm[1].bmv_offset),
134                     (long long)BBTOFSB(bm[1].bmv_length));
135
136             if (bm[1].bmv_block == -1)
137                     printf("hole");
138             else
139                     printf("%lld..%lld",
140                             (long long)BBTOFSB(bm[1].bmv_block),
141                             (long long)BBTOFSB(bm[1].bmv_block +
142                                     bm[1].bmv_length - 1));
143             printf("\n");
144     }
145 }
146
147 int
148 main(int argc, char **argv)
149 {
150         int             c;
151         char            *dirname = NULL;
152         int             done = 0;
153         int             status = 0;
154         struct flock64  f;
155         off64_t         len;
156         char            line[1024];
157         off64_t         off;
158         int             oflags;
159         static char     *opnames[] = { "freesp",
160                                        "allocsp",
161                                        "unresvsp",
162                                        "resvsp" };
163         int             opno;
164
165         /* Assume that if we have FREESP64 then we have the rest */
166 #ifdef XFS_IOC_FREESP64
167 #define USE_XFSCTL
168         static int      optab[] = { XFS_IOC_FREESP64,
169                                     XFS_IOC_ALLOCSP64,
170                                     XFS_IOC_UNRESVSP64,
171                                     XFS_IOC_RESVSP64 };
172 #else
173 #ifdef F_FREESP64
174 #define USE_FCNTL
175         static int      optab[] = { F_FREESP64,
176                                     F_ALLOCSP64,
177                                     F_UNRESVSP64,
178                                     F_RESVSP64 };
179 #else
180 bozo!
181 #endif
182 #endif
183         int             rflag = 0;
184         struct statvfs64        svfs;
185         int             tflag = 0;
186         int             nflag = 0;
187         int             unlinkit = 0;
188         __int64_t       v;
189
190         while ((c = getopt(argc, argv, "b:d:f:rtn")) != -1) {
191                 switch (c) {
192                 case 'b':
193                         blocksize = atoi(optarg);
194                         break;
195                 case 'd':
196                         if (filename) {
197                                 printf("can't specify both -d and -f\n");
198                                 exit(1);
199                         }
200                         dirname = optarg;
201                         break;
202                 case 'f':
203                         if (dirname) {
204                                 printf("can't specify both -d and -f\n");
205                                 exit(1);
206                         }
207                         filename = optarg;
208                         break;
209                 case 'r':
210                         rflag = 1;
211                         break;
212                 case 't':
213                         tflag = 1;
214                         break;
215                 case 'n':
216                         nflag++;
217                         break;
218                 default:
219                         printf("unknown option\n");
220                         usage();
221                         exit(1);
222                 }
223         }
224         if (!dirname && !filename)
225                 dirname = ".";
226         if (!filename) {
227                 static char     tmpfile[] = "allocXXXXXX";
228
229                 mkstemp(tmpfile);
230                 filename = malloc(strlen(tmpfile) + strlen(dirname) + 2);
231                 sprintf(filename, "%s/%s", dirname, tmpfile);
232                 unlinkit = 1;
233         }
234         oflags = O_RDWR | O_CREAT | (tflag ? O_TRUNC : 0);
235         fd = open(filename, oflags, 0666);
236         if (!nflag) {
237             printf("alloc:\n");
238             printf("    filename %s\n", filename);
239         }
240         if (fd < 0) {
241                 perror(filename);
242                 exit(1);
243         }
244         if (!blocksize) {
245                 if (fstatvfs64(fd, &svfs) < 0) {
246                         perror(filename);
247                         status = 1;
248                         goto done;
249                 }
250                 blocksize = (int)svfs.f_bsize;
251         }
252         if (blocksize<0) {
253                 fprintf(stderr,"illegal blocksize %d\n", blocksize);
254                 status = 1;
255                 goto done;
256         }
257         printf("    blocksize %d\n", blocksize);
258         if (rflag) {
259                 struct fsxattr a;
260
261 #ifdef XFS_IOC_FSGETXATTR
262                 if (xfsctl(filename, fd, XFS_IOC_FSGETXATTR, &a) < 0) {
263                         perror("XFS_IOC_FSGETXATTR");
264                         status = 1;
265                         goto done;
266                 }
267 #else
268 #ifdef F_FSGETXATTR
269                 if (fcntl(fd, F_FSGETXATTR, &a) < 0) {
270                         perror("F_FSGETXATTR");
271                         status = 1;
272                         goto done;
273                 }
274 #else
275 bozo!
276 #endif
277 #endif
278
279                 a.fsx_xflags |= XFS_XFLAG_REALTIME;
280
281 #ifdef XFS_IOC_FSSETXATTR
282                 if (xfsctl(filename, fd, XFS_IOC_FSSETXATTR, &a) < 0) {
283                         perror("XFS_IOC_FSSETXATTR");
284                         status = 1;
285                         goto done;
286                 }
287 #else
288 #ifdef F_FSSETXATTR
289                 if (fcntl(fd, F_FSSETXATTR, &a) < 0) {
290                         perror("F_FSSETXATTR");
291                         status = 1;
292                         goto done;
293                 }
294 #else
295 bozo!
296 #endif
297 #endif
298         }
299         while (!done) {
300                 char *p;
301                 
302                 if (!nflag) printf("alloc> ");
303                 fflush(stdout);
304                 if (!fgets(line, 1024, stdin)) break;
305                 
306                 p=line+strlen(line);
307                 if (p!=line&&p[-1]=='\n') p[-1]=0;
308                 
309                 opno = 0;
310                 switch (line[0]) {
311                 case 'r':
312                         opno++;
313                 case 'u':
314                         opno++;
315                 case 'a':
316                         opno++;
317                 case 'f':
318                         v = strtoll(&line[2], &p, 0);
319                         if (*p == 'b') {
320                                 off = FSBTOOFF(v);
321                                 p++;
322                         } else
323                                 off = v;
324                         f.l_whence = SEEK_SET;
325                         f.l_start = off;
326                         if (*p == '\0')
327                                 v = -1;
328                         else
329                                 v = strtoll(p, &p, 0);
330                         if (*p == 'b') {
331                                 len = FSBTOOFF(v);
332                                 p++;
333                         } else
334                                 len = v;
335                         
336                         printf("    CMD %s, off=%lld, len=%lld\n", 
337                                 opnames[opno], (long long)off, (long long)len);
338                         
339                         f.l_len = len;
340 #ifdef USE_XFSCTL
341                         c = xfsctl(filename, fd, optab[opno], &f);
342 #else
343 #ifdef USE_FCNTL
344                         c = fcntl(fd, optab[opno], &f);
345 #else
346 bozo!
347 #endif
348 #endif
349                         if (c < 0) {
350                                 perror(opnames[opno]);
351                                 break;
352                         }
353                         
354                         map(off,len);                        
355                         break;
356                 case 'p':
357                 case 'm':
358                         p = &line[1];
359                         v = strtoll(p, &p, 0);
360                         if (*p == 'b') {
361                                 off = FSBTOOFF(v);
362                                 p++;
363                         } else
364                                 off = v;
365                         if (*p == '\0')
366                                 len = -1;
367                         else {
368                                 v = strtoll(p, &p, 0);
369                                 if (*p == 'b')
370                                         len = FSBTOOFF(v);
371                                 else
372                                         len = v;
373                         }
374                         map(off,len);
375                         break;
376                 case 't':
377                         p = &line[1];
378                         v = strtoll(p, &p, 0);
379                         if (*p == 'b')
380                                 off = FSBTOOFF(v);
381                         else
382                                 off = v;
383                         printf("    TRUNCATE off=%lld\n", (long long)off);
384                         if (ftruncate64(fd, off) < 0) {
385                                 perror("ftruncate");
386                                 break;
387                         }
388                         break;
389                 case 's':
390                         printf("    SYNC\n");
391                         fsync(fd);
392                         break;
393                 case 'q':
394                         printf("    QUIT\n");
395                         done = 1;
396                         break;
397                 case '?':
398                 case 'h':
399                         usage();
400                         break;
401                 default:
402                         printf("unknown command '%s'\n", line);
403                         break;
404                 }
405         }
406         if (!nflag) printf("\n");
407 done:
408         if (fd != -1)
409                 close(fd);
410         if (unlinkit)
411                 unlink(filename);
412         exit(status);
413         /* NOTREACHED */
414 }