Auto-detect missing hw support for crc32c and fallback to software
authorJens Axboe <jaxboe@fusionio.com>
Mon, 21 Jun 2010 13:08:17 +0000 (15:08 +0200)
committerJens Axboe <jaxboe@fusionio.com>
Mon, 21 Jun 2010 13:08:17 +0000 (15:08 +0200)
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
crc/crc32c-intel.c
crc/crc32c.h
fio.c
options.c

index cec5ad5dec9d5d88ec7498133f2915ae0c1bd146..fc106fa5a9755348e97b5e7dd631267b911061f0 100644 (file)
@@ -1,4 +1,10 @@
 #include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include "crc32c.h"
 
 /*
@@ -68,5 +74,37 @@ uint32_t crc32c_intel(unsigned char const *data, unsigned long length)
        return crc;
 }
 
-#endif /* ARCH_HAVE_SSE */
+static void sig_ill(int sig)
+{
+}
+
+static void crc32c_test(void)
+{
+       unsigned char buf[4] = { 1, 2, 3, 4 };
+       struct sigaction act;
+
+       /*
+        * Check if hw accelerated crc32c is available
+        */
+       memset(&act, 0, sizeof(act));
+       act.sa_handler = sig_ill;
+       act.sa_flags = SA_RESETHAND;
+       sigaction(SIGILL, &act, NULL);
+
+       (void) crc32c_intel(buf, sizeof(buf));
+}
+
+int crc32c_intel_works(void)
+{
+       if (!fork()) {
+               crc32c_test();
+               exit(0);
+       } else {
+               int status;
 
+               wait(&status);
+               return !WIFSIGNALED(status);
+       }
+}
+
+#endif /* ARCH_HAVE_SSE */
index 0976261ac61832a9b36e1ab50a93b6c59b60d8f7..50f3665f39375ddc4a8c4d6c7888930a13dcdda6 100644 (file)
@@ -24,8 +24,13 @@ extern uint32_t crc32c(unsigned char const *, unsigned long);
 
 #ifdef ARCH_HAVE_SSE
 extern uint32_t crc32c_intel(unsigned char const *, unsigned long);
+extern int crc32c_intel_works(void);
 #else
 #define crc32c_intel crc32c
+static inline int crc32c_intel_works(void)
+{
+       return 0;
+}
 #endif
 
 #endif
diff --git a/fio.c b/fio.c
index 4d260600056ba7ee99c1d06365195f962e29f4b3..b2a08bf0154f594e06f0ea8850f3c49bd5189dd3 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -142,15 +142,6 @@ static void sig_int(int sig)
        }
 }
 
-static void sig_ill(int fio_unused sig)
-{
-       if (!threads)
-               return;
-
-       log_err("fio: system does not support the sse4.2 instruction for crc32c-intel.\nUse crc32c instead.\n");
-       terminate_threads(TERMINATE_ALL);
-}
-
 static void set_sig_handlers(void)
 {
        struct sigaction act;
@@ -165,11 +156,6 @@ static void set_sig_handlers(void)
        act.sa_flags = SA_RESTART;
        sigaction(SIGINT, &act, NULL);
 
-       memset(&act, 0, sizeof(act));
-       act.sa_handler = sig_ill;
-       act.sa_flags = SA_RESETHAND;
-       sigaction(SIGILL, &act, NULL);
-
        memset(&act, 0, sizeof(act));
        act.sa_handler = sig_quit;
        act.sa_flags = SA_RESTART;
index f470b45392cb78e8884f5d33c0aaa489293c5616..fb187489766205d64a15e08b7d86b7a1edb04f2e 100644 (file)
--- a/options.c
+++ b/options.c
@@ -16,6 +16,8 @@
 #include "lib/fls.h"
 #include "options.h"
 
+#include "crc/crc32c.h"
+
 /*
  * Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that.
  */
@@ -225,6 +227,21 @@ static int str_mem_cb(void *data, const char *mem)
        return 0;
 }
 
+static int str_verify_cb(void *data, const char *mem)
+{
+       struct thread_data *td = data;
+
+       if (td->o.verify != VERIFY_CRC32C_INTEL)
+               return 0;
+
+       if (!crc32c_intel_works()) {
+               log_info("fio: System does not support hw accelerated crc32c. Falling back to sw crc32c.\n");
+               td->o.verify = VERIFY_CRC32C;
+       }
+
+       return 0;
+}
+
 static int fio_clock_source_cb(void *data, const char *str)
 {
        struct thread_data *td = data;
@@ -1298,6 +1315,7 @@ static struct fio_option options[FIO_MAX_OPTS] = {
                .type   = FIO_OPT_STR,
                .off1   = td_var_offset(verify),
                .help   = "Verify data written",
+               .cb     = str_verify_cb,
                .def    = "0",
                .posval = {
                          { .ival = "0",