QA source updates and some associated test changes
[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 #define BBSHIFT         9
41 #define BBSIZE          (1<<BBSHIFT)
42 #define BBMASK          (BBSIZE-1)
43 #define BTOBB(bytes)    (((__u64)(bytes) + BBSIZE - 1) >> BBSHIFT)
44 #define BTOBBT(bytes)   ((__u64)(bytes) >> BBSHIFT)
45 #define BBTOB(bbs)      ((bbs) << BBSHIFT)
46 #define OFFTOBB(bytes)  (((__u64)(bytes) + BBSIZE - 1) >> BBSHIFT)
47 #define OFFTOBBT(bytes) ((__u64)(bytes) >> BBSHIFT)
48 #define BBTOOFF(bbs)    ((__u64)(bbs) << BBSHIFT)
49
50 #define SEEKLIMIT32     0x7fffffff
51 #define BBSEEKLIMIT32   BTOBBT(SEEKLIMIT32)
52 #define SEEKLIMIT       0x7fffffffffffffffLL
53 #define BBSEEKLIMIT     OFFTOBBT(SEEKLIMIT)
54
55 #define FSBTOBB(f)      (OFFTOBBT(FSBTOOFF(f)))
56 #define BBTOFSB(b)      (OFFTOFSB(BBTOOFF(b)))
57 #define OFFTOFSB(o)     ((o) / blocksize)
58 #define FSBTOOFF(f)     ((f) * blocksize)
59
60 void usage(void)
61 {
62     printf("usage: alloc [-b blocksize] [-d dir] [-f file] [-n] [-r] [-t]\n"
63            "flags:\n"
64            "    -n - non-interractive mode\n"
65            "    -r - real time file\n"
66            "    -t - truncate on open\n"
67            "\n"  
68            "commands:\n"  
69            "    r   [offset] [length] - reserve\n"
70            "    u   [offset] [length] - unreserve\n"
71            "    a   [offset] [length] - alloc      *** identical to free\n"
72            "    f   [offset] [length] - free       *** identical to alloc\n" 
73            "    m/p [offset] [length] - print map\n"
74            "    s                     - sync file\n"
75            "    t   [offset]          - truncate\n"
76            "    q                     - quit\n"
77            "    h/?                   - this help\n");
78            
79 }
80
81 int             fd = -1;
82 int             blocksize;
83 char            *filename;
84
85 /* params are in bytes */
86 void map(off64_t off, off64_t len)
87 {
88     struct getbmap      bm[2]={{0}};
89     
90     bm[0].bmv_count = 2;
91     bm[0].bmv_offset = OFFTOBB(off);
92     if (len==(off64_t)-1) { /* unsigned... */
93         bm[0].bmv_length = -1;
94         printf("    MAP off=%lld, len=%lld [%lld-]\n", 
95                 (__s64)off, (__s64)len,
96                 (__s64)BBTOFSB(bm[0].bmv_offset));
97     } else {
98         bm[0].bmv_length = OFFTOBB(len);
99         printf("    MAP off=%lld, len=%lld [%lld,%lld]\n", 
100                 (__s64)off, (__s64)len,
101                 (__s64)BBTOFSB(bm[0].bmv_offset),
102                 (__s64)BBTOFSB(bm[0].bmv_length));
103     }
104     
105     printf("        [ofs,count]: start..end\n");
106     for (;;) {
107             if (xfsctl(filename, fd, XFS_IOC_GETBMAP, bm) < 0) {
108                     perror("getbmap");
109                     break;
110             }
111             if (bm[0].bmv_entries == 0)
112                     break;
113             printf("        [%lld,%lld]: ",
114                     (__s64)BBTOFSB(bm[1].bmv_offset),
115                     (__s64)BBTOFSB(bm[1].bmv_length));
116             if (bm[1].bmv_block == -1)
117                     printf("hole");
118             else
119                     printf("%lld..%lld",
120                             (__s64)BBTOFSB(bm[1].bmv_block),
121                             (__s64)BBTOFSB(bm[1].bmv_block +
122                                     bm[1].bmv_length - 1));
123             printf("\n");
124     }
125 }
126
127 int
128 main(int argc, char **argv)
129 {
130         int             c;
131         char            *dirname = NULL;
132         int             done = 0;
133         int             status = 0;
134         struct flock64  f;
135         off64_t         len;
136         char            line[1024];
137         off64_t         off;
138         int             oflags;
139         static char     *opnames[] =
140                 { "freesp", "allocsp", "unresvsp", "resvsp" };
141         int             opno;
142         static int      optab[] =
143                 { XFS_IOC_FREESP64, XFS_IOC_ALLOCSP64, XFS_IOC_UNRESVSP64, XFS_IOC_RESVSP64 };
144         int             rflag = 0;
145         struct statvfs64        svfs;
146         int             tflag = 0;
147         int             nflag = 0;
148         int             unlinkit = 0;
149         __int64_t       v;
150
151         while ((c = getopt(argc, argv, "b:d:f:rtn")) != -1) {
152                 switch (c) {
153                 case 'b':
154                         blocksize = atoi(optarg);
155                         break;
156                 case 'd':
157                         if (filename) {
158                                 printf("can't specify both -d and -f\n");
159                                 exit(1);
160                         }
161                         dirname = optarg;
162                         break;
163                 case 'f':
164                         if (dirname) {
165                                 printf("can't specify both -d and -f\n");
166                                 exit(1);
167                         }
168                         filename = optarg;
169                         break;
170                 case 'r':
171                         rflag = 1;
172                         break;
173                 case 't':
174                         tflag = 1;
175                         break;
176                 case 'n':
177                         nflag++;
178                         break;
179                 default:
180                         printf("unknown option\n");
181                         usage();
182                         exit(1);
183                 }
184         }
185         if (!dirname && !filename)
186                 dirname = ".";
187         if (!filename) {
188                 static char     tmpfile[] = "allocXXXXXX";
189
190                 mkstemp(tmpfile);
191                 filename = malloc(strlen(tmpfile) + strlen(dirname) + 2);
192                 sprintf(filename, "%s/%s", dirname, tmpfile);
193                 unlinkit = 1;
194         }
195         oflags = O_RDWR | O_CREAT | (tflag ? O_TRUNC : 0);
196         fd = open(filename, oflags, 0666);
197         if (!nflag) {
198             printf("alloc:\n");
199             printf("    filename %s\n", filename);
200         }
201         if (fd < 0) {
202                 perror(filename);
203                 exit(1);
204         }
205         if (!blocksize) {
206                 if (fstatvfs64(fd, &svfs) < 0) {
207                         perror(filename);
208                         status = 1;
209                         goto done;
210                 }
211                 blocksize = (int)svfs.f_bsize;
212         }
213         if (blocksize<0) {
214                 fprintf(stderr,"illegal blocksize %d\n", blocksize);
215                 status = 1;
216                 goto done;
217         }
218         printf("    blocksize %d\n", blocksize);
219         if (rflag) {
220                 struct fsxattr a;
221
222                 if (xfsctl(filename, fd, XFS_IOC_FSGETXATTR, &a) < 0) {
223                         perror("XFS_IOC_FSGETXATTR");
224                         status = 1;
225                         goto done;
226                 }
227                 a.fsx_xflags |= XFS_XFLAG_REALTIME;
228                 if (xfsctl(filename, fd, XFS_IOC_FSSETXATTR, &a) < 0) {
229                         perror("XFS_IOC_FSSETXATTR");
230                         status = 1;
231                         goto done;
232                 }
233         }
234         while (!done) {
235                 char *p;
236                 
237                 if (!nflag) printf("alloc> ");
238                 fflush(stdout);
239                 if (!fgets(line, 1024, stdin)) break;
240                 
241                 p=line+strlen(line);
242                 if (p!=line&&p[-1]=='\n') p[-1]=0;
243                 
244                 opno = 0;
245                 switch (line[0]) {
246                 case 'r':
247                         opno++;
248                 case 'u':
249                         opno++;
250                 case 'a':
251                         opno++;
252                 case 'f':
253                         v = strtoll(&line[2], &p, 0);
254                         if (*p == 'b') {
255                                 off = FSBTOOFF(v);
256                                 p++;
257                         } else
258                                 off = v;
259                         f.l_whence = SEEK_SET;
260                         f.l_start = off;
261                         if (*p == '\0')
262                                 v = -1;
263                         else
264                                 v = strtoll(p, &p, 0);
265                         if (*p == 'b') {
266                                 len = FSBTOOFF(v);
267                                 p++;
268                         } else
269                                 len = v;
270                         
271                         printf("    CMD %s, off=%lld, len=%lld\n", 
272                                 opnames[opno], (__s64)off, (__s64)len);
273                         
274                         f.l_len = len;
275                         c = xfsctl(filename, fd, optab[opno], &f);
276                         if (c < 0) {
277                                 perror(opnames[opno]);
278                                 break;
279                         }
280                         
281                         map(off,len);                        
282                         break;
283                 case 'p':
284                 case 'm':
285                         p = &line[1];
286                         v = strtoll(p, &p, 0);
287                         if (*p == 'b') {
288                                 off = FSBTOOFF(v);
289                                 p++;
290                         } else
291                                 off = v;
292                         if (*p == '\0')
293                                 len = -1;
294                         else {
295                                 v = strtoll(p, &p, 0);
296                                 if (*p == 'b')
297                                         len = FSBTOOFF(v);
298                                 else
299                                         len = v;
300                         }
301                         map(off,len);
302                         break;
303                 case 't':
304                         p = &line[1];
305                         v = strtoll(p, &p, 0);
306                         if (*p == 'b')
307                                 off = FSBTOOFF(v);
308                         else
309                                 off = v;
310                         printf("    TRUNCATE off=%lld\n", (__s64)off);
311                         if (ftruncate64(fd, off) < 0) {
312                                 perror("ftruncate");
313                                 break;
314                         }
315                         break;
316                 case 's':
317                         printf("    SYNC\n");
318                         fsync(fd);
319                         break;
320                 case 'q':
321                         printf("    QUIT\n");
322                         done = 1;
323                         break;
324                 case '?':
325                 case 'h':
326                         usage();
327                         break;
328                 default:
329                         printf("unknown command '%s'\n", line);
330                         break;
331                 }
332         }
333         if (!nflag) printf("\n");
334 done:
335         if (fd != -1)
336                 close(fd);
337         if (unlinkit)
338                 unlink(filename);
339         exit(status);
340         /* NOTREACHED */
341 }