Simple little program for populating a filesystem that could look like one DMF might...
authorNathan Scott <nathans@sgi.com>
Fri, 7 Jul 2006 16:01:51 +0000 (16:01 +0000)
committerNathan Scott <nathans@sgi.com>
Fri, 7 Jul 2006 16:01:51 +0000 (16:01 +0000)
Merge of master-melb:xfs-cmds:26472a by kenmcd.

src/Makefile
src/dmiperf.c [new file with mode: 0644]

index c82e8289018dc9b30643aa813ec357ade9a6bce2..b041a1c285de93d612db4412d650086d9c6c3da0 100644 (file)
@@ -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 \
        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
 
 
 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)
 
 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
 
 ifeq ($(PKG_PLATFORM),irix)
 fill2: fill2.o
diff --git a/src/dmiperf.c b/src/dmiperf.c
new file mode 100644 (file)
index 0000000..28f95a4
--- /dev/null
@@ -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");
+}