mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
Simple little program for populating a filesystem that could look like one DMF might be using.
Merge of master-melb:xfs-cmds:26472a by kenmcd.
This commit is contained in:
+4
-1
@@ -10,7 +10,7 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
|
||||
mmapcat append_reader append_writer dirperf metaperf \
|
||||
devzero feature alloc fault fstest t_access_root \
|
||||
godown resvtest writemod makeextents itrash \
|
||||
multi_open_unlink
|
||||
multi_open_unlink dmiperf
|
||||
|
||||
LINUX_TARGETS = loggen xfsctl bstat t_mtab getdevicesize
|
||||
|
||||
@@ -79,6 +79,9 @@ multi_open_unlink: multi_open_unlink.o
|
||||
acl_get: acl_get.o $(LIBACL) $(LIBATTR)
|
||||
$(LINKTEST) $(LIBACL) $(LIBATTR) $(LDLIBS)
|
||||
|
||||
dmiperf: dmiperf.o $(LIBATTR)
|
||||
$(LINKTEST) $(LIBATTR) $(LDLIBS)
|
||||
|
||||
|
||||
ifeq ($(PKG_PLATFORM),irix)
|
||||
fill2: fill2.o
|
||||
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Silicon Graphics, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <dirent.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <attr/attributes.h>
|
||||
|
||||
#define MAXNAMELEN 256
|
||||
#ifndef __sgi__
|
||||
typedef unsigned int uint_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Loop over directory sizes:
|
||||
* make m directories
|
||||
* touch n files in each directory
|
||||
* write y bytes to all files in each directory
|
||||
* set DMF attribute on x files in each directory
|
||||
* Change directory sizes by multiplication or addition.
|
||||
* Allow control of starting & stopping sizes, name length, target directory.
|
||||
* Print size and wallclock time (ms per file).
|
||||
* Output can be used to make graphs (gnuplot)
|
||||
*/
|
||||
|
||||
static uint_t addval;
|
||||
static uint_t dirchars;
|
||||
static char *directory;
|
||||
static uint_t firstsize;
|
||||
static uint_t lastsize;
|
||||
static uint_t minchars;
|
||||
static double mulval;
|
||||
static uint_t nchars;
|
||||
static uint_t ndirs;
|
||||
static uint_t pfxchars;
|
||||
static off64_t fsize;
|
||||
static char *buffer;
|
||||
static size_t bsize;
|
||||
|
||||
static int mkfile(char *, char *);
|
||||
static void filename(int, int, char *);
|
||||
static int hexchars(uint_t);
|
||||
static uint_t nextsize(uint_t);
|
||||
static double now(void);
|
||||
static void usage(void);
|
||||
|
||||
/*
|
||||
* Maximum size allowed, this is pretty nuts.
|
||||
* The largest one we've ever built has been about 2 million.
|
||||
*/
|
||||
#define MAX_DIR_SIZE (16 * 1024 * 1024)
|
||||
#define DFL_FIRST_SIZE 1
|
||||
#define DFL_LAST_SIZE (1024 * 1024)
|
||||
#define MAX_DIR_COUNT 1024
|
||||
#define MIN_DIR_COUNT 1
|
||||
|
||||
#define DMFATTRLEN 22
|
||||
#define DMFATTRNAME "SGI_DMI_DMFATTR"
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
uint_t cursize;
|
||||
int i;
|
||||
int j;
|
||||
char name[MAXNAMELEN];
|
||||
char attr[DMFATTRLEN];
|
||||
double stime;
|
||||
|
||||
while ((c = getopt(argc, argv, "a:b:c:d:f:l:m:n:s:")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
addval = (uint_t)atoi(optarg);
|
||||
break;
|
||||
case 'b':
|
||||
bsize = (size_t)atol(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
nchars = (uint_t)atoi(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
directory = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
firstsize = (uint_t)atoi(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
lastsize = (uint_t)atoi(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
mulval = atof(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
ndirs = (uint_t)atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
fsize = (off64_t)atol(optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (!addval && !mulval)
|
||||
mulval = 2.0;
|
||||
else if ((addval && mulval) || mulval < 0.0) {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
if (!bsize)
|
||||
bsize = 1024 * 1024;
|
||||
buffer = memalign(getpagesize(), bsize);
|
||||
memset(buffer, 0xfeed, bsize);
|
||||
memset(attr, 0xaaaaaaa, sizeof(attr));
|
||||
|
||||
if (!directory)
|
||||
directory = ".";
|
||||
else {
|
||||
if (mkdir(directory, 0777) < 0 && errno != EEXIST) {
|
||||
perror(directory);
|
||||
exit(1);
|
||||
}
|
||||
if (chdir(directory) < 0) {
|
||||
perror(directory);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (firstsize == 0)
|
||||
firstsize = DFL_FIRST_SIZE;
|
||||
else if (firstsize > MAX_DIR_SIZE)
|
||||
firstsize = MAX_DIR_SIZE;
|
||||
if (lastsize == 0)
|
||||
lastsize = DFL_LAST_SIZE;
|
||||
else if (lastsize > MAX_DIR_SIZE)
|
||||
lastsize = MAX_DIR_SIZE;
|
||||
if (lastsize < firstsize)
|
||||
lastsize = firstsize;
|
||||
minchars = hexchars(lastsize - 1);
|
||||
if (nchars < minchars)
|
||||
nchars = minchars;
|
||||
else if (nchars >= MAXNAMELEN)
|
||||
nchars = MAXNAMELEN - 1;
|
||||
if (ndirs > MAX_DIR_COUNT)
|
||||
ndirs = MAX_DIR_COUNT;
|
||||
if (ndirs < MIN_DIR_COUNT)
|
||||
ndirs = MIN_DIR_COUNT;
|
||||
dirchars = hexchars(ndirs);
|
||||
pfxchars = nchars - minchars;
|
||||
if (pfxchars)
|
||||
memset(&name[dirchars + 1], 'a', pfxchars);
|
||||
|
||||
cursize = firstsize;
|
||||
for (j = 0; j < ndirs; j++) {
|
||||
filename(0, j, name);
|
||||
name[dirchars] = '\0';
|
||||
mkdir(name, 0777);
|
||||
stime = now();
|
||||
for (i = 0; i < cursize; i++) {
|
||||
filename((i + j) % cursize, j, name);
|
||||
close(mkfile(name, attr));
|
||||
}
|
||||
printf("%d %.3f\n", cursize,
|
||||
(now() - stime) * 1.0e3 / (cursize * ndirs));
|
||||
cursize = nextsize(cursize);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mkfile(char *name, char *attr)
|
||||
{
|
||||
int fd;
|
||||
ssize_t wrote, wsize;
|
||||
off64_t bytes = fsize;
|
||||
|
||||
if ((fd = open(name, O_WRONLY | O_CREAT | O_EXCL | O_DIRECT)) < 0) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
if (attr_setf(fd, DMFATTRNAME, attr, DMFATTRLEN, ATTR_ROOT) < 0) {
|
||||
perror("attr_setf");
|
||||
exit(1);
|
||||
}
|
||||
while (bytes > 0) {
|
||||
wsize = (bsize < bytes) ? bsize : bytes;
|
||||
if ((wrote = write(fd, buffer, wsize)) < 0) {
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
bytes -= wrote;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void
|
||||
filename(int idx, int dir, char *name)
|
||||
{
|
||||
static char hexc[16] = "0123456789abcdef";
|
||||
int i;
|
||||
|
||||
for (i = dirchars - 1; i >= 0; i--)
|
||||
*name++ = hexc[(dir >> (4 * i)) & 0xf];
|
||||
*name++ = '/';
|
||||
name += pfxchars; /* skip pfx a's */
|
||||
for (i = minchars - 1; i >= 0; i--)
|
||||
*name++ = hexc[(idx >> (4 * i)) & 0xf];
|
||||
*name = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
hexchars(uint_t maxval)
|
||||
{
|
||||
if (maxval < 16)
|
||||
return 1;
|
||||
if (maxval < 16 * 16)
|
||||
return 2;
|
||||
if (maxval < 16 * 16 * 16)
|
||||
return 3;
|
||||
if (maxval < 16 * 16 * 16 * 16)
|
||||
return 4;
|
||||
if (maxval < 16 * 16 * 16 * 16 * 16)
|
||||
return 5;
|
||||
if (maxval < 16 * 16 * 16 * 16 * 16 * 16)
|
||||
return 6;
|
||||
if (maxval < 16 * 16 * 16 * 16 * 16 * 16 * 16)
|
||||
return 7;
|
||||
return 8;
|
||||
}
|
||||
|
||||
static uint_t
|
||||
nextsize(uint_t cursize)
|
||||
{
|
||||
double n;
|
||||
|
||||
n = cursize;
|
||||
if (addval)
|
||||
n += addval;
|
||||
else
|
||||
n *= mulval;
|
||||
if (n > (double)lastsize + 0.5)
|
||||
return lastsize + 1; /* i.e. out of bounds */
|
||||
else if ((uint_t)n == cursize)
|
||||
return cursize + 1;
|
||||
else
|
||||
return (uint_t)n;
|
||||
}
|
||||
|
||||
static double
|
||||
now(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
return (double)tv.tv_sec + 1.0e-6 * (double)tv.tv_usec;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: dirperf [-d dir] [-a addstep | -m mulstep] [-f first] "
|
||||
"[-l last] [-c nchars] [-n ndirs] [-s size]\n");
|
||||
}
|
||||
Reference in New Issue
Block a user