mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
c432589da3
Mostly scripted like all the others, manually added tags to Makefile, nsexec.c and t_mmap_writev.c. Manually touched up open_by_handle.c and t_encrypted_d_revalidate.c post script. Notes for future reference: - src/log-writes/ code has no explicit copyright or license tags, nor does the upstream repository, hence license is unknown. Need Josef to clarify the license and send a patch adding SPDX tags to those files. - src/perf code has no explicit copyright or license tags, but it was code submitted explictly for fstests so it is assumed to be GPLv2.0 and tagged as such. If this is incorrect, Josef will need to clarify copyright and the license and send patches to correct it. Signed-off-by: Dave Chinner <dchinner@redhat.com>
389 lines
8.5 KiB
C
389 lines
8.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2000-2003 Silicon Graphics, Inc.
|
|
* All Rights Reserved.
|
|
*/
|
|
|
|
#include "global.h"
|
|
|
|
/*
|
|
* Block I/O parameterization. A basic block (BB) is the lowest size of
|
|
* filesystem allocation, and must equal 512. Length units given to bio
|
|
* routines are in BB's.
|
|
*/
|
|
|
|
/* Assume that if we have BTOBB, then we have the rest */
|
|
#ifndef BTOBB
|
|
#define BBSHIFT 9
|
|
#define BBSIZE (1<<BBSHIFT)
|
|
#define BBMASK (BBSIZE-1)
|
|
#define BTOBB(bytes) (((__u64)(bytes) + BBSIZE - 1) >> BBSHIFT)
|
|
#define BTOBBT(bytes) ((__u64)(bytes) >> BBSHIFT)
|
|
#define BBTOB(bbs) ((bbs) << BBSHIFT)
|
|
#define OFFTOBBT(bytes) ((__u64)(bytes) >> BBSHIFT)
|
|
|
|
#define SEEKLIMIT32 0x7fffffff
|
|
#define BBSEEKLIMIT32 BTOBBT(SEEKLIMIT32)
|
|
#define SEEKLIMIT 0x7fffffffffffffffLL
|
|
#define BBSEEKLIMIT OFFTOBBT(SEEKLIMIT)
|
|
#endif
|
|
|
|
#ifndef OFFTOBB
|
|
#define OFFTOBB(bytes) (((__u64)(bytes) + BBSIZE - 1) >> BBSHIFT)
|
|
#define BBTOOFF(bbs) ((__u64)(bbs) << BBSHIFT)
|
|
#endif
|
|
|
|
#define FSBTOBB(f) (OFFTOBBT(FSBTOOFF(f)))
|
|
#define BBTOFSB(b) (OFFTOFSB(BBTOOFF(b)))
|
|
#define OFFTOFSB(o) ((o) / blocksize)
|
|
#define FSBTOOFF(f) ((f) * blocksize)
|
|
|
|
void usage(void)
|
|
{
|
|
printf("usage: alloc [-b blocksize] [-d dir] [-f file] [-n] [-r] [-t]\n"
|
|
"flags:\n"
|
|
" -n - non-interractive mode\n"
|
|
" -r - real time file\n"
|
|
" -t - truncate on open\n"
|
|
"\n"
|
|
"commands:\n"
|
|
" r [offset] [length] - reserve\n"
|
|
" u [offset] [length] - unreserve\n"
|
|
" a [offset] [length] - alloc *** identical to free\n"
|
|
" f [offset] [length] - free *** identical to alloc\n"
|
|
" m/p [offset] [length] - print map\n"
|
|
" s - sync file\n"
|
|
" t [offset] - truncate\n"
|
|
" q - quit\n"
|
|
" h/? - this help\n");
|
|
|
|
}
|
|
|
|
int fd = -1;
|
|
int blocksize;
|
|
char *filename;
|
|
|
|
/* params are in bytes */
|
|
void map(off64_t off, off64_t len)
|
|
{
|
|
struct getbmap bm[2];
|
|
|
|
bzero(bm, sizeof(bm));
|
|
|
|
bm[0].bmv_count = 2;
|
|
bm[0].bmv_offset = OFFTOBB(off);
|
|
if (len==(off64_t)-1) { /* unsigned... */
|
|
bm[0].bmv_length = -1;
|
|
printf(" MAP off=%lld, len=%lld [%lld-]\n",
|
|
(long long)off, (long long)len,
|
|
(long long)BBTOFSB(bm[0].bmv_offset));
|
|
} else {
|
|
bm[0].bmv_length = OFFTOBB(len);
|
|
printf(" MAP off=%lld, len=%lld [%lld,%lld]\n",
|
|
(long long)off, (long long)len,
|
|
(long long)BBTOFSB(bm[0].bmv_offset),
|
|
(long long)BBTOFSB(bm[0].bmv_length));
|
|
}
|
|
|
|
printf(" [ofs,count]: start..end\n");
|
|
for (;;) {
|
|
#ifdef XFS_IOC_GETBMAP
|
|
if (xfsctl(filename, fd, XFS_IOC_GETBMAP, bm) < 0) {
|
|
#else
|
|
#ifdef F_GETBMAP
|
|
if (fcntl(fd, F_GETBMAP, bm) < 0) {
|
|
#else
|
|
bozo!
|
|
#endif
|
|
#endif
|
|
perror("getbmap");
|
|
break;
|
|
}
|
|
|
|
if (bm[0].bmv_entries == 0)
|
|
break;
|
|
|
|
printf(" [%lld,%lld]: ",
|
|
(long long)BBTOFSB(bm[1].bmv_offset),
|
|
(long long)BBTOFSB(bm[1].bmv_length));
|
|
|
|
if (bm[1].bmv_block == -1)
|
|
printf("hole");
|
|
else
|
|
printf("%lld..%lld",
|
|
(long long)BBTOFSB(bm[1].bmv_block),
|
|
(long long)BBTOFSB(bm[1].bmv_block +
|
|
bm[1].bmv_length - 1));
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int c;
|
|
char *dirname = NULL;
|
|
int done = 0;
|
|
int status = 0;
|
|
struct flock64 f;
|
|
off64_t len;
|
|
char line[1024];
|
|
off64_t off;
|
|
int oflags;
|
|
static char *opnames[] = { "freesp",
|
|
"allocsp",
|
|
"unresvsp",
|
|
"resvsp" };
|
|
int opno;
|
|
|
|
/* Assume that if we have FREESP64 then we have the rest */
|
|
#ifdef XFS_IOC_FREESP64
|
|
#define USE_XFSCTL
|
|
static int optab[] = { XFS_IOC_FREESP64,
|
|
XFS_IOC_ALLOCSP64,
|
|
XFS_IOC_UNRESVSP64,
|
|
XFS_IOC_RESVSP64 };
|
|
#else
|
|
#ifdef F_FREESP64
|
|
#define USE_FCNTL
|
|
static int optab[] = { F_FREESP64,
|
|
F_ALLOCSP64,
|
|
F_UNRESVSP64,
|
|
F_RESVSP64 };
|
|
#else
|
|
bozo!
|
|
#endif
|
|
#endif
|
|
int rflag = 0;
|
|
struct statvfs64 svfs;
|
|
int tflag = 0;
|
|
int nflag = 0;
|
|
int unlinkit = 0;
|
|
int64_t v;
|
|
|
|
while ((c = getopt(argc, argv, "b:d:f:rtn")) != -1) {
|
|
switch (c) {
|
|
case 'b':
|
|
blocksize = atoi(optarg);
|
|
break;
|
|
case 'd':
|
|
if (filename) {
|
|
printf("can't specify both -d and -f\n");
|
|
exit(1);
|
|
}
|
|
dirname = optarg;
|
|
break;
|
|
case 'f':
|
|
if (dirname) {
|
|
printf("can't specify both -d and -f\n");
|
|
exit(1);
|
|
}
|
|
filename = optarg;
|
|
break;
|
|
case 'r':
|
|
rflag = 1;
|
|
break;
|
|
case 't':
|
|
tflag = 1;
|
|
break;
|
|
case 'n':
|
|
nflag++;
|
|
break;
|
|
default:
|
|
printf("unknown option\n");
|
|
usage();
|
|
exit(1);
|
|
}
|
|
}
|
|
if (!dirname && !filename)
|
|
dirname = ".";
|
|
if (!filename) {
|
|
static char tmpfile[] = "allocXXXXXX";
|
|
|
|
mkstemp(tmpfile);
|
|
filename = malloc(strlen(tmpfile) + strlen(dirname) + 2);
|
|
sprintf(filename, "%s/%s", dirname, tmpfile);
|
|
unlinkit = 1;
|
|
}
|
|
oflags = O_RDWR | O_CREAT | (tflag ? O_TRUNC : 0);
|
|
fd = open(filename, oflags, 0666);
|
|
if (!nflag) {
|
|
printf("alloc:\n");
|
|
printf(" filename %s\n", filename);
|
|
}
|
|
if (fd < 0) {
|
|
perror(filename);
|
|
exit(1);
|
|
}
|
|
if (!blocksize) {
|
|
if (fstatvfs64(fd, &svfs) < 0) {
|
|
perror(filename);
|
|
status = 1;
|
|
goto done;
|
|
}
|
|
blocksize = (int)svfs.f_bsize;
|
|
}
|
|
if (blocksize<0) {
|
|
fprintf(stderr,"illegal blocksize %d\n", blocksize);
|
|
status = 1;
|
|
goto done;
|
|
}
|
|
printf(" blocksize %d\n", blocksize);
|
|
if (rflag) {
|
|
struct fsxattr a;
|
|
|
|
#ifdef XFS_IOC_FSGETXATTR
|
|
if (xfsctl(filename, fd, XFS_IOC_FSGETXATTR, &a) < 0) {
|
|
perror("XFS_IOC_FSGETXATTR");
|
|
status = 1;
|
|
goto done;
|
|
}
|
|
#else
|
|
#ifdef F_FSGETXATTR
|
|
if (fcntl(fd, F_FSGETXATTR, &a) < 0) {
|
|
perror("F_FSGETXATTR");
|
|
status = 1;
|
|
goto done;
|
|
}
|
|
#else
|
|
bozo!
|
|
#endif
|
|
#endif
|
|
|
|
a.fsx_xflags |= XFS_XFLAG_REALTIME;
|
|
|
|
#ifdef XFS_IOC_FSSETXATTR
|
|
if (xfsctl(filename, fd, XFS_IOC_FSSETXATTR, &a) < 0) {
|
|
perror("XFS_IOC_FSSETXATTR");
|
|
status = 1;
|
|
goto done;
|
|
}
|
|
#else
|
|
#ifdef F_FSSETXATTR
|
|
if (fcntl(fd, F_FSSETXATTR, &a) < 0) {
|
|
perror("F_FSSETXATTR");
|
|
status = 1;
|
|
goto done;
|
|
}
|
|
#else
|
|
bozo!
|
|
#endif
|
|
#endif
|
|
}
|
|
while (!done) {
|
|
char *p;
|
|
|
|
if (!nflag) printf("alloc> ");
|
|
fflush(stdout);
|
|
if (!fgets(line, 1024, stdin)) break;
|
|
|
|
p=line+strlen(line);
|
|
if (p!=line&&p[-1]=='\n') p[-1]=0;
|
|
|
|
opno = 0;
|
|
switch (line[0]) {
|
|
case 'r':
|
|
opno++;
|
|
case 'u':
|
|
opno++;
|
|
case 'a':
|
|
opno++;
|
|
case 'f':
|
|
v = strtoll(&line[2], &p, 0);
|
|
if (*p == 'b') {
|
|
off = FSBTOOFF(v);
|
|
p++;
|
|
} else
|
|
off = v;
|
|
f.l_whence = SEEK_SET;
|
|
f.l_start = off;
|
|
if (*p == '\0')
|
|
v = -1;
|
|
else
|
|
v = strtoll(p, &p, 0);
|
|
if (*p == 'b') {
|
|
len = FSBTOOFF(v);
|
|
p++;
|
|
} else
|
|
len = v;
|
|
|
|
printf(" CMD %s, off=%lld, len=%lld\n",
|
|
opnames[opno], (long long)off, (long long)len);
|
|
|
|
f.l_len = len;
|
|
#ifdef USE_XFSCTL
|
|
c = xfsctl(filename, fd, optab[opno], &f);
|
|
#else
|
|
#ifdef USE_FCNTL
|
|
c = fcntl(fd, optab[opno], &f);
|
|
#else
|
|
bozo!
|
|
#endif
|
|
#endif
|
|
if (c < 0) {
|
|
perror(opnames[opno]);
|
|
break;
|
|
}
|
|
|
|
map(off,len);
|
|
break;
|
|
case 'p':
|
|
case 'm':
|
|
p = &line[1];
|
|
v = strtoll(p, &p, 0);
|
|
if (*p == 'b') {
|
|
off = FSBTOOFF(v);
|
|
p++;
|
|
} else
|
|
off = v;
|
|
if (*p == '\0')
|
|
len = -1;
|
|
else {
|
|
v = strtoll(p, &p, 0);
|
|
if (*p == 'b')
|
|
len = FSBTOOFF(v);
|
|
else
|
|
len = v;
|
|
}
|
|
map(off,len);
|
|
break;
|
|
case 't':
|
|
p = &line[1];
|
|
v = strtoll(p, &p, 0);
|
|
if (*p == 'b')
|
|
off = FSBTOOFF(v);
|
|
else
|
|
off = v;
|
|
printf(" TRUNCATE off=%lld\n", (long long)off);
|
|
if (ftruncate64(fd, off) < 0) {
|
|
perror("ftruncate");
|
|
break;
|
|
}
|
|
break;
|
|
case 's':
|
|
printf(" SYNC\n");
|
|
fsync(fd);
|
|
break;
|
|
case 'q':
|
|
printf(" QUIT\n");
|
|
done = 1;
|
|
break;
|
|
case '?':
|
|
case 'h':
|
|
usage();
|
|
break;
|
|
default:
|
|
printf("unknown command '%s'\n", line);
|
|
break;
|
|
}
|
|
}
|
|
if (!nflag) printf("\n");
|
|
done:
|
|
if (fd != -1)
|
|
close(fd);
|
|
if (unlinkit)
|
|
unlink(filename);
|
|
exit(status);
|
|
/* NOTREACHED */
|
|
}
|