diff options
| author | Kaushal M <kaushal@gluster.com> | 2011-09-06 17:18:20 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vijay@gluster.com> | 2011-09-19 22:00:25 -0700 | 
| commit | 8d4d8088c73f2ffc60b8e5c23a33e6b996fb5053 (patch) | |
| tree | df5e6dc68206c72ad1cb3f8b664f50028d725a8b | |
| parent | e0178776546f06646c11bcb1ea345f82436d73aa (diff) | |
glusterd: run 'volume top read-perf/write-perf' in different thread
Runs the 'volume top read-perf/write-perf' operations in a different
thread without blocking glusterd. Prvents glusterd from being
unresponsive when large values of 'bs' and 'count' are given.
Also increase cli timeout for top/profile commands , from 120s to 300s
to allow large i/o top read-perf and write-perf to return result.
Change-Id: I4b7de1d735f33643d836772db7f25133f112b75a
BUG: 2720
Reviewed-on: http://review.gluster.com/375
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Shishir Gowda <shishirng@gluster.com>
| -rw-r--r-- | cli/src/cli-cmd.c | 13 | ||||
| -rw-r--r-- | cli/src/cli-cmd.h | 2 | ||||
| -rw-r--r-- | cli/src/cli.h | 1 | ||||
| -rw-r--r-- | glusterfsd/src/glusterfsd-mem-types.h | 1 | ||||
| -rw-r--r-- | glusterfsd/src/glusterfsd-mgmt.c | 352 | ||||
| -rw-r--r-- | glusterfsd/src/glusterfsd.h | 16 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 195 | 
7 files changed, 352 insertions, 228 deletions
diff --git a/cli/src/cli-cmd.c b/cli/src/cli-cmd.c index 385e2ac2e1c..17869eb613d 100644 --- a/cli/src/cli-cmd.c +++ b/cli/src/cli-cmd.c @@ -31,6 +31,7 @@  #include "cli.h"  #include "cli-cmd.h"  #include "cli-mem-types.h" +#include "protocol-common.h"  #include <fnmatch.h> @@ -281,14 +282,14 @@ seconds_from_now (unsigned secs, struct timespec *ts)  }  int -cli_cmd_await_response () +cli_cmd_await_response (unsigned time)  {          struct  timespec        ts = {0,};          int                     ret = 0;          cli_op_ret = -1; -        seconds_from_now (CLI_DEFAULT_CMD_TIMEOUT, &ts); +        seconds_from_now (time, &ts);          while (!cmd_done && !ret) {                  ret = pthread_cond_timedwait (&cond, &cond_mutex,                                          &ts); @@ -366,7 +367,11 @@ cli_cmd_submit (void *req, call_frame_t *frame,                  int procnum, struct iobref *iobref,                  xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc)  { -        int     ret = -1; +        int             ret = -1; +        unsigned        timeout = 0; + +        timeout = (GLUSTER_CLI_PROFILE_VOLUME == procnum) ? +                   CLI_TOP_CMD_TIMEOUT : CLI_DEFAULT_CMD_TIMEOUT;          cli_cmd_lock ();          cmd_sent = 0; @@ -375,7 +380,7 @@ cli_cmd_submit (void *req, call_frame_t *frame,          if (!ret) {                  cmd_sent = 1; -                ret = cli_cmd_await_response (); +                ret = cli_cmd_await_response (timeout);          } else                  cli_cmd_unlock (); diff --git a/cli/src/cli-cmd.h b/cli/src/cli-cmd.h index 1878571fa34..82e0ff113a4 100644 --- a/cli/src/cli-cmd.h +++ b/cli/src/cli-cmd.h @@ -83,7 +83,7 @@ struct cli_cmd_word *cli_cmd_nextword (struct cli_cmd_word *word,                                         const char *text);  void cli_cmd_tokens_destroy (char **tokens); -int cli_cmd_await_response (); +int cli_cmd_await_response (unsigned time);  int cli_cmd_broadcast_response (int32_t status); diff --git a/cli/src/cli.h b/cli/src/cli.h index 1e0d69cd8a2..bf3437827ec 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -33,6 +33,7 @@  #define CLI_GLUSTERD_PORT                  24007  #define CLI_DEFAULT_CONN_TIMEOUT             120  #define CLI_DEFAULT_CMD_TIMEOUT              120 +#define CLI_TOP_CMD_TIMEOUT                  300 //Longer timeout for volume top  #define DEFAULT_CLI_LOG_FILE_DIRECTORY     DATADIR "/log/glusterfs"  #define CLI_VOL_STATUS_BRICK_LEN              55  #define CLI_TAB_LENGTH                         8 diff --git a/glusterfsd/src/glusterfsd-mem-types.h b/glusterfsd/src/glusterfsd-mem-types.h index 7f953d1ff80..a28a7b2e31b 100644 --- a/glusterfsd/src/glusterfsd-mem-types.h +++ b/glusterfsd/src/glusterfsd-mem-types.h @@ -30,6 +30,7 @@ enum gfd_mem_types_ {          gfd_mt_xlator_cmdline_option_t,          gfd_mt_char,          gfd_mt_call_pool_t, +        gfd_mt_vol_top_priv_t,          gfd_mt_end  }; diff --git a/glusterfsd/src/glusterfsd-mgmt.c b/glusterfsd/src/glusterfsd-mgmt.c index 330b83fa36f..43d49b3f4e8 100644 --- a/glusterfsd/src/glusterfsd-mgmt.c +++ b/glusterfsd/src/glusterfsd-mgmt.c @@ -22,6 +22,7 @@  #include <sys/wait.h>  #include <stdlib.h>  #include <signal.h> +#include <pthread.h>  #ifndef _CONFIG_H  #define _CONFIG_H @@ -38,11 +39,12 @@  #include "protocol-common.h"  #include "glusterfs3.h"  #include "portmap-xdr.h" -#include "glusterd1-xdr.h"  #include "xdr-generic.h"  #include "glusterfsd.h" +#include "glusterfsd-mem-types.h"  #include "rpcsvc.h" +#include "cli1-xdr.h"  static char is_mgmt_rpc_reconnect; @@ -253,28 +255,83 @@ glusterfs_translator_info_response_send (rpcsvc_request_t *req, int ret,  }  int +glusterfs_handle_translator_info_get_cont (gfd_vol_top_priv_t *priv) +{ +        int                     ret = -1; +        xlator_t                *any = NULL; +        xlator_t                *xlator = NULL; +        glusterfs_graph_t       *active = NULL; +        glusterfs_ctx_t         *ctx = NULL; +        char                    msg[2048] = {0,}; +        dict_t                  *output = NULL; +        dict_t                  *dict = NULL; + +        GF_ASSERT (priv); + +        dict = dict_new (); +        ret = dict_unserialize (priv->xlator_req.input.input_val, +                                priv->xlator_req.input.input_len, &dict); +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to unserialize dict"); +                goto cont; +        } +        ret = dict_set_double (dict, "time", priv->time); +        if (ret) +                goto cont; +        ret = dict_set_double (dict, "throughput", priv->throughput); +        if (ret) +                goto cont; + +cont: +        ctx = glusterfs_ctx_get (); +        GF_ASSERT (ctx); +        active = ctx->active; +        any = active->first; + +        xlator = xlator_search_by_name (any, priv->xlator_req.name); +        if (!xlator) { +                snprintf (msg, sizeof (msg), "xlator %s is not loaded", +                          priv->xlator_req.name); +                goto out; +        } + +        output = dict_new (); +        ret = xlator->notify (xlator, GF_EVENT_TRANSLATOR_INFO, dict, output); + +out: +        ret = glusterfs_translator_info_response_send (priv->req, ret, +                                                       msg, output); + +        if (priv->xlator_req.name) +                free (priv->xlator_req.name); +        if (priv->xlator_req.input.input_val) +                free (priv->xlator_req.input.input_val); +        if (dict) +                dict_unref (dict); +        if (output) +                dict_unref (output); +        GF_FREE (priv); + +        return ret; +} + +int  glusterfs_handle_translator_info_get (rpcsvc_request_t *req)  {          int32_t                  ret     = -1;          gd1_mgmt_brick_op_req    xlator_req = {0,};          dict_t                   *dict    = NULL; -        xlator_t                 *xlator = NULL; -        xlator_t                 *any = NULL; -        dict_t                   *output = NULL; -        char                     msg[2048] = {0}; -        glusterfs_ctx_t          *ctx = NULL; -        glusterfs_graph_t        *active = NULL;          xlator_t                 *this = NULL; +        gf1_cli_top_op            top_op = 0; +        int32_t                  blk_size = 0; +        int32_t                  blk_count = 0; +        gfd_vol_top_priv_t       *priv = NULL; +        pthread_t                tid = -1;          GF_ASSERT (req);          this = THIS;          GF_ASSERT (this); -        ctx = glusterfs_ctx_get (); -        GF_ASSERT (ctx); - -        active = ctx->active; -        any = active->first;          if (!xdr_to_generic (req->msg[0], &xlator_req,                               (xdrproc_t)xdr_gd1_mgmt_brick_op_req)) {                  //failed to decode msg; @@ -293,29 +350,270 @@ glusterfs_handle_translator_info_get (rpcsvc_request_t *req)                  goto out;          } -        xlator = xlator_search_by_name (any, xlator_req.name); -        if (!xlator) { -                snprintf (msg, sizeof (msg), "xlator %s is not loaded", -                          xlator_req.name); -                ret = -1; +        priv = GF_MALLOC (sizeof (gfd_vol_top_priv_t), gfd_mt_vol_top_priv_t); +        if (!priv) { +                gf_log ("glusterd", GF_LOG_ERROR, "failed to allocate memory");                  goto out;          } - -        output = dict_new (); -        ret = xlator->notify (xlator, GF_EVENT_TRANSLATOR_INFO, dict, output); +        priv->xlator_req = xlator_req; +        priv->req = req; + +        ret = dict_get_int32 (dict, "top-op", (int32_t *)&top_op); +        if ((!ret) && (GF_CLI_TOP_READ_PERF == top_op || +            GF_CLI_TOP_WRITE_PERF == top_op)) { +                ret = dict_get_int32 (dict, "blk-size", &blk_size); +                if (ret) +                        goto cont; +                ret = dict_get_int32 (dict, "blk-cnt", &blk_count); +                if (ret) +                        goto cont; +                priv->blk_size = blk_size; +                priv->blk_count = blk_count; +                if (GF_CLI_TOP_READ_PERF == top_op) { +                        ret = pthread_create (&tid, NULL, +                                              glusterfs_volume_top_read_perf, +                                              priv); +                } else if ( GF_CLI_TOP_WRITE_PERF == top_op) { +                        ret = pthread_create (&tid, NULL, +                                              glusterfs_volume_top_write_perf, +                                              priv); +                } +                if (ret) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "Thread create failed"); +                        goto cont; +                } +                gf_log ("glusterd", GF_LOG_DEBUG, "Created new thread with " +                        "tid %u", (unsigned int)tid); +                goto out; +        } +cont: +        priv->throughput = 0; +        priv->time = 0; +        ret = glusterfs_handle_translator_info_get_cont (priv);  out: -        ret = glusterfs_translator_info_response_send (req, ret, msg, output);          if (dict)                  dict_unref (dict); -        if (xlator_req.input.input_val) -                free (xlator_req.input.input_val); // malloced by xdr -        if (output) -                dict_unref (output); -        if (xlator_req.name) -                free (xlator_req.name); //malloced by xdr          return ret;  } +void * +glusterfs_volume_top_write_perf (void *args) +{ +        int32_t                 fd = -1; +        int32_t                 input_fd = -1; +        char                    export_path[PATH_MAX]; +        char                    *buf = NULL; +        int32_t                 blk_size = 0; +        int32_t                 blk_count = 0; +        int32_t                 iter = 0; +        int32_t                 ret = -1; +        int64_t                 total_blks = 0; +        struct timeval          begin, end = {0,}; +        double                  throughput = 0; +        double                  time = 0; +        gfd_vol_top_priv_t      *priv = NULL; + +        GF_ASSERT (args); +        priv = (gfd_vol_top_priv_t *)args; + +        blk_size = priv->blk_size; +        blk_count = priv->blk_count; + +        snprintf (export_path, sizeof (export_path), "%s/%s", +                  priv->xlator_req.name, ".gf-tmp-stats-perf"); + +        fd = open (export_path, O_CREAT|O_RDWR, S_IRWXU); +        if (-1 == fd) { +                ret = -1; +                gf_log ("glusterd", GF_LOG_ERROR, "Could not open tmp file"); +                goto out; +        } + +        buf = GF_MALLOC (blk_size * sizeof(*buf), gf_common_mt_char); +        if (!buf) { +                ret = -1; +                goto out; +        } + +        input_fd = open ("/dev/urandom", O_RDONLY); +        if (-1 == input_fd) { +                ret = -1; +                gf_log ("glusterd",GF_LOG_ERROR, "Unable to open input file"); +                goto out; +        } + +        gettimeofday (&begin, NULL); +        for (iter = 0; iter < blk_count; iter++) { +                ret = read (input_fd, buf, blk_size); +                if (ret != blk_size) { +                        ret = -1; +                        goto out; +                } +                ret = write (fd, buf, blk_size); +                if (ret != blk_size) { +                        ret = -1; +                        goto out; +                } +                total_blks += ret; +        } +        ret = 0; +        if (total_blks != (blk_size * blk_count)) { +                gf_log ("glusterd", GF_LOG_WARNING, "Error in write"); +                ret = -1; +                goto out; +        } + +        gettimeofday (&end, NULL); +        time = (end.tv_sec - begin.tv_sec) * 1e6 +                     + (end.tv_usec - begin.tv_usec); +        throughput = total_blks / time; +        gf_log ("glusterd", GF_LOG_INFO, "Throughput %.2f Mbps time %.2f secs " +                "bytes written %"PRId64, throughput, time, total_blks); + +out: +        priv->throughput = throughput; +        priv->time = time; + +        if (fd >= 0) +                close (fd); +        if (input_fd >= 0) +                close (input_fd); +        if (buf) +                GF_FREE (buf); +        unlink (export_path); + +        (void)glusterfs_handle_translator_info_get_cont (priv); + +        return NULL; +} + +void * +glusterfs_volume_top_read_perf (void *args) +{ +        int32_t                 fd = -1; +        int32_t                 input_fd = -1; +        int32_t                 output_fd = -1; +        char                    export_path[PATH_MAX]; +        char                    *buf = NULL; +        int32_t                 blk_size = 0; +        int32_t                 blk_count = 0; +        int32_t                 iter = 0; +        int32_t                 ret = -1; +        int64_t                 total_blks = 0; +        struct timeval          begin, end = {0,}; +        double                  throughput = 0; +        double                  time = 0; +        gfd_vol_top_priv_t      *priv = NULL; + +        GF_ASSERT (args); +        priv = (gfd_vol_top_priv_t *)args; + +        blk_size = priv->blk_size; +        blk_count = priv->blk_count; + +        snprintf (export_path, sizeof (export_path), "%s/%s", +                  priv->xlator_req.name, ".gf-tmp-stats-perf"); +        fd = open (export_path, O_CREAT|O_RDWR, S_IRWXU); +        if (-1 == fd) { +                ret = -1; +                gf_log ("glusterd", GF_LOG_ERROR, "Could not open tmp file"); +                goto out; +        } + +        buf = GF_MALLOC (blk_size * sizeof(*buf), gf_common_mt_char); +        if (!buf) { +                ret = -1; +                gf_log ("glusterd", GF_LOG_ERROR, "Could not allocate memory"); +                goto out; +        } + +        input_fd = open ("/dev/urandom", O_RDONLY); +        if (-1 == input_fd) { +                ret = -1; +                gf_log ("glusterd", GF_LOG_ERROR, "Could not open input file"); +                goto out; +        } + +        output_fd = open ("/dev/null", O_RDWR); +        if (-1 == output_fd) { +                ret = -1; +                gf_log ("glusterd", GF_LOG_ERROR, "Could not open output file"); +                goto out; +        } + +        for (iter = 0; iter < blk_count; iter++) { +                ret = read (input_fd, buf, blk_size); +                if (ret != blk_size) { +                        ret = -1; +                        goto out; +                } +                ret = write (fd, buf, blk_size); +                if (ret != blk_size) { +                        ret = -1; +                        goto out; +                } +        } + +        ret = fsync (fd); +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "could not flush cache"); +                goto out; +        } +        ret = lseek (fd, 0L, 0); +        if (ret != 0) { +                gf_log ("glusterd", GF_LOG_ERROR, +                        "could not seek back to start"); +                ret = -1; +                goto out; +        } +        gettimeofday (&begin, NULL); +        for (iter = 0; iter < blk_count; iter++) { +                ret = read (fd, buf, blk_size); +                if (ret != blk_size) { +                        ret = -1; +                        goto out; +                } +                ret = write (output_fd, buf, blk_size); +                if (ret != blk_size) { +                        ret = -1; +                        goto out; +                } +                total_blks += ret; +        } +        ret = 0; +        if ((blk_size * blk_count) != total_blks) { +                ret = -1; +                gf_log ("glusterd", GF_LOG_WARNING, "Error in write"); +                goto out; +        } + +        gettimeofday (&end, NULL); +        time = (end.tv_sec - begin.tv_sec) * 1e6 +               + (end.tv_usec - begin.tv_usec); +        throughput = total_blks / time; +        gf_log ("glusterd", GF_LOG_INFO, "Throughput %.2f Mbps time %.2f secs " +                "bytes read %"PRId64, throughput, time, total_blks); + +out: +        priv->throughput = throughput; +        priv->time = time; + +        if (fd >= 0) +                close (fd); +        if (input_fd >= 0) +                close (input_fd); +        if (output_fd >= 0) +                close (output_fd); +        if (buf) +                GF_FREE (buf); +        unlink (export_path); + +        (void)glusterfs_handle_translator_info_get_cont (priv); + +        return NULL; +} +  int  glusterfs_handle_rpc_msg (rpcsvc_request_t *req)  { diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h index 5106559c14c..0e68f7f0ea8 100644 --- a/glusterfsd/src/glusterfsd.h +++ b/glusterfsd/src/glusterfsd.h @@ -24,7 +24,8 @@  #define _CONFIG_H  #include "config.h"  #endif - +#include "rpcsvc.h" +#include "glusterd1-xdr.h"  #define DEFAULT_GLUSTERD_VOLFILE              CONFDIR "/glusterd.vol"  #define DEFAULT_CLIENT_VOLFILE                CONFDIR "/glusterfs.vol" @@ -81,9 +82,22 @@ enum argp_option_keys {          ARGP_USER_MAP_ROOT_KEY            = 156,  }; +struct _gfd_vol_top_priv_t { +        rpcsvc_request_t        *req; +        gd1_mgmt_brick_op_req   xlator_req; +        int32_t                 blk_count; +        int32_t                 blk_size; +        double                  throughput; +        double                  time; +        int32_t                 ret; +}; +typedef struct _gfd_vol_top_priv_t gfd_vol_top_priv_t; +  int glusterfs_mgmt_pmap_signout (glusterfs_ctx_t *ctx);  int glusterfs_mgmt_pmap_signin (glusterfs_ctx_t *ctx);  int glusterfs_volfile_fetch (glusterfs_ctx_t *ctx);  void cleanup_and_exit (int signum); +void *glusterfs_volume_top_read_perf (void *args); +void *glusterfs_volume_top_write_perf (void *args);  #endif /* __GLUSTERFSD_H__ */ diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 2b2a1e766df..c9d1c99a1e1 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -171,11 +171,6 @@ glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickin  {          int                     ret = -1;          gd1_mgmt_brick_op_req   *brick_req = NULL; -        gf1_cli_top_op          top_op = 0; -        double                  throughput = 0; -        double                  time = 0; -        int32_t                 blk_size = 0; -        int32_t                 blk_count = 0;          GF_ASSERT (op < GD_OP_MAX);          GF_ASSERT (op > GD_OP_NONE); @@ -206,46 +201,12 @@ glusterd_brick_op_build_payload (glusterd_op_t op, glusterd_brickinfo_t *brickin                  brick_req->op = GF_BRICK_XLATOR_INFO;                  brick_req->name = brickinfo->path; -                ret = dict_get_int32 (dict, "top-op", (int32_t*)&top_op); -                if (ret) -                        goto cont;  -                if (top_op == GF_CLI_TOP_READ_PERF || -                    top_op == GF_CLI_TOP_WRITE_PERF) { - -                        ret = dict_get_int32 (dict, "blk-size", &blk_size); -                        if (ret) { -                                goto cont; -                        } -                        ret = dict_get_int32 (dict, "blk-cnt", &blk_count); -                        if (ret) -                                goto out; -                        if (top_op == GF_CLI_TOP_READ_PERF) -                                 ret = glusterd_volume_stats_read_perf ( -                                        brickinfo->path, blk_size, blk_count,  -                                        &throughput, &time); -                        else if (!ret && top_op == GF_CLI_TOP_WRITE_PERF) -                                ret = glusterd_volume_stats_write_perf ( -                                        brickinfo->path, blk_size, blk_count,  -                                        &throughput, &time); - -                        if (ret)  -                                goto out; - -                        ret = dict_set_double (dict, "throughput", -                                              throughput); -                        if (ret) -                                goto out; -                        ret = dict_set_double (dict, "time", time); -                        if (ret) -                                goto out; -                }                  break;          default:                  goto out;          break;          } -cont:          ret = dict_allocate_and_serialize (dict, &brick_req->input.input_val,                                             (size_t*)&brick_req->input.input_len);          if (ret) @@ -3415,159 +3376,3 @@ glusterd_op_sm_init ()          return 0;  } -int32_t -glusterd_volume_stats_write_perf (char *brick_path, int32_t blk_size, -                int32_t blk_count, double *throughput, double *time) -{ -        int32_t          fd = -1; -        int32_t          input_fd = -1; -        char             export_path[1024]; -        char            *buf = NULL; -        int32_t          iter = 0; -        int32_t          ret = -1; -        int64_t          total_blks = 0; -        struct timeval   begin, end = {0, }; - - -        GF_VALIDATE_OR_GOTO ("stripe", brick_path, out); - -        snprintf (export_path, sizeof(export_path), "%s/%s", -                 brick_path, ".gf_tmp_stats_perf"); -        fd = open (export_path, O_CREAT|O_RDWR, S_IRWXU); -        if (fd == -1) -                return errno; -        buf = GF_MALLOC (blk_size * sizeof(*buf), gf_common_mt_char); - -        if (!buf) -                return ret; - -        input_fd = open("/dev/zero", O_RDONLY); -        if (input_fd == -1) -                return errno; -        gettimeofday (&begin, NULL); -        for (iter = 0; iter < blk_count; iter++) { -                ret = read (input_fd, buf, blk_size); -                if (ret != blk_size) { -                        ret = -1; -                        goto out; -                } -                ret = write (fd, buf, blk_size); -                if (ret != blk_size) { -                        ret = -1; -                        goto out; -                } -                total_blks += ret; -        } -        ret = 0; -        if (total_blks != (blk_size * blk_count)) { -                gf_log ("glusterd", GF_LOG_WARNING, "Errors in write"); -                ret = -1; -                goto out; -        } - -        gettimeofday (&end, NULL); -        *time = (end.tv_sec - begin.tv_sec) * 1e6 -                + (end.tv_usec - begin.tv_usec); - -        *throughput = total_blks / *time; -        gf_log ("glusterd", GF_LOG_INFO, "Throughput %.2f MBps time %.2f secs bytes " -                "written %"PRId64, *throughput, *time / 1e6, total_blks); -out: -        if (fd >= 0) -                close (fd); -        if (input_fd >= 0) -                close (input_fd); -        if (buf) -                GF_FREE (buf); -        unlink (export_path); -        return ret; -} - -int32_t -glusterd_volume_stats_read_perf (char *brick_path, int32_t blk_size, -                int32_t blk_count, double *throughput, double *time) -{ -        int32_t          fd = -1; -        int32_t          output_fd = -1; -        int32_t          input_fd = -1; -        char             export_path[1024]; -        char            *buf = NULL; -        int32_t          iter = 0; -        int32_t          ret = -1; -        int64_t          total_blks = 0; -        struct timeval   begin, end = {0, }; - - -        GF_VALIDATE_OR_GOTO ("glusterd", brick_path, out); - -        snprintf (export_path, sizeof(export_path), "%s/%s", -                 brick_path, ".gf_tmp_stats_perf"); -        fd = open (export_path, O_CREAT|O_RDWR, S_IRWXU); -        if (fd == -1) -                return errno; -        buf = GF_MALLOC (blk_size * sizeof(*buf), gf_common_mt_char); - -        if (!buf) -                return ret; - -        output_fd = open("/dev/null", O_RDWR); -        if (output_fd == -1) -                return errno; -        input_fd = open("/dev/zero", O_RDONLY); -        if (input_fd == -1) -                return errno; -        for (iter = 0; iter < blk_count; iter++) { -                ret = read (input_fd, buf, blk_size); -                if (ret != blk_size) { -                        ret = -1; -                        goto out; -                } -                ret = write (fd, buf, blk_size); -                if (ret != blk_size) { -                        ret = -1; -                        goto out; -                } -        } - - -        lseek (fd, 0L, 0); -        gettimeofday (&begin, NULL); -        for (iter = 0; iter < blk_count; iter++) { -                ret = read (fd, buf, blk_size); -                if (ret != blk_size) { -                        ret = -1; -                        goto out; -                } -                ret = write (output_fd, buf, blk_size); -                if (ret != blk_size) { -                        ret = -1; -                        goto out; -                } -                total_blks += ret; -        } -        ret = 0; -        if (total_blks != (blk_size * blk_count)) { -                gf_log ("glusterd", GF_LOG_WARNING, "Errors in write"); -                ret = -1; -                goto out; -        } - -        gettimeofday (&end, NULL); -        *time = (end.tv_sec - begin.tv_sec) * 1e6 -                + (end.tv_usec - begin.tv_usec); - -        *throughput = total_blks / *time; -        gf_log ("glusterd", GF_LOG_INFO, "Throughput %.2f MBps time %.2f secs bytes " -                "read %"PRId64, *throughput, *time / 1e6, total_blks); -out: -        if (fd >= 0) -                close (fd); -        if (input_fd >= 0) -                close (input_fd); -        if (output_fd >= 0) -                close (output_fd); -        if (buf) -                GF_FREE (buf); -        unlink (export_path); -        return ret; -}  | 
