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