07fa68b9ae3d3996f70d9acc2b568ccbb1b0143c
[xfstests-dev.git] / src / alloc.c
1 /*
2  * Copyright (c) 2000-2001 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;
82 int             blocksize = 0;
83
84 /* params are in bytes */
85 void map(off64_t off, off64_t len)
86 {
87     struct getbmap      bm[2]={{0}};
88     
89     bm[0].bmv_count = 2;
90     bm[0].bmv_offset = OFFTOBB(off);
91     if (len==(off64_t)-1) { /* unsigned... */
92         bm[0].bmv_length = -1;
93         printf("    MAP off=%lld, len=%lld [%lld-]\n", 
94                 (__s64)off, (__s64)len,
95                 (__s64)BBTOFSB(bm[0].bmv_offset));
96     } else {
97         bm[0].bmv_length = OFFTOBB(len);
98         printf("    MAP off=%lld, len=%lld [%lld,%lld]\n", 
99                 (__s64)off, (__s64)len,
100                 (__s64)BBTOFSB(bm[0].bmv_offset),
101                 (__s64)BBTOFSB(bm[0].bmv_length));
102     }
103     
104     printf("        [ofs,count]: start..end\n");
105     for (;;) {
106             if (ioctl(fd, XFS_IOC_GETBMAP, bm) < 0) {
107                     perror("getbmap");
108                     break;
109             }
110             if (bm[0].bmv_entries == 0)
111                     break;
112             printf("        [%lld,%lld]: ",
113                     (__s64)BBTOFSB(bm[1].bmv_offset),
114                     (__s64)BBTOFSB(bm[1].bmv_length));
115             if (bm[1].bmv_block == -1)
116                     printf("hole");
117             else
118                     printf("%lld..%lld",
119                             (__s64)BBTOFSB(bm[1].bmv_block),
120                             (__s64)BBTOFSB(bm[1].bmv_block +
121                                     bm[1].bmv_length - 1));
122             printf("\n");
123     }
124 }
125
126 int
127 main(int argc, char **argv)
128 {
129         int             c;
130         char            *dirname = NULL;
131         int             done = 0;
132         struct flock64  f;
133         char            *filename = NULL;
134         off64_t         len;
135         char            line[1024];
136         off64_t         off;
137         int             oflags;
138         static char     *opnames[] =
139                 { "freesp", "allocsp", "unresvsp", "resvsp" };
140         int             opno;
141         static int      optab[] =
142                 { XFS_IOC_FREESP64, XFS_IOC_ALLOCSP64, XFS_IOC_UNRESVSP64, XFS_IOC_RESVSP64 };
143         int             rflag = 0;
144         struct statvfs64        svfs;
145         int             tflag = 0;
146         int             nflag = 0;
147         int             unlinkit = 0;
148         __int64_t       v;
149
150         while ((c = getopt(argc, argv, "b:d:f:rtn")) != -1) {
151                 switch (c) {
152                 case 'b':
153                         blocksize = atoi(optarg);
154                         break;
155                 case 'd':
156                         if (filename) {
157                                 printf("can't specify both -d and -f\n");
158                                 exit(1);
159                         }
160                         dirname = optarg;
161                         break;
162                 case 'f':
163                         if (dirname) {
164                                 printf("can't specify both -d and -f\n");
165                                 exit(1);
166                         }
167                         filename = optarg;
168                         break;
169                 case 'r':
170                         rflag = 1;
171                         break;
172                 case 't':
173                         tflag = 1;
174                         break;
175                 case 'n':
176                         nflag++;
177                         break;
178                 default:
179                         printf("unknown option\n");
180                         usage();
181                         exit(1);
182                 }
183         }
184         if (!dirname && !filename)
185                 dirname = ".";
186         if (!filename) {
187                 static char     tmpfile[] = "allocXXXXXX";
188
189                 mkstemp(tmpfile);
190                 filename = malloc(strlen(tmpfile) + strlen(dirname) + 2);
191                 sprintf(filename, "%s/%s", dirname, tmpfile);
192                 unlinkit = 1;
193         }
194         oflags = O_RDWR | O_CREAT | (tflag ? O_TRUNC : 0);
195         fd = open(filename, oflags, 0666);
196         if (!nflag) {
197             printf("alloc:\n");
198             printf("    filename %s\n", filename);
199         }
200         if (fd < 0) {
201                 perror(filename);
202                 exit(1);
203         }
204         if (unlinkit)
205                 unlink(filename);
206         if (!blocksize) {
207                 if (fstatvfs64(fd, &svfs) < 0) {
208                         perror(filename);
209                         exit(1);
210                 }
211                 blocksize = (int)svfs.f_bsize;
212         }
213         if (blocksize<0) {
214                 fprintf(stderr,"illegal blocksize %d\n", blocksize);
215                 exit(1);
216         }
217         printf("    blocksize %d\n", blocksize);
218         if (rflag) {
219                 struct fsxattr a;
220
221                 if (ioctl(fd, XFS_IOC_FSGETXATTR, &a) < 0) {
222                         perror("XFS_IOC_FSGETXATTR");
223                         exit(1);
224                 }
225                 a.fsx_xflags |= XFS_XFLAG_REALTIME;
226                 if (ioctl(fd, XFS_IOC_FSSETXATTR, &a) < 0) {
227                         perror("XFS_IOC_FSSETXATTR");
228                         exit(1);
229                 }
230         }
231         while (!done) {
232                 char *p;
233                 
234                 if (!nflag) printf("alloc> ");
235                 fflush(stdout);
236                 if (!fgets(line, 1024, stdin)) break;
237                 
238                 p=line+strlen(line);
239                 if (p!=line&&p[-1]=='\n') p[-1]=0;
240                 
241                 opno = 0;
242                 switch (line[0]) {
243                 case 'r':
244                         opno++;
245                 case 'u':
246                         opno++;
247                 case 'a':
248                         opno++;
249                 case 'f':
250                         v = strtoll(&line[2], &p, 0);
251                         if (*p == 'b') {
252                                 off = FSBTOOFF(v);
253                                 p++;
254                         } else
255                                 off = v;
256                         f.l_whence = SEEK_SET;
257                         f.l_start = off;
258                         if (*p == '\0')
259                                 v = -1;
260                         else
261                                 v = strtoll(p, &p, 0);
262                         if (*p == 'b') {
263                                 len = FSBTOOFF(v);
264                                 p++;
265                         } else
266                                 len = v;
267                         
268                         printf("    CMD %s, off=%lld, len=%lld\n", 
269                                 opnames[opno], (__s64)off, (__s64)len);
270                         
271                         f.l_len = len;
272                         c = ioctl(fd, optab[opno], &f);
273                         if (c < 0) {
274                                 perror(opnames[opno]);
275                                 break;
276                         }
277                         
278                         map(off,len);                        
279                         break;
280                 case 'p':
281                 case 'm':
282                         p = &line[1];
283                         v = strtoll(p, &p, 0);
284                         if (*p == 'b') {
285                                 off = FSBTOOFF(v);
286                                 p++;
287                         } else
288                                 off = v;
289                         if (*p == '\0')
290                                 len = -1;
291                         else {
292                                 v = strtoll(p, &p, 0);
293                                 if (*p == 'b')
294                                         len = FSBTOOFF(v);
295                                 else
296                                         len = v;
297                         }
298                         map(off,len);
299                         break;
300                 case 't':
301                         p = &line[1];
302                         v = strtoll(p, &p, 0);
303                         if (*p == 'b')
304                                 off = FSBTOOFF(v);
305                         else
306                                 off = v;
307                         printf("    TRUNCATE off=%lld\n", (__s64)off);
308                         if (ftruncate64(fd, off) < 0) {
309                                 perror("ftruncate");
310                                 break;
311                         }
312                         break;
313                 case 's':
314                         printf("    SYNC\n");
315                         fsync(fd);
316                         break;
317                 case 'q':
318                         printf("    QUIT\n");
319                         done = 1;
320                         break;
321                 case '?':
322                 case 'h':
323                         usage();
324                         break;
325                 default:
326                         printf("unknown command '%s'\n", line);
327                         break;
328                 }
329         }
330         if (!nflag) printf("\n");
331         close(fd);
332         exit(0);
333         /* NOTREACHED */
334 }