Start of client/server
authorJens Axboe <axboe@kernel.dk>
Thu, 29 Sep 2011 23:45:28 +0000 (17:45 -0600)
committerJens Axboe <axboe@kernel.dk>
Thu, 29 Sep 2011 23:45:28 +0000 (17:45 -0600)
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Makefile
fio.c
fio.h
init.c
server.c [new file with mode: 0644]
server.h [new file with mode: 0644]

index 85942a0..a4b042b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ SOURCE = gettime.c fio.c ioengines.c init.c stat.c log.c time.c filesetup.c \
                rbtree.c smalloc.c filehash.c profile.c debug.c lib/rand.c \
                lib/num2str.c $(wildcard crc/*.c) engines/cpu.c \
                engines/mmap.c engines/sync.c engines/null.c engines/net.c \
-               memalign.c
+               memalign.c server.c
 
 ifeq ($(UNAME), Linux)
   SOURCE += diskutil.c fifo.c blktrace.c helpers.c cgroup.c trim.c \
diff --git a/fio.c b/fio.c
index b492889..8c844af 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -1690,41 +1690,16 @@ static void run_threads(void)
        fio_unpin_memory();
 }
 
-int main(int argc, char *argv[], char *envp[])
+int exec_run(void)
 {
-       long ps;
-
-       arch_init(envp);
-
-       sinit();
-
-       /*
-        * We need locale for number printing, if it isn't set then just
-        * go with the US format.
-        */
-       if (!getenv("LC_NUMERIC"))
-               setlocale(LC_NUMERIC, "en_US");
-
-       ps = sysconf(_SC_PAGESIZE);
-       if (ps < 0) {
-               log_err("Failed to get page size\n");
-               return 1;
-       }
-
-       page_size = ps;
-       page_mask = ps - 1;
-
-       fio_keywords_init();
-
-       if (parse_options(argc, argv))
-               return 1;
-
        if (exec_profile && load_profile(exec_profile))
                return 1;
 
        if (!thread_number)
                return 0;
 
+       printf("%d threads\n", thread_number);
+
        if (write_bw_log) {
                setup_log(&agg_io_log[DDIR_READ]);
                setup_log(&agg_io_log[DDIR_WRITE]);
@@ -1762,3 +1737,44 @@ int main(int argc, char *argv[], char *envp[])
        fio_mutex_remove(writeout_mutex);
        return exit_value;
 }
+
+void reset_fio_state(void)
+{
+       groupid = 0;
+       thread_number = 0;
+       nr_process = 0;
+       nr_thread = 0;
+       done_secs = 0;
+}
+
+int main(int argc, char *argv[], char *envp[])
+{
+       long ps;
+
+       arch_init(envp);
+
+       sinit();
+
+       /*
+        * We need locale for number printing, if it isn't set then just
+        * go with the US format.
+        */
+       if (!getenv("LC_NUMERIC"))
+               setlocale(LC_NUMERIC, "en_US");
+
+       ps = sysconf(_SC_PAGESIZE);
+       if (ps < 0) {
+               log_err("Failed to get page size\n");
+               return 1;
+       }
+
+       page_size = ps;
+       page_mask = ps - 1;
+
+       fio_keywords_init();
+
+       if (parse_options(argc, argv))
+               return 1;
+
+       return exec_run();
+}
diff --git a/fio.h b/fio.h
index 022ba57..49ddd92 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -690,6 +690,9 @@ static inline int should_fsync(struct thread_data *td)
  * Init/option functions
  */
 extern int __must_check parse_options(int, char **);
+extern int parse_jobs_ini(char *, int, int);
+extern int exec_run(void);
+extern void reset_fio_state(void);
 extern int fio_options_parse(struct thread_data *, char **, int);
 extern void fio_keywords_init(void);
 extern int fio_cmd_option_parse(struct thread_data *, const char *, char *);
diff --git a/init.c b/init.c
index 62c070e..5d57091 100644 (file)
--- a/init.c
+++ b/init.c
@@ -19,6 +19,7 @@
 #include "filehash.h"
 #include "verify.h"
 #include "profile.h"
+#include "server.h"
 
 #include "lib/getopt.h"
 
@@ -44,6 +45,7 @@ int nr_job_sections = 0;
 char *exec_profile = NULL;
 int warnings_fatal = 0;
 int terse_version = 2;
+int is_backend = 0;
 
 int write_bw_log = 0;
 int read_only = 0;
@@ -153,6 +155,11 @@ static struct option l_opts[FIO_NR_OPTIONS] = {
                .has_arg        = required_argument,
                .val            = 'V',
        },
+       {
+               .name           = (char *) "server",
+               .has_arg        = no_argument,
+               .val            = 'S',
+       },
        {
                .name           = NULL,
        },
@@ -799,7 +806,7 @@ static int is_empty_or_comment(char *line)
 /*
  * This is our [ini] type file parser.
  */
-static int parse_jobs_ini(char *file, int stonewall_flag)
+int parse_jobs_ini(char *file, int is_buf, int stonewall_flag)
 {
        unsigned int global;
        struct thread_data *td;
@@ -813,14 +820,18 @@ static int parse_jobs_ini(char *file, int stonewall_flag)
        char **opts;
        int i, alloc_opts, num_opts;
 
-       if (!strcmp(file, "-"))
-               f = stdin;
-       else
-               f = fopen(file, "r");
+       if (is_buf)
+               f = NULL;
+       else {
+               if (!strcmp(file, "-"))
+                       f = stdin;
+               else
+                       f = fopen(file, "r");
 
-       if (!f) {
-               perror("fopen job file");
-               return 1;
+               if (!f) {
+                       perror("fopen job file");
+                       return 1;
+               }
        }
 
        string = malloc(4096);
@@ -842,7 +853,10 @@ static int parse_jobs_ini(char *file, int stonewall_flag)
                 * haven't handled.
                 */
                if (!skip_fgets) {
-                       p = fgets(string, 4095, f);
+                       if (is_buf)
+                               p = strsep(&file, "\n");
+                       else
+                               p = fgets(string, 4095, f);
                        if (!p)
                                break;
                }
@@ -896,7 +910,14 @@ static int parse_jobs_ini(char *file, int stonewall_flag)
                num_opts = 0;
                memset(opts, 0, alloc_opts * sizeof(char *));
 
-               while ((p = fgets(string, 4096, f)) != NULL) {
+               while (1) {
+                       if (is_buf)
+                               p = strsep(&file, "\n");
+                       else
+                               p = fgets(string, 4096, f);
+                       if (!p)
+                               break;
+
                        if (is_empty_or_comment(p))
                                continue;
 
@@ -949,7 +970,7 @@ static int parse_jobs_ini(char *file, int stonewall_flag)
        free(string);
        free(name);
        free(opts);
-       if (f != stdin)
+       if (!is_buf && f != stdin)
                fclose(f);
        return ret;
 }
@@ -1282,6 +1303,9 @@ static int parse_cmd_line(int argc, char *argv[])
                                exit_val = 1;
                        }
                        break;
+               case 'S':
+                       is_backend = 1;
+                       break;
                default:
                        do_exit++;
                        exit_val = 1;
@@ -1292,6 +1316,9 @@ static int parse_cmd_line(int argc, char *argv[])
        if (do_exit)
                exit(exit_val);
 
+       if (is_backend)
+               fio_server();
+
        if (td) {
                if (!ret)
                        ret = add_job(td, td->o.name ?: "fio", 0);
@@ -1327,7 +1354,7 @@ int parse_options(int argc, char *argv[])
        for (i = 0; i < job_files; i++) {
                if (fill_def_thread())
                        return 1;
-               if (parse_jobs_ini(ini_file[i], i))
+               if (parse_jobs_ini(ini_file[i], 0, i))
                        return 1;
                free(ini_file[i]);
        }
diff --git a/server.c b/server.c
new file mode 100644 (file)
index 0000000..bd49b9c
--- /dev/null
+++ b/server.c
@@ -0,0 +1,108 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "fio.h"
+
+static int net_port = 8765;
+
+static int accept_loop(int listen_sk)
+{
+       struct sockaddr addr;
+       unsigned int len = sizeof(addr);
+       int sk;
+
+again:
+       sk = accept(listen_sk, &addr, &len);
+       printf("got a hit\n");
+       if (sk < 0) {
+               log_err("fio: accept failed\n");
+               return -1;
+       }
+
+       /* read forever */
+       for (;;) {
+               char buf[131072];
+               int ret;
+
+               ret = recv(sk, buf, 4096, 0);
+               if (ret > 0) {
+                       parse_jobs_ini(buf, 1, 0);
+                       exec_run();
+                       reset_fio_state();
+                       break;
+               } else if (!ret)
+                       break;
+               if (errno == EAGAIN || errno == EINTR)
+                       continue;
+               break;
+       }
+
+       close(sk);
+       printf("closed\n");
+       goto again;
+}
+
+int fio_server(void)
+{
+       struct sockaddr_in saddr_in;
+       struct sockaddr addr;
+       unsigned int len;
+       int sk, opt;
+
+       sk = socket(AF_INET, SOCK_STREAM, 0);
+       if (sk < 0) {
+               log_err("fio: socket\n");
+               return -1;
+       }
+
+       opt = 1;
+       if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
+               log_err("fio: setsockopt\n");
+               return -1;
+       }
+#ifdef SO_REUSEPORT
+       if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
+               td_verror(td, errno, "setsockopt");
+               return 1;
+       }
+#endif
+
+       saddr_in.sin_family = AF_INET;
+       saddr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+       saddr_in.sin_port = htons(net_port);
+
+       if (bind(sk, (struct sockaddr *) &saddr_in, sizeof(saddr_in)) < 0) {
+               perror("bind");
+               log_err("fio: bind\n");
+               return -1;
+       }
+
+       if (listen(sk, 1) < 0) {
+               log_err("fio: listen\n");
+               return -1;
+       }
+
+       len = sizeof(addr);
+       if (getsockname(sk, &addr, &len) < 0) {
+               log_err("fio: getsockname");
+               return -1;
+       }
+
+       return accept_loop(sk);
+}
diff --git a/server.h b/server.h
new file mode 100644 (file)
index 0000000..879faab
--- /dev/null
+++ b/server.h
@@ -0,0 +1,6 @@
+#ifndef FIO_SERVER_H
+#define FIO_SERVER_H
+
+extern int fio_server(void);
+
+#endif