Add support for AIX
authorCigy Cyriac <CCyriac@fusionio.com>
Tue, 10 Aug 2010 23:51:11 +0000 (19:51 -0400)
committerJens Axboe <jaxboe@fusionio.com>
Tue, 10 Aug 2010 23:51:11 +0000 (19:51 -0400)
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Makefile.aix [new file with mode: 0644]
README
fio.h
init.c
lib/getopt.h [new file with mode: 0644]
lib/getopt_long.c [new file with mode: 0644]
options.c
os/os-aix.h [new file with mode: 0644]
os/os.h

diff --git a/Makefile.aix b/Makefile.aix
new file mode 100644 (file)
index 0000000..29d6e09
--- /dev/null
@@ -0,0 +1,73 @@
+CC     = gcc
+DEBUGFLAGS = -D_FORTIFY_SOURCE=2 -DFIO_INC_DEBUG
+OPTFLAGS= -O2 -g $(EXTFLAGS)
+CFLAGS = -Wwrite-strings -Wall -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(DEBUGFLAGS) -fno-omit-frame-pointer -D_LARGE_FILES -D__ppc__
+PROGS  = fio
+SCRIPTS = fio_generate_plots
+OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o filesetup.o \
+       eta.o verify.o memory.o io_u.o parse.o mutex.o options.o \
+       rbtree.o fifo.o smalloc.o filehash.o helpers.o \
+       profile.o debug.o getopt_long.o
+
+OBJS += lib/rand.o
+OBJS += lib/getopt_long.o
+
+OBJS += crc/crc7.o
+OBJS += crc/crc16.o
+OBJS += crc/crc32.o
+OBJS += crc/crc32c.o
+OBJS += crc/crc32c-intel.o
+OBJS += crc/crc64.o
+OBJS += crc/sha1.o
+OBJS += crc/sha256.o
+OBJS += crc/sha512.o
+OBJS += crc/md5.o
+
+OBJS += engines/cpu.o
+OBJS += engines/mmap.o
+OBJS += engines/posixaio.o
+OBJS += engines/sync.o
+OBJS += engines/null.o
+OBJS += engines/net.o
+
+OBJS += profiles/tiobench.o
+
+ifneq ($(findstring $(MAKEFLAGS),s),s)
+ifndef V
+       QUIET_CC        = @echo '   ' CC $@;
+       QUIET_DEP       = @echo '   ' DEP $@;
+endif
+endif
+
+INSTALL = installbsd -c
+prefix = /usr/local
+bindir = $(prefix)/bin
+mandir = $(prefix)/man
+
+%.o: %.c
+       $(QUIET_CC)$(CC) -o $*.o -c $(CFLAGS) $<
+fio: $(OBJS)
+       $(QUIET_CC)$(CC) $(CFLAGS) -o $@ $(filter %.o,$^) $(EXTLIBS) -lpthread -lm -ldl -lrt
+
+depend:
+       $(QUIET_DEP)$(CC) -MM $(ALL_CFLAGS) *.c engines/*.c crc/*.c 1> .depend
+
+$(PROGS): depend
+
+all: depend $(PROGS) $(SCRIPTS)
+
+clean:
+       -rm -f .depend cscope.out $(OBJS) $(PROGS) core.* core
+
+cscope:
+       @cscope -b
+
+install: $(PROGS) $(SCRIPTS)
+       mkdir -p -m 755 $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1
+       $(INSTALL) $(PROGS) $(SCRIPTS) $(DESTDIR)$(bindir)
+       $(INSTALL) -m 644 fio.1 $(DESTDIR)$(mandir)/man1
+       $(INSTALL) -m 644 fio_generate_plots.1 $(DESTDIR)$(mandir)/man1
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/README b/README
index f2438badd3a13e76e689a31a2d710380e36289b7..41154552bba6c5643f5ddbc06713f3eaad2be01b 100644 (file)
--- a/README
+++ b/README
@@ -65,6 +65,10 @@ specify the FreeBSD Makefile with -f and use gmake (not make), eg:
 
 $ gmake -f Makefile.Freebsd && gmake -f Makefile.FreeBSD install
 
+Same goes for AIX:
+
+$ gmake -f Makefile.aix && gmake -f Makefile.aix install
+
 Likewise with OpenSolaris, use the Makefile.solaris to compile there.
 The OpenSolaris make should work fine. This might change in the
 future if I opt for an autoconf type setup.
@@ -270,7 +274,7 @@ The job file parameters are:
 Platforms
 ---------
 
-Fio works on (at least) Linux, Solaris, and FreeBSD. Some features and/or
+Fio works on (at least) Linux, Solaris, AIX and FreeBSD. Some features and/or
 options may only be available on some of the platforms, typically because
 those features only apply to that platform (like the solarisaio engine, or
 the splice engine on Linux).
@@ -291,6 +295,23 @@ your mileage may vary. Sending me patches for other platforms is greatly
 appreciated. There's a lot of value in having the same test/benchmark tool
 available on all platforms.
 
+Note that POSIX aio is not enabled by default on AIX. If you get messages like:
+
+    Symbol resolution failed for /usr/lib/libc.a(posix_aio.o) because:
+        Symbol _posix_kaio_rdwr (number 2) is not exported from dependent module /unix.
+
+you need to enable POSIX aio. Run the following commands as root:
+
+    # lsdev -C -l posix_aio0
+        posix_aio0 Defined  Posix Asynchronous I/O
+    # cfgmgr -l posix_aio0
+    # lsdev -C -l posix_aio0
+        posix_aio0 Available  Posix Asynchronous I/O
+
+POSIX aio should work now. To make the change permanent:
+
+    # chdev -l posix_aio0 -P -a autoconfig='available'
+        posix_aio0 changed
 
 
 Author
diff --git a/fio.h b/fio.h
index de76e6599cacbb5d29e2f0edbf33988cc460375d..57881072b2156162209eb7c386e80f50a0c1cc45 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -11,7 +11,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
-#include <getopt.h>
 #include <inttypes.h>
 #include <assert.h>
 
@@ -32,6 +31,7 @@
 #include "options.h"
 #include "profile.h"
 #include "time.h"
+#include "lib/getopt.h"
 
 #ifdef FIO_HAVE_GUASI
 #include <guasi.h>
diff --git a/init.c b/init.c
index 09b9152ae29d47a0ce252715495b92d6bc607c6f..c3fe88f6986f256d61374f9f0f434cbff3f2d1be 100644 (file)
--- a/init.c
+++ b/init.c
@@ -8,7 +8,6 @@
 #include <ctype.h>
 #include <string.h>
 #include <errno.h>
-#include <getopt.h>
 #include <sys/ipc.h>
 #include <sys/shm.h>
 #include <sys/types.h>
@@ -21,6 +20,8 @@
 #include "verify.h"
 #include "profile.h"
 
+#include "lib/getopt.h"
+
 static char fio_version_string[] = "fio 1.42";
 
 #define FIO_RANDSEED           (0xb1899bedUL)
diff --git a/lib/getopt.h b/lib/getopt.h
new file mode 100644 (file)
index 0000000..56fe3bf
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _AIX
+
+#include <getopt.h>
+
+#else /* _AIX */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+struct option {
+       const char *name;
+       int has_arg;
+       int *flag;
+       int val;
+};
+
+enum {
+       no_argument       = 0,
+       required_argument = 1,
+       optional_argument = 2,
+};
+
+int getopt_long_only(int, char *const *, const char *, const struct option *, int *);
+
+#endif /* _GETOPT_H */
+#endif /* _AIX */
diff --git a/lib/getopt_long.c b/lib/getopt_long.c
new file mode 100644 (file)
index 0000000..3d80627
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * getopt.c
+ *
+ * getopt_long(), or at least a common subset thereof:
+ *
+ * - Option reordering is not supported
+ * - -W foo is not supported
+ * - First optstring character "-" not supported.
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+char *optarg;
+int optind, opterr, optopt;
+static struct getopt_private_state {
+       const char *optptr;
+       const char *last_optstring;
+       char *const *last_argv;
+} pvt;
+
+static inline const char *option_matches(const char *arg_str,
+                                        const char *opt_name)
+{
+       while (*arg_str != '\0' && *arg_str != '=') {
+               if (*arg_str++ != *opt_name++)
+                       return NULL;
+       }
+
+       if (*opt_name)
+               return NULL;
+
+       return arg_str;
+}
+
+int getopt_long_only(int argc, char *const *argv, const char *optstring,
+               const struct option *longopts, int *longindex)
+{
+       const char *carg;
+       const char *osptr;
+       int opt;
+
+       /* getopt() relies on a number of different global state
+          variables, which can make this really confusing if there is
+          more than one use of getopt() in the same program.  This
+          attempts to detect that situation by detecting if the
+          "optstring" or "argv" argument have changed since last time
+          we were called; if so, reinitialize the query state. */
+
+       if (optstring != pvt.last_optstring || argv != pvt.last_argv ||
+           optind < 1 || optind > argc) {
+               /* optind doesn't match the current query */
+               pvt.last_optstring = optstring;
+               pvt.last_argv = argv;
+               optind = 1;
+               pvt.optptr = NULL;
+       }
+
+       carg = argv[optind];
+
+       /* First, eliminate all non-option cases */
+
+       if (!carg || carg[0] != '-' || !carg[1])
+               return -1;
+
+       if (carg[1] == '-') {
+               const struct option *lo;
+               const char *opt_end = NULL;
+
+               optind++;
+
+               /* Either it's a long option, or it's -- */
+               if (!carg[2]) {
+                       /* It's -- */
+                       return -1;
+               }
+
+               for (lo = longopts; lo->name; lo++) {
+                       if ((opt_end = option_matches(carg+2, lo->name)))
+                           break;
+               }
+               if (!opt_end)
+                       return '?';
+
+               if (longindex)
+                       *longindex = lo-longopts;
+
+               if (*opt_end == '=') {
+                       if (lo->has_arg)
+                               optarg = (char *)opt_end+1;
+                       else
+                               return '?';
+               } else if (lo->has_arg == 1) {
+                       if (!(optarg = argv[optind]))
+                               return '?';
+                       optind++;
+               }
+
+               if (lo->flag) {
+                       *lo->flag = lo->val;
+                       return 0;
+               } else {
+                       return lo->val;
+               }
+       }
+
+       if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) {
+               /* Someone frobbed optind, change to new opt. */
+               pvt.optptr = carg + 1;
+       }
+
+       opt = *pvt.optptr++;
+
+       if (opt != ':' && (osptr = strchr(optstring, opt))) {
+               if (osptr[1] == ':') {
+                       if (*pvt.optptr) {
+                               /* Argument-taking option with attached
+                                  argument */
+                               optarg = (char *)pvt.optptr;
+                               optind++;
+                       } else {
+                               /* Argument-taking option with non-attached
+                                  argument */
+                               if (argv[optind + 1]) {
+                                       optarg = (char *)argv[optind+1];
+                                       optind += 2;
+                               } else {
+                                       /* Missing argument */
+                                       optind++;
+                                       return (optstring[0] == ':')
+                                               ? ':' : '?';
+                               }
+                       }
+                       return opt;
+               } else {
+                       /* Non-argument-taking option */
+                       /* pvt.optptr will remember the exact position to
+                          resume at */
+                       if (!*pvt.optptr)
+                               optind++;
+                       return opt;
+               }
+       } else {
+               /* Unknown option */
+               optopt = opt;
+               if (!*pvt.optptr)
+                       optind++;
+               return '?';
+       }
+}
index 6dd74ed42732aff997a41ecdeee08d5e09cfac33..7a9d5d392ad60afbc9f7431362746d3ed79bffb9 100644 (file)
--- a/options.c
+++ b/options.c
@@ -3,7 +3,6 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <string.h>
-#include <getopt.h>
 #include <assert.h>
 #include <libgen.h>
 #include <fcntl.h>
diff --git a/os/os-aix.h b/os/os-aix.h
new file mode 100644 (file)
index 0000000..1cc35e8
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef FIO_OS_AIX_H
+#define FIO_OS_AIX_H
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/devinfo.h>
+#include <sys/ioctl.h>
+
+#define FIO_HAVE_POSIXAIO
+#define FIO_HAVE_FALLOCATE
+#define FIO_HAVE_ODIRECT
+#define FIO_USE_GENERIC_RAND
+
+#define FIO_HAVE_PSHARED_MUTEX
+
+#define OS_MAP_ANON            MAP_ANON
+
+static inline int blockdev_invalidate_cache(int fd)
+{
+       return EINVAL;
+}
+
+static inline int blockdev_size(int fd, unsigned long long *bytes)
+{
+       struct devinfo info;
+
+       if (!ioctl(fd, IOCINFO, &info)) {
+               *bytes = (unsigned long long)info.un.scdk.numblks *
+                               info.un.scdk.blksize;
+               return 0;
+       }
+
+       return errno;
+}
+
+static inline unsigned long long os_phys_mem(void)
+{
+       long mem = sysconf(_SC_AIX_REALMEM);
+
+       if (mem == -1)
+               return 0;
+
+       return (unsigned long long) mem * 1024;
+}
+
+#endif
diff --git a/os/os.h b/os/os.h
index 218766ab1fee160a252dc3bc14a8c5ee69705c79..e2bb0ba9a23b49da17be0fc6987d68b8b2f86d64 100644 (file)
--- a/os/os.h
+++ b/os/os.h
@@ -14,6 +14,8 @@
 #include "os-solaris.h"
 #elif defined(__APPLE__)
 #include "os-mac.h"
+#elif defined(_AIX)
+#include "os-aix.h"
 #else
 #error "unsupported os"
 #endif