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