1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2006 Silicon Graphics, Inc.
20 #include <attr/attributes.h>
22 typedef unsigned int uint_t;
25 * Loop over directory sizes:
27 * touch n files in each directory
28 * write y bytes to all files in each directory
29 * set DMF attribute on x files in each directory
30 * Change directory sizes by multiplication or addition.
31 * Allow control of starting & stopping sizes, name length, target directory.
32 * Print size and wallclock time (ms per file).
33 * Output can be used to make graphs (gnuplot)
37 static uint_t dirchars;
38 static char *directory;
39 static uint_t firstsize;
40 static uint_t lastsize;
41 static uint_t minchars;
45 static uint_t pfxchars;
50 static int mkfile(char *, char *);
51 static void filename(int, int, char *);
52 static int hexchars(uint_t);
53 static uint_t nextsize(uint_t);
54 static double now(void);
55 static void usage(void);
58 * Maximum size allowed, this is pretty nuts.
59 * The largest one we've ever built has been about 2 million.
61 #define MAX_DIR_SIZE (16 * 1024 * 1024)
62 #define DFL_FIRST_SIZE 1
63 #define DFL_LAST_SIZE (1024 * 1024)
64 #define MAX_DIR_COUNT 1024
65 #define MIN_DIR_COUNT 1
68 #define DMFATTRNAME "SGI_DMI_DMFATTR"
71 main(int argc, char **argv)
77 char name[NAME_MAX + 1];
78 char attr[DMFATTRLEN];
81 while ((c = getopt(argc, argv, "a:b:c:d:f:l:m:n:s:")) != -1) {
84 addval = (uint_t)atoi(optarg);
87 bsize = (size_t)atol(optarg);
90 nchars = (uint_t)atoi(optarg);
96 firstsize = (uint_t)atoi(optarg);
99 lastsize = (uint_t)atoi(optarg);
102 mulval = atof(optarg);
105 ndirs = (uint_t)atoi(optarg);
108 fsize = (off64_t)atol(optarg);
116 if (!addval && !mulval)
118 else if ((addval && mulval) || mulval < 0.0) {
124 buffer = memalign(getpagesize(), bsize);
125 memset(buffer, 0xfeed, bsize);
126 memset(attr, 0xaaaaaaa, sizeof(attr));
131 if (mkdir(directory, 0777) < 0 && errno != EEXIST) {
135 if (chdir(directory) < 0) {
141 firstsize = DFL_FIRST_SIZE;
142 else if (firstsize > MAX_DIR_SIZE)
143 firstsize = MAX_DIR_SIZE;
145 lastsize = DFL_LAST_SIZE;
146 else if (lastsize > MAX_DIR_SIZE)
147 lastsize = MAX_DIR_SIZE;
148 if (lastsize < firstsize)
149 lastsize = firstsize;
150 minchars = hexchars(lastsize - 1);
151 if (nchars < minchars)
153 else if (nchars >= NAME_MAX + 1)
155 if (ndirs > MAX_DIR_COUNT)
156 ndirs = MAX_DIR_COUNT;
157 if (ndirs < MIN_DIR_COUNT)
158 ndirs = MIN_DIR_COUNT;
159 dirchars = hexchars(ndirs);
160 pfxchars = nchars - minchars;
162 memset(&name[dirchars + 1], 'a', pfxchars);
165 for (j = 0; j < ndirs; j++) {
166 filename(0, j, name);
167 name[dirchars] = '\0';
170 for (i = 0; i < cursize; i++) {
171 filename((i + j) % cursize, j, name);
172 close(mkfile(name, attr));
174 printf("%d %.3f\n", cursize,
175 (now() - stime) * 1.0e3 / (cursize * ndirs));
176 cursize = nextsize(cursize);
182 mkfile(char *name, char *attr)
185 ssize_t wrote, wsize;
186 off64_t bytes = fsize;
188 if ((fd = open(name, O_WRONLY | O_CREAT | O_EXCL | O_DIRECT, 0666)) < 0) {
192 if (attr_setf(fd, DMFATTRNAME, attr, DMFATTRLEN, ATTR_ROOT) < 0) {
197 wsize = (bsize < bytes) ? bsize : bytes;
198 if ((wrote = write(fd, buffer, wsize)) < 0) {
208 filename(int idx, int dir, char *name)
210 static char hexc[16] = "0123456789abcdef";
213 for (i = dirchars - 1; i >= 0; i--)
214 *name++ = hexc[(dir >> (4 * i)) & 0xf];
216 name += pfxchars; /* skip pfx a's */
217 for (i = minchars - 1; i >= 0; i--)
218 *name++ = hexc[(idx >> (4 * i)) & 0xf];
223 hexchars(uint_t maxval)
227 if (maxval < 16 * 16)
229 if (maxval < 16 * 16 * 16)
231 if (maxval < 16 * 16 * 16 * 16)
233 if (maxval < 16 * 16 * 16 * 16 * 16)
235 if (maxval < 16 * 16 * 16 * 16 * 16 * 16)
237 if (maxval < 16 * 16 * 16 * 16 * 16 * 16 * 16)
243 nextsize(uint_t cursize)
252 if (n > (double)lastsize + 0.5)
253 return lastsize + 1; /* i.e. out of bounds */
254 else if ((uint_t)n == cursize)
265 gettimeofday(&tv, NULL);
266 return (double)tv.tv_sec + 1.0e-6 * (double)tv.tv_usec;
273 "usage: dirperf [-d dir] [-a addstep | -m mulstep] [-f first] "
274 "[-l last] [-c nchars] [-n ndirs] [-s size]\n");