Add support for AIX
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
diff --git a/Makefile.aix b/Makefile.aix
new file mode 100644
index 0000000..29d6e09
--- /dev/null
+++ b/Makefile.aix
@@ -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 f2438ba..4115455 100644
--- a/README
+++ b/README
@@ -65,6 +65,10 @@
$ 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 @@
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 @@
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 de76e65..5788107 100644
--- 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 09b9152..c3fe88f 100644
--- 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
index 0000000..56fe3bf
--- /dev/null
+++ b/lib/getopt.h
@@ -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
index 0000000..3d80627
--- /dev/null
+++ b/lib/getopt_long.c
@@ -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 '?';
+ }
+}
diff --git a/options.c b/options.c
index 6dd74ed..7a9d5d3 100644
--- 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
index 0000000..1cc35e8
--- /dev/null
+++ b/os/os-aix.h
@@ -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 218766a..e2bb0ba 100644
--- 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