From f208d7148fefd55b4073bda978816d71831ffefa Mon Sep 17 00:00:00 2001 From: shishir gowda Date: Wed, 16 Mar 2011 03:34:53 +0000 Subject: TOP: io-stats related changes Signed-off-by: shishir gowda Signed-off-by: Vijay Bellur BUG: 2516 (Implement gluster volume top command) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2516 --- xlators/debug/io-stats/src/io-stats-mem-types.h | 2 + xlators/debug/io-stats/src/io-stats.c | 678 +++++++++++++++++++++++- 2 files changed, 671 insertions(+), 9 deletions(-) diff --git a/xlators/debug/io-stats/src/io-stats-mem-types.h b/xlators/debug/io-stats/src/io-stats-mem-types.h index 0c711029a..59f88ea32 100644 --- a/xlators/debug/io-stats/src/io-stats-mem-types.h +++ b/xlators/debug/io-stats/src/io-stats-mem-types.h @@ -27,6 +27,8 @@ enum gf_io_stats_mem_types_ { gf_io_stats_mt_ios_conf = gf_common_mt_end + 1, gf_io_stats_mt_ios_fd, + gf_io_stats_mt_ios_stat, + gf_io_stats_mt_ios_stat_list, gf_io_stats_mt_end }; #endif diff --git a/xlators/debug/io-stats/src/io-stats.c b/xlators/debug/io-stats/src/io-stats.c index 15f2007d2..e7435d072 100644 --- a/xlators/debug/io-stats/src/io-stats.c +++ b/xlators/debug/io-stats/src/io-stats.c @@ -46,6 +46,53 @@ #include #include "defaults.h" +#define MAX_LIST_MEMBERS 100 + +typedef enum { + IOS_STATS_TYPE_NONE, + IOS_STATS_TYPE_OPEN, + IOS_STATS_TYPE_READ, + IOS_STATS_TYPE_WRITE, + IOS_STATS_TYPE_OPENDIR, + IOS_STATS_TYPE_READDIRP, + IOS_STATS_TYPE_READ_THROUGHPUT, + IOS_STATS_TYPE_WRITE_THROUGHPUT, + IOS_STATS_TYPE_MAX, +}ios_stats_type_t; + +typedef enum { + IOS_STATS_THRU_READ, + IOS_STATS_THRU_WRITE, + IOS_STATS_THRU_MAX, +}ios_stats_thru_t; + +struct ios_stat_lat { + struct timeval time; + double throughput; +}; + +struct ios_stat { + gf_lock_t lock; + uuid_t gfid; + char *filename; + uint64_t counters [IOS_STATS_TYPE_MAX]; + struct ios_stat_lat thru_counters [IOS_STATS_THRU_MAX]; + int refcnt; +}; + +struct ios_stat_list { + struct list_head list; + struct ios_stat *iosstat; + double value; +}; + +struct ios_stat_head { + gf_lock_t lock; + double min_cnt; + uint64_t members; + struct ios_stat_list *iosstats; +}; + struct ios_lat { double min; double max; @@ -60,6 +107,8 @@ struct ios_global_stats { uint64_t fop_hits[GF_FOP_MAXVALUE]; struct timeval started_at; struct ios_lat latency[GF_FOP_MAXVALUE]; + uint64_t nr_opens; + uint64_t max_nr_opens; }; @@ -70,6 +119,8 @@ struct ios_conf { struct ios_global_stats incremental; gf_boolean_t dump_fd_stats; int measure_latency; + struct ios_stat_head list[IOS_STATS_TYPE_MAX]; + struct ios_stat_head thru_list[IOS_STATS_THRU_MAX]; }; @@ -199,6 +250,53 @@ struct ios_local { } while (0) +#define BUMP_STATS(iosstat, type) \ + do { \ + struct ios_conf *conf = NULL; \ + \ + conf = this->private; \ + \ + LOCK(&iosstat->lock); \ + { \ + iosstat->counters[type]++; \ + ios_stat_add_to_list (&conf->list[type], \ + iosstat->counters[type], iosstat); \ + } \ + UNLOCK (&iosstat->lock); \ + \ + } while (0) + + +#define BUMP_THROUGHPUT(iosstat, type) \ + do { \ + struct ios_conf *conf = NULL; \ + double elapsed; \ + struct timeval *begin, *end; \ + double throughput; \ + \ + begin = &frame->begin; \ + end = &frame->end; \ + \ + elapsed = (end->tv_sec - begin->tv_sec) * 1e6 \ + + (end->tv_usec - begin->tv_usec); \ + throughput = op_ret / elapsed; \ + \ + conf = this->private; \ + LOCK(&iosstat->lock); \ + { \ + if (iosstat->thru_counters[type].throughput \ + <= throughput) { \ + iosstat->thru_counters[type].throughput = \ + throughput; \ + gettimeofday (&iosstat-> \ + thru_counters[type].time, NULL); \ + ios_stat_add_to_list (&conf->thru_list[type], \ + throughput, iosstat); \ + } \ + } \ + UNLOCK (&iosstat->lock); \ + } while (0) + int ios_fd_ctx_get (fd_t *fd, xlator_t *this, struct ios_fd **iosfd) { @@ -228,6 +326,172 @@ ios_fd_ctx_set (fd_t *fd, xlator_t *this, struct ios_fd *iosfd) return ret; } +int +ios_stat_ref (struct ios_stat *iosstat) +{ + iosstat->refcnt++; + return iosstat->refcnt; +} + +int +ios_stat_unref (struct ios_stat *iosstat) +{ + int cleanup = 0; + LOCK (&iosstat->lock); + { + iosstat->refcnt--; + if (iosstat->refcnt <= 0) { + if (iosstat->filename) { + GF_FREE (iosstat->filename); + iosstat->filename = NULL; + } + cleanup = 1; + } + } + UNLOCK (&iosstat->lock); + + if (cleanup) { + GF_FREE (iosstat); + iosstat = NULL; + } + + return 0; +} + +int +ios_inode_ctx_set (inode_t *inode, xlator_t *this, struct ios_stat *iosstat) +{ + uint64_t iosstat64 = 0; + int ret = 0; + + ios_stat_ref (iosstat); + iosstat64 = (unsigned long )iosstat; + ret = inode_ctx_put (inode, this, iosstat64); + return ret; +} + +int +ios_inode_ctx_get (inode_t *inode, xlator_t *this, struct ios_stat **iosstat) +{ + uint64_t iosstat64 = 0; + unsigned long iosstatlong = 0; + int ret = 0; + + ret = inode_ctx_get (inode, this, &iosstat64); + iosstatlong = iosstat64; + if (ret != -1) + *iosstat = (void *) iosstatlong; + + return ret; + +} + +int +ios_stat_add_to_list (struct ios_stat_head *list_head, uint64_t value, + struct ios_stat *iosstat) +{ + struct ios_stat_list *new = NULL; + struct ios_stat_list *entry = NULL; + struct ios_stat_list *t = NULL; + struct ios_stat_list *list_entry = NULL; + struct ios_stat_list *tmp = NULL; + struct ios_stat_list *last = NULL; + struct ios_stat *stat = NULL; + int cnt = 0; + int found = 0; + int reposition = 0; + double min_count = 0; + + LOCK (&list_head->lock); + { + + if (list_head->min_cnt == 0) + list_head->min_cnt = value; + if ((list_head->members == MAX_LIST_MEMBERS) && + (list_head->min_cnt > value)) + goto out; + + list_for_each_entry_safe (entry, t, + &list_head->iosstats->list, list) { + cnt++; + if (cnt == list_head->members) + last = entry; + + if (!uuid_compare (iosstat->gfid, + entry->iosstat->gfid)) { + list_entry = entry; + found = cnt; + entry->value = value; + if (!reposition) { + if (cnt == list_head->members) + list_head->min_cnt = value; + goto out; + } + break; + } else if (entry->value <= value && !reposition) { + reposition = cnt; + tmp = entry; + if (cnt == list_head->members - 1) + min_count = entry->value; + } + } + if (found) { + list_del (&list_entry->list); + list_add_tail (&list_entry->list, &tmp->list); + if (min_count) + list_head->min_cnt = min_count; + goto out; + } else if (list_head->members == MAX_LIST_MEMBERS && reposition) { + new = GF_CALLOC (1, sizeof (*new), + gf_io_stats_mt_ios_stat_list); + new->iosstat = iosstat; + new->value = value; + ios_stat_ref (iosstat); + list_add_tail (&new->list, &tmp->list); + stat = last->iosstat; + last->iosstat = NULL; + ios_stat_unref (stat); + list_del (&last->list); + GF_FREE (last); + if (reposition == MAX_LIST_MEMBERS) + list_head->min_cnt = value; + else if (min_count) { + gf_log ("shishir", 1, "I am here"); + list_head->min_cnt = min_count; + } + } else if (list_head->members < MAX_LIST_MEMBERS) { + new = GF_CALLOC (1, sizeof (*new), + gf_io_stats_mt_ios_stat_list); + new->iosstat = iosstat; + new->value = value; + ios_stat_ref (iosstat); + if (reposition) { + list_add_tail (&new->list, &tmp->list); + } else { + list_add_tail (&new->list, &entry->list); + } + list_head->members++; + if (list_head->min_cnt > value) + list_head->min_cnt = value; + } + } +out: + UNLOCK (&list_head->lock); + return 0; +} + +inline int +ios_stats_cleanup (xlator_t *this, inode_t *inode) +{ + + struct ios_stat *iosstat = NULL; + + ios_inode_ctx_get (inode, this, &iosstat); + if (iosstat) { + ios_stat_unref (iosstat); + } + return 0; +} #define ios_log(this, logfp, fmt ...) \ do { \ @@ -238,11 +502,60 @@ 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 +ios_dump_file_stats (struct ios_stat_head *list_head, xlator_t *this, FILE* logfp) +{ + struct ios_stat_list *entry = NULL; + + LOCK (&list_head->lock); + { + list_for_each_entry (entry, &list_head->iosstats->list, list) { + ios_log (this, logfp, "%.0f\t\t%s", + entry->value, entry->iosstat->filename); + } + } + UNLOCK (&list_head->lock); + return 0; +} + +int +ios_dump_throughput_stats (struct ios_stat_head *list_head, xlator_t *this, + FILE* logfp, ios_stats_type_t type) +{ + struct ios_stat_list *entry = NULL; + struct timeval time = {0, }; + struct tm *tm = NULL; + char timestr[256] = {0, }; + + LOCK (&list_head->lock); + { + list_for_each_entry (entry, &list_head->iosstats->list, list) { + time = entry->iosstat->thru_counters[type].time; + tm = localtime (&time.tv_sec); + if (!tm) + continue; + strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm); + snprintf (timestr + strlen (timestr), 256 - strlen (timestr), + ".%"GF_PRI_SUSECONDS, time.tv_usec); + + ios_log (this, logfp, "%.2f\t\t%s \t\t- %s", + entry->value, + entry->iosstat->filename, timestr); + } + } + UNLOCK (&list_head->lock); + return 0; +} + int io_stats_dump_global_to_logfp (xlator_t *this, struct ios_global_stats *stats, struct timeval *now, int interval, FILE* logfp) { int i = 0; + struct ios_stat_head *list_head = NULL; + struct ios_conf *conf = NULL; + + conf = this->private; if (interval == -1) ios_log (this, logfp, "=== Cumulative stats ==="); @@ -280,6 +593,50 @@ io_stats_dump_global_to_logfp (xlator_t *this, struct ios_global_stats *stats, stats->latency[i].max); } + if (interval == -1) { + LOCK (&conf->lock); + { + ios_log (this, logfp, "Current open fd's: %"PRId64 + " Max open fd's: %"PRId64,conf->cumulative.nr_opens, + conf->cumulative.max_nr_opens); + } + UNLOCK (&conf->lock); + ios_log (this, logfp, "==========Open file stats========"); + ios_log (this, logfp, "open call count:\t\t\tfile name"); + list_head = &conf->list[IOS_STATS_TYPE_OPEN]; + ios_dump_file_stats (list_head, this, logfp); + + + ios_log (this, logfp, "==========Read file stats========"); + ios_log (this, logfp, "read call count:\t\t\tfilename"); + list_head = &conf->list[IOS_STATS_TYPE_READ]; + ios_dump_file_stats (list_head, this, logfp); + + ios_log (this, logfp, "==========Write file stats========"); + ios_log (this, logfp, "write call count:\t\t\tfilename"); + list_head = &conf->list[IOS_STATS_TYPE_WRITE]; + ios_dump_file_stats (list_head, this, logfp); + + ios_log (this, logfp, "==========Directory open stats========"); + ios_log (this, logfp, "Opendir count:\t\t\tdirectory name"); + list_head = &conf->list[IOS_STATS_TYPE_OPENDIR]; + ios_dump_file_stats (list_head, this, logfp); + + ios_log (this, logfp, "==========Directory readdirp stats========"); + ios_log (this, logfp, "readdirp count:\t\t\tdirectory name"); + list_head = &conf->list[IOS_STATS_TYPE_READDIRP]; + ios_dump_file_stats (list_head, this, logfp); + + ios_log (this, logfp, "==========Read throughput file stats========"); + ios_log (this, logfp, "read throughput(MBps):\t\t\tfilename"); + list_head = &conf->thru_list[IOS_STATS_THRU_READ]; + ios_dump_throughput_stats(list_head, this, logfp, IOS_STATS_THRU_READ); + + ios_log (this, logfp, "==========Write throughput file stats========"); + ios_log (this, logfp, "write througput (MBps):\t\t\tfilename"); + list_head = &conf->thru_list[IOS_STATS_THRU_WRITE]; + ios_dump_throughput_stats (list_head, this, logfp, IOS_STATS_THRU_WRITE); + } return 0; } @@ -421,6 +778,8 @@ io_stats_dump_global (xlator_t *this, struct ios_global_stats *stats, GF_ASSERT (stats); GF_ASSERT (this); + + switch (args->type) { case IOS_DUMP_TYPE_FILE: ret = io_stats_dump_global_to_logfp (this, stats, now, @@ -608,6 +967,100 @@ update_ios_latency (struct ios_conf *conf, call_frame_t *frame, return 0; } +int32_t +io_stats_dump_stats_to_dict (xlator_t *this, dict_t *resp, + ios_stats_type_t flags, int32_t list_cnt) +{ + struct ios_conf *conf = NULL; + int cnt = -1; + char key[256]; + struct ios_stat_head *list_head = NULL; + struct ios_stat_list *entry = NULL; + int ret = -1; + ios_stats_thru_t index = IOS_STATS_THRU_MAX; + + conf = this->private; + + switch (flags) { + case IOS_STATS_TYPE_OPEN: + list_head = &conf->list[IOS_STATS_TYPE_OPEN]; + LOCK (&conf->lock); + { + ret = dict_set_uint64 (resp, "current-open", + conf->cumulative.nr_opens); + if (ret) + goto out; + ret = dict_set_uint64 (resp, "max-open", + conf->cumulative.max_nr_opens); + if (ret) + goto out; + } + UNLOCK (&conf->lock); + + break; + case IOS_STATS_TYPE_READ: + list_head = &conf->list[IOS_STATS_TYPE_READ]; + break; + case IOS_STATS_TYPE_WRITE: + list_head = &conf->list[IOS_STATS_TYPE_WRITE]; + break; + case IOS_STATS_TYPE_OPENDIR: + list_head = &conf->list[IOS_STATS_TYPE_OPENDIR]; + break; + case IOS_STATS_TYPE_READDIRP: + list_head = &conf->list[IOS_STATS_TYPE_READDIRP]; + break; + case IOS_STATS_TYPE_READ_THROUGHPUT: + list_head = &conf->thru_list[IOS_STATS_THRU_READ]; + index = IOS_STATS_THRU_READ; + break; + case IOS_STATS_TYPE_WRITE_THROUGHPUT: + list_head = &conf->thru_list[IOS_STATS_THRU_WRITE]; + index = IOS_STATS_THRU_WRITE; + break; + + default: + goto out; + } + ret = dict_set_int32 (resp, "top-op", flags); + LOCK (&list_head->lock); + { + list_for_each_entry (entry, &list_head->iosstats->list, list) { + + cnt++; + snprintf (key, 256, "%s-%d", "filename", cnt); + ret = dict_set_str (resp, key, entry->iosstat->filename); + if (ret) + goto out; + snprintf (key, 256, "%s-%d", "value",cnt); + ret = dict_set_uint64 (resp, key, entry->value); + if (ret) + goto out; + if (index != IOS_STATS_THRU_MAX) { + snprintf (key, 256, "%s-%d", "time-sec", cnt); + gf_log ("shishir", 1, "%s %ld",key,entry->iosstat->thru_counters[index].time.tv_sec); + ret = dict_set_int32 (resp, key, + entry->iosstat->thru_counters[index].time.tv_sec); + if (ret) + goto out; + snprintf (key, 256, "%s-%d", "time-usec", cnt); + gf_log ("shishir", 1, "%s %ld",key,entry->iosstat->thru_counters[index].time.tv_usec); + ret = dict_set_int32 (resp, key, + entry->iosstat->thru_counters[index].time.tv_usec); + if (ret) + goto out; + } + if (cnt == list_cnt) + break; + + } + } + UNLOCK (&list_head->lock); + + ret = dict_set_int32 (resp, "members", cnt); + out: + return ret; +} int io_stats_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, fd_t *fd, @@ -616,6 +1069,10 @@ io_stats_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, { struct ios_fd *iosfd = NULL; char *path = NULL; + struct ios_stat *iosstat = NULL; + struct ios_conf *conf = NULL; + + conf = this->private; path = frame->local; frame->local = NULL; @@ -638,6 +1095,23 @@ io_stats_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, gettimeofday (&iosfd->opened_at, NULL); ios_fd_ctx_set (fd, this, iosfd); + LOCK (&conf->lock); + { + conf->cumulative.nr_opens++; + if (conf->cumulative.nr_opens > conf->cumulative.max_nr_opens) + conf->cumulative.max_nr_opens = conf->cumulative.nr_opens; + } + UNLOCK (&conf->lock); + + iosstat = GF_CALLOC (1, sizeof (*iosstat), gf_io_stats_mt_ios_stat); + if (!iosstat) { + GF_FREE (path); + goto unwind; + } + iosstat->filename = gf_strdup (path); + uuid_copy (iosstat->gfid, buf->ia_gfid); + LOCK_INIT (&iosstat->lock); + ios_inode_ctx_set (fd->inode, this, iosstat); unwind: END_FOP_LATENCY (frame, CREATE); @@ -653,7 +1127,10 @@ io_stats_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, { struct ios_fd *iosfd = NULL; char *path = NULL; + struct ios_stat *iosstat = NULL; + struct ios_conf *conf = NULL; + conf = this->private; path = frame->local; frame->local = NULL; @@ -676,10 +1153,26 @@ io_stats_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, ios_fd_ctx_set (fd, this, iosfd); + ios_inode_ctx_get (fd->inode, this, &iosstat); + + LOCK (&conf->lock); + { + conf->cumulative.nr_opens++; + if (conf->cumulative.nr_opens > conf->cumulative.max_nr_opens) + conf->cumulative.max_nr_opens = conf->cumulative.nr_opens; + } + UNLOCK (&conf->lock); + + if (iosstat) { + BUMP_STATS (iosstat, IOS_STATS_TYPE_OPEN); + iosstat = NULL; + } unwind: END_FOP_LATENCY (frame, OPEN); + STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd); return 0; + } @@ -701,6 +1194,7 @@ io_stats_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, { int len = 0; fd_t *fd = NULL; + struct ios_stat *iosstat = NULL; fd = frame->local; frame->local = NULL; @@ -711,9 +1205,18 @@ io_stats_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } END_FOP_LATENCY (frame, READ); + ios_inode_ctx_get (fd->inode, this, &iosstat); + + if (iosstat) { + BUMP_STATS (iosstat, IOS_STATS_TYPE_READ); + BUMP_THROUGHPUT (iosstat, IOS_STATS_THRU_READ); + iosstat = NULL; + } + STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, vector, count, buf, iobref); return 0; + } @@ -722,9 +1225,25 @@ io_stats_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf) { + struct ios_stat *iosstat = NULL; + inode_t *inode = NULL; + END_FOP_LATENCY (frame, WRITE); + if (frame->local){ + inode = frame->local; + frame->local = NULL; + ios_inode_ctx_get (inode, this, &iosstat); + if (iosstat) { + BUMP_STATS (iosstat, IOS_STATS_TYPE_WRITE); + BUMP_THROUGHPUT (iosstat, IOS_STATS_THRU_WRITE); + inode = NULL; + iosstat = NULL; + } + } + STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, prebuf, postbuf); return 0; + } @@ -734,7 +1253,20 @@ int io_stats_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, gf_dirent_t *buf) { + struct ios_stat *iosstat = NULL; + inode_t *inode = frame->local; + + frame->local = NULL; + END_FOP_LATENCY (frame, READDIRP); + + ios_inode_ctx_get (inode, this, &iosstat); + + if (iosstat) { + BUMP_STATS (iosstat, IOS_STATS_TYPE_READDIRP); + iosstat = NULL; + } + STACK_UNWIND_STRICT (readdirp, frame, op_ret, op_errno, buf); return 0; } @@ -777,10 +1309,19 @@ io_stats_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *preparent, struct iatt *postparent) { + inode_t *inode = NULL; + + if (frame->local) { + inode = frame->local; + frame->local = NULL; + ios_stats_cleanup (this, inode); + inode = NULL; + } END_FOP_LATENCY (frame, UNLINK); STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, preparent, postparent); return 0; + } @@ -854,7 +1395,22 @@ io_stats_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, inode_t *inode, struct iatt *buf, struct iatt *preparent, struct iatt *postparent) { + struct ios_stat *iosstat = NULL; + char *path = frame->local; + END_FOP_LATENCY (frame, MKDIR); + if (op_ret < 0) + goto unwind; + + iosstat = GF_CALLOC (1, sizeof (*iosstat), gf_io_stats_mt_ios_stat); + if (iosstat) { + LOCK_INIT (&iosstat->lock); + iosstat->filename = gf_strdup(path); + uuid_copy (iosstat->gfid, buf->ia_gfid); + ios_inode_ctx_set (inode, this, iosstat); + } + +unwind: STACK_UNWIND_STRICT (mkdir, frame, op_ret, op_errno, inode, buf, preparent, postparent); return 0; @@ -888,10 +1444,20 @@ int io_stats_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, fd_t *fd) { - if (op_ret >= 0) - ios_fd_ctx_set (fd, this, 0); + struct ios_stat *iosstat = NULL; + int ret = -1; END_FOP_LATENCY (frame, OPENDIR); + if (op_ret < 0) + goto unwind; + + ios_fd_ctx_set (fd, this, 0); + + ret = ios_inode_ctx_get (fd->inode, this, &iosstat); + if (!ret) + BUMP_STATS (iosstat, IOS_STATS_TYPE_OPENDIR); + +unwind: STACK_UNWIND_STRICT (opendir, frame, op_ret, op_errno, fd); return 0; } @@ -902,7 +1468,18 @@ io_stats_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *preparent, struct iatt *postparent) { + inode_t *inode = NULL; + END_FOP_LATENCY (frame, RMDIR); + + + if (frame->local) { + inode = frame->local; + frame->local = NULL; + ios_stats_cleanup (this, inode); + inode = NULL; + } + STACK_UNWIND_STRICT (rmdir, frame, op_ret, op_errno, preparent, postparent); return 0; @@ -1052,7 +1629,6 @@ io_stats_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, return 0; } - int io_stats_entrylk (call_frame_t *frame, xlator_t *this, const char *volume, loc_t *loc, const char *basename, @@ -1221,6 +1797,8 @@ io_stats_mkdir (call_frame_t *frame, xlator_t *this, { BUMP_FOP (MKDIR); + frame->local = gf_strdup (loc->path); + START_FOP_LATENCY (frame); STACK_WIND (frame, io_stats_mkdir_cbk, @@ -1253,6 +1831,7 @@ io_stats_rmdir (call_frame_t *frame, xlator_t *this, { BUMP_FOP (RMDIR); + frame->local = loc->inode; START_FOP_LATENCY (frame); STACK_WIND (frame, io_stats_rmdir_cbk, @@ -1411,7 +1990,8 @@ io_stats_writev (call_frame_t *frame, xlator_t *this, { int len = 0; - + if (fd->inode) + frame->local = fd->inode; len = iov_length (vector, count); BUMP_FOP (WRITE); @@ -1424,6 +2004,7 @@ io_stats_writev (call_frame_t *frame, xlator_t *this, FIRST_CHILD(this)->fops->writev, fd, vector, count, offset, iobref); return 0; + } @@ -1582,6 +2163,7 @@ int io_stats_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd) { + BUMP_FOP (OPENDIR); START_FOP_LATENCY (frame); @@ -1599,6 +2181,7 @@ io_stats_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, { BUMP_FOP (READDIRP); + frame->local = fd->inode; START_FOP_LATENCY (frame); STACK_WIND (frame, io_stats_readdirp_cbk, @@ -1728,9 +2311,18 @@ int io_stats_release (xlator_t *this, fd_t *fd) { struct ios_fd *iosfd = NULL; + struct ios_conf *conf = NULL; BUMP_FOP (RELEASE); + conf = this->private; + + LOCK (&conf->lock); + { + conf->cumulative.nr_opens--; + } + UNLOCK (&conf->lock); + ios_fd_ctx_get (fd, this, &iosfd); if (iosfd) { io_stats_dump_fd (this, iosfd); @@ -1840,6 +2432,7 @@ init (xlator_t *this) char *str = NULL; int ret = 0; char *log_str = NULL; + int i = 0; if (!this) return -1; @@ -1870,6 +2463,36 @@ init (xlator_t *this) gettimeofday (&conf->cumulative.started_at, NULL); gettimeofday (&conf->incremental.started_at, NULL); + for (i = 0; i list[i].iosstats = GF_CALLOC (1, + sizeof(conf->list[i].iosstats), + gf_io_stats_mt_ios_stat); + + if (!conf->list[i].iosstats) { + gf_log (this->name, GF_LOG_ERROR, + "Out of memory"); + return -1; + } + + INIT_LIST_HEAD(&conf->list[i].iosstats->list); + LOCK_INIT (&conf->list[i].lock); + } + + for (i = 0; i < IOS_STATS_THRU_MAX; i ++) { + conf->thru_list[i].iosstats = GF_CALLOC (1, + sizeof (*conf->thru_list[i].iosstats), + gf_io_stats_mt_ios_stat); + + if (!conf->thru_list[i].iosstats) { + gf_log (this->name, GF_LOG_ERROR, + "Out of memory"); + return -1; + } + + INIT_LIST_HEAD(&conf->thru_list[i].iosstats->list); + LOCK_INIT (&conf->thru_list[i].lock); + } + ret = dict_get_str (options, "dump-fd-stats", &str); if (ret == 0) { ret = gf_string2boolean (str, &conf->dump_fd_stats); @@ -1945,30 +2568,67 @@ validate_options (xlator_t *this, dict_t *options, char **op_errstr) ret = 0; 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; + dict_t *dict = NULL; + int32_t top_op = 0; + int32_t list_cnt = 0; + double throughput = 0; + double time = 0; va_list ap; + dict = data; 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, + ret = dict_get_int32 (dict, "top-op", &top_op); + if (!ret) { + ret = dict_get_int32 (dict, "list-cnt", &list_cnt); + if (!list_cnt) + list_cnt = 100; + if (top_op > IOS_STATS_TYPE_NONE && + top_op < IOS_STATS_TYPE_MAX) + ret = io_stats_dump_stats_to_dict (this, output, + top_op, list_cnt); + if (top_op == IOS_STATS_TYPE_READ_THROUGHPUT || + top_op == IOS_STATS_TYPE_WRITE_THROUGHPUT) { + ret = dict_get_double (dict, "throughput", + &throughput); + if (!ret) { + ret = dict_get_double (dict, "time", + &time); + if (ret) + goto out; + ret = dict_set_double (output, + "throughput", throughput); + if (ret) + goto out; + ret = dict_set_double (output, "time", + time); + if (ret) + goto out; + } + ret = 0; + + } + } else { + (void) ios_dump_args_init (&args, IOS_DUMP_TYPE_DICT, output); - ret = io_stats_dump (this, &args); + ret = io_stats_dump (this, &args); + } break; default: default_notify (this, event, data); break; } - +out: return ret; } @@ -2027,5 +2687,5 @@ struct volume_options options[] = { { .key = {"log-level"}, .type = GF_OPTION_TYPE_STR, }, - { .key = {NULL} }, + { .key = {NULL} }, }; -- cgit