diff options
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
| -rw-r--r-- | xlators/debug/io-stats/src/io-stats.c | 269 | 
2 files changed, 254 insertions, 16 deletions
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 97f31961a2e..820ba831a1d 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -343,6 +343,7 @@ typedef enum {          GF_EVENT_TRANSPORT_CONNECTED,          GF_EVENT_VOLFILE_MODIFIED,          GF_EVENT_GRAPH_NEW, +        GF_EVENT_TRANSLATOR_INFO,          GF_EVENT_MAXVAL,  } glusterfs_event_t; diff --git a/xlators/debug/io-stats/src/io-stats.c b/xlators/debug/io-stats/src/io-stats.c index fff16ede215..15f2007d234 100644 --- a/xlators/debug/io-stats/src/io-stats.c +++ b/xlators/debug/io-stats/src/io-stats.c @@ -43,6 +43,8 @@  #include "glusterfs.h"  #include "xlator.h"  #include "io-stats-mem-types.h" +#include <stdarg.h> +#include "defaults.h"  struct ios_lat {          double  min; @@ -80,6 +82,23 @@ struct ios_fd {          struct timeval  opened_at;  }; +typedef enum { +        IOS_DUMP_TYPE_NONE = 0, +        IOS_DUMP_TYPE_FILE = 1, +        IOS_DUMP_TYPE_DICT = 2, +        IOS_DUMP_TYPE_MAX  = 3 +} ios_dump_type_t; + +struct ios_dump_args { +        ios_dump_type_t type; +        union { +                FILE *logfp; +                dict_t *dict; +        } u; +}; + +typedef int (*block_dump_func) (xlator_t *, struct ios_dump_args*, +                                    int , int , uint64_t ) ;  struct ios_local {          struct timeval  wind_at; @@ -219,10 +238,9 @@ ios_fd_ctx_set (fd_t *fd, xlator_t *this, struct ios_fd *iosfd)                  gf_log (this->name, GF_LOG_NORMAL, fmt);        \          } while (0) -  int -io_stats_dump_global (xlator_t *this, struct ios_global_stats *stats, -                      struct timeval *now, int interval, FILE *logfp) +io_stats_dump_global_to_logfp (xlator_t *this, struct ios_global_stats *stats, +                               struct timeval *now, int interval, FILE* logfp)  {          int    i = 0; @@ -265,17 +283,200 @@ io_stats_dump_global (xlator_t *this, struct ios_global_stats *stats,          return 0;  } +int +io_stats_dump_global_to_dict (xlator_t *this, struct ios_global_stats *stats, +                              struct timeval *now, int interval, dict_t *dict) +{ +        int             ret = 0; +        char            key[256] = {0}; +        uint64_t        sec = 0; +        int             i = 0; +        uint64_t        count = 0; + +        GF_ASSERT (stats); +        GF_ASSERT (now); +        GF_ASSERT (dict); +        GF_ASSERT (this); + +        if (interval == -1) +                snprintf (key, sizeof (key), "cumulative"); +        else +                snprintf (key, sizeof (key), "interval"); +        ret = dict_set_int32 (dict, key, interval); +        if (ret) +                gf_log (this->name, GF_LOG_ERROR, "failed to set " +                        "interval %d", interval); + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%d-duration", interval); +        sec = (uint64_t) (now->tv_sec - stats->started_at.tv_sec); +        ret = dict_set_uint64 (dict, key, sec); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "failed to set " +                        "duration(%d) - %"PRId64, interval, sec); +                goto out; +        } + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%d-total-read", interval); +        ret = dict_set_uint64 (dict, key, stats->data_read); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "failed to set total " +                       "read(%d) - %"PRId64, interval, stats->data_read); +                goto out; +        } + +        memset (key, 0, sizeof (key)); +        snprintf (key, sizeof (key), "%d-total-write", interval); +        ret = dict_set_uint64 (dict, key, stats->data_written); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "failed to set total " +                        "write(%d) - %"PRId64, interval, stats->data_written); +                goto out; +        } +        for (i = 0; i < 32; i++) { +                if (stats->block_count_read[i]) { +                        memset (key, 0, sizeof (key)); +                        snprintf (key, sizeof (key), "%d-read-%d", interval, +                                  (1 << i)); +                        count = stats->block_count_read[i]; +                        ret = dict_set_uint64 (dict, key, count); +                        if (ret) { +                                gf_log (this->name, GF_LOG_ERROR, "failed to " +                                        "set read-%db+, with: %"PRId64, +                                        (1<<i), count); +                                goto out; +                        } +                } +        } + +        for (i = 0; i < 32; i++) { +                if (stats->block_count_write[i]) { +                        snprintf (key, sizeof (key), "%d-write-%d", interval, +                                  (1<<i)); +                        count = stats->block_count_write[i]; +                        ret = dict_set_uint64 (dict, key, count); +                        if (ret) { +                                gf_log (this->name, GF_LOG_ERROR, "failed to " +                                        "set write-%db+, with: %"PRId64, +                                        (1<<i), count); +                                goto out; +                        } +                } +        } + +        for (i = 0; i < GF_FOP_MAXVALUE; i++) { +                if (stats->fop_hits[i] == 0) +                        continue; +                snprintf (key, sizeof (key), "%d-%d-hits", interval, i); +                ret = dict_set_uint64 (dict, key, stats->fop_hits[i]); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "failed to " +                                "set %s-fop-hits: %"PRIu64, gf_fop_list[i], +                                stats->fop_hits[i]); +                        goto out; +                } + +                if (stats->latency[i].avg == 0) +                        continue; +                snprintf (key, sizeof (key), "%d-%d-avglatency", interval, i); +                ret = dict_set_double (dict, key, stats->latency[i].avg); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "failed to set %s " +                                "avglatency(%d) with %f", gf_fop_list[i], +                                interval, stats->latency[i].avg); +                        goto out; +                } +                snprintf (key, sizeof (key), "%d-%d-minlatency", interval, i); +                ret = dict_set_double (dict, key, stats->latency[i].min); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "failed to set %s " +                                "minlatency(%d) with %f", gf_fop_list[i], +                                interval, stats->latency[i].min); +                        goto out; +                } +                snprintf (key, sizeof (key), "%d-%d-maxlatency", interval, i); +                ret = dict_set_double (dict, key, stats->latency[i].max); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "failed to set %s " +                                "maxlatency(%d) with %f", gf_fop_list[i], +                                interval, stats->latency[i].max); +                        goto out; +                } +        } +out: +        gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret); +        return ret; +}  int -io_stats_dump (xlator_t *this, char *filename, inode_t *inode, -               const char *path) +io_stats_dump_global (xlator_t *this, struct ios_global_stats *stats, +                      struct timeval *now, int interval, +                      struct ios_dump_args *args) +{ +        int     ret = -1; + +        GF_ASSERT (args); +        GF_ASSERT (now); +        GF_ASSERT (stats); +        GF_ASSERT (this); + +        switch (args->type) { +        case IOS_DUMP_TYPE_FILE: +                ret = io_stats_dump_global_to_logfp (this, stats, now, +                                                     interval, args->u.logfp); +        break; +        case IOS_DUMP_TYPE_DICT: +                ret = io_stats_dump_global_to_dict (this, stats, now, +                                                    interval, args->u.dict); +        break; +        default: +                GF_ASSERT (0); +                ret = -1; +        break; +        } +        return ret; +} + +int +ios_dump_args_init (struct ios_dump_args *args, ios_dump_type_t type, +                    void *output) +{ +        int             ret = 0; + +        GF_ASSERT (args); +        GF_ASSERT (type > IOS_DUMP_TYPE_NONE && type < IOS_DUMP_TYPE_MAX); +        GF_ASSERT (output); + +        args->type = type; +        switch (args->type) { +        case IOS_DUMP_TYPE_FILE: +                args->u.logfp = output; +                break; +        case IOS_DUMP_TYPE_DICT: +                args->u.dict = output; +                break; +        default: +                GF_ASSERT (0); +                ret = -1; +        } + +        return ret; +} + +int +io_stats_dump (xlator_t *this, struct ios_dump_args *args)  {          struct ios_conf         *conf = NULL;          struct ios_global_stats  cumulative = {0, };          struct ios_global_stats  incremental = {0, };          int                      increment = 0;          struct timeval           now; -        FILE                    *logfp = NULL; + +        GF_ASSERT (this); +        GF_ASSERT (args); +        GF_ASSERT (args->type > IOS_DUMP_TYPE_NONE); +        GF_ASSERT (args->type < IOS_DUMP_TYPE_MAX);          conf = this->private; @@ -292,12 +493,9 @@ io_stats_dump (xlator_t *this, char *filename, inode_t *inode,          }          UNLOCK (&conf->lock); -        logfp = fopen (filename, "w+"); -        io_stats_dump_global (this, &cumulative, &now, -1, logfp); -        io_stats_dump_global (this, &incremental, &now, increment, logfp); +        io_stats_dump_global (this, &cumulative, &now, -1, args); +        io_stats_dump_global (this, &incremental, &now, increment, args); -        if (logfp) -                fclose (logfp);          return 0;  } @@ -1285,10 +1483,12 @@ conditional_dump (dict_t *dict, char *key, data_t *value, void *data)                  inode_t        *inode;                  const char     *path;          } *stub; -        xlator_t   *this = NULL; -        inode_t    *inode = NULL; -        const char *path = NULL; -        char       *filename = NULL; +        xlator_t             *this = NULL; +        inode_t              *inode = NULL; +        const char           *path = NULL; +        char                 *filename = NULL; +        FILE                 *logfp = NULL; +        struct ios_dump_args args = {0};          stub  = data;          this  = stub->this; @@ -1300,7 +1500,18 @@ conditional_dump (dict_t *dict, char *key, data_t *value, void *data)          memcpy (filename, data_to_str (value), value->len);          if (fnmatch ("*io*stat*dump", key, 0) == 0) { -                io_stats_dump (this, filename, inode, path); + +                logfp = fopen (filename, "w+"); +                GF_ASSERT (logfp); +                if (!logfp) { +                        gf_log (this->name, GF_LOG_ERROR, "failed to open %s " +                                "for writing", filename); +                        return; +                } +                (void) ios_dump_args_init (&args, IOS_DUMP_TYPE_FILE, +                                           logfp); +                io_stats_dump (this, &args); +                fclose (logfp);          }  } @@ -1735,6 +1946,32 @@ validate_options (xlator_t *this, dict_t *options, char **op_errstr)          return ret;  } +int +notify (xlator_t *this, int32_t event, void *data, ...) +{ +        int          ret = 0; +        struct ios_dump_args args = {0}; +        dict_t       *output = NULL; +        va_list ap; + +        va_start (ap, data); +        output = va_arg (ap, dict_t*); +        va_end (ap); +        switch (event) { +        case GF_EVENT_TRANSLATOR_INFO: +                (void) ios_dump_args_init (&args, IOS_DUMP_TYPE_DICT, +                                           output); +                ret = io_stats_dump (this, &args); +                break; +        default: +                default_notify (this, event, data); +                break; + +        } + +        return ret; +} +  struct xlator_fops fops = {          .stat        = io_stats_stat,          .readlink    = io_stats_readlink,  | 
