3604df
From 2faa19e96c5c1a249c0e6e8095e3e8eeaa3954a5 Mon Sep 17 00:00:00 2001
3604df
From: Poornima G <pgurusid@redhat.com>
3604df
Date: Wed, 17 Aug 2016 20:19:59 +0530
3604df
Subject: [PATCH 131/141] io-stats: Add stats for upcall notifications
3604df
3604df
With this patch, there will be additional entries seen in
3604df
the profile info:
3604df
3604df
UPCALL : Total number of upcall events that were sent from
3604df
         the brick(in brick profile), and number of upcall
3604df
         notifications recieved by client(in client profile)
3604df
3604df
Cache invalidation events:
3604df
-------------------------
3604df
CI_IATT : Number of upcalls that were cache invalidation and
3604df
         had one of the IATT_UPDATE_FLAGS set. This indicates
3604df
         that one of the iatt value was changed.
3604df
3604df
CI_XATTR : Number of upcalls that were cache invalidation, and
3604df
         had one of the UP_XATTR or UP_XATTR_RM set. This indicates
3604df
         that an xattr was updated or deleted.
3604df
3604df
CI_RENAME : Number of upcalls that were cache invalidation,
3604df
         resulted by the renaming of a file or directory
3604df
3604df
CI_UNLINK : Number of upcalls that were cache invalidation,
3604df
         resulted by the unlink of a file.
3604df
3604df
CI_FORGET : Number of upcalls that were cache invalidation,
3604df
         resulted by the forget of inode on the server side.
3604df
3604df
Lease events:
3604df
------------
3604df
LEASE_RECALL : Number of lease recalls sent by the brick (in
3604df
         brick profile), and number of lease recalls recieved
3604df
         by client(in client profile)
3604df
3604df
Note that the sum of CI_IATT, CI_XATTR, CI_RENAME, CI_UNLINK,
3604df
CI_FORGET, LEASE_RECALL may not be equal to UPCALL. This is
3604df
because, each cache invalidation can carry multiple flags.
3604df
Eg:
3604df
- Every CI_XATTR will have CI_IATT
3604df
- Every CI_UNLINK will also increment CI_IATT as link count is an
3604df
iatt attribute.
3604df
3604df
Also UP_PARENT_DENTRY_FLAGS is currently not accounted for,
3604df
as CI_RENAME and CI_UNLINK will always have the flag
3604df
UP_PARENT_DENTRY_FLAGS
3604df
3604df
Change-Id: Ieb8cd21dde2c4c7618f12d025a5e5156f9cc0fe9
3604df
BUG: 1284873
3604df
Signed-off-by: Poornima G <pgurusid@redhat.com>
3604df
Reviewed-on: http://review.gluster.org/15193
3604df
Smoke: Gluster Build System <jenkins@build.gluster.org>
3604df
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
3604df
Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
3604df
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
3604df
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
3604df
Reviewed-on: https://code.engineering.redhat.com/gerrit/87044
3604df
Tested-by: Rajesh Joseph <rjoseph@redhat.com>
3604df
---
3604df
 cli/src/cli-rpc-ops.c                 |   25 +++++++++
3604df
 cli/src/cli-xml-output.c              |   44 ++++++++++++++++-
3604df
 libglusterfs/src/globals.c            |   13 +++++
3604df
 libglusterfs/src/globals.h            |    1 +
3604df
 rpc/xdr/src/glusterfs-fops.x          |   12 +++++
3604df
 tests/bugs/upcall/bug-upcall-stat.t   |   38 ++++++++++++++
3604df
 xlators/debug/io-stats/src/io-stats.c |   87 +++++++++++++++++++++++++++++++++
3604df
 7 files changed, 219 insertions(+), 1 deletions(-)
3604df
 create mode 100755 tests/bugs/upcall/bug-upcall-stat.t
3604df
3604df
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
3604df
index e8fc658..58884a2 100644
3604df
--- a/cli/src/cli-rpc-ops.c
3604df
+++ b/cli/src/cli-rpc-ops.c
3604df
@@ -30,6 +30,7 @@
3604df
 #include "protocol-common.h"
3604df
 #include "cli-mem-types.h"
3604df
 #include "compat.h"
3604df
+#include "upcall-utils.h"
3604df
 
3604df
 #include "syscall.h"
3604df
 #include "glusterfs3.h"
3604df
@@ -6293,6 +6294,7 @@ cmd_profile_volume_brick_out (dict_t *dict, int count, int interval)
3604df
         uint64_t                rb_counts[32] = {0};
3604df
         uint64_t                wb_counts[32] = {0};
3604df
         cli_profile_info_t      profile_info[GF_FOP_MAXVALUE] = {{0}};
3604df
+        cli_profile_info_t      upcall_info[GF_UPCALL_FLAGS_MAXVALUE] = {{0},};
3604df
         char                    output[128] = {0};
3604df
         int                     per_line = 0;
3604df
         char                    read_blocks[128] = {0};
3604df
@@ -6316,6 +6318,13 @@ cmd_profile_volume_brick_out (dict_t *dict, int count, int interval)
3604df
                 ret = dict_get_uint64 (dict, key, &wb_counts[i]);
3604df
         }
3604df
 
3604df
+        for (i = 0; i < GF_UPCALL_FLAGS_MAXVALUE; i++) {
3604df
+                snprintf (key, sizeof (key), "%d-%d-%d-upcall-hits", count,
3604df
+                          interval, i);
3604df
+                ret = dict_get_uint64 (dict, key, &upcall_info[i].fop_hits);
3604df
+                upcall_info[i].fop_name = (char *)gf_upcall_list[i];
3604df
+        }
3604df
+
3604df
         for (i = 0; i < GF_FOP_MAXVALUE; i++) {
3604df
                 memset (key, 0, sizeof (key));
3604df
                 snprintf (key, sizeof (key), "%d-%d-%d-hits", count,
3604df
@@ -6440,6 +6449,22 @@ cmd_profile_volume_brick_out (dict_t *dict, int count, int interval)
3604df
                                  profile_info[i].fop_name);
3604df
                 }
3604df
         }
3604df
+
3604df
+        for (i = 0; i < GF_UPCALL_FLAGS_MAXVALUE; i++) {
3604df
+                if (upcall_info[i].fop_hits == 0)
3604df
+                        continue;
3604df
+                if (upcall_info[i].fop_hits) {
3604df
+                        cli_out ("%10.2lf %10.2lf us %10.2lf us %10.2lf us"
3604df
+                                 " %14"PRId64" %11s",
3604df
+                                 upcall_info[i].percentage_avg_latency,
3604df
+                                 upcall_info[i].avg_latency,
3604df
+                                 upcall_info[i].min_latency,
3604df
+                                 upcall_info[i].max_latency,
3604df
+                                 upcall_info[i].fop_hits,
3604df
+                                 upcall_info[i].fop_name);
3604df
+                }
3604df
+        }
3604df
+
3604df
         cli_out (" ");
3604df
         cli_out ("%12s: %"PRId64" seconds", "Duration", sec);
3604df
         cli_out ("%12s: %"PRId64" bytes", "Data Read", r_count);
3604df
diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c
3604df
index 6d1e617..f249e40 100644
3604df
--- a/cli/src/cli-xml-output.c
3604df
+++ b/cli/src/cli-xml-output.c
3604df
@@ -13,7 +13,7 @@
3604df
 #include "run.h"
3604df
 #include "compat.h"
3604df
 #include "syscall.h"
3604df
-
3604df
+#include "upcall-utils.h"
3604df
 
3604df
 enum gf_task_types {
3604df
     GF_TASK_TYPE_REBALANCE,
3604df
@@ -2200,6 +2200,48 @@ cont:
3604df
                 max_latency = 0.0;
3604df
         }
3604df
 
3604df
+        for (i = 0; i < GF_UPCALL_FLAGS_MAXVALUE; i++) {
3604df
+                hits = 0;
3604df
+                avg_latency = 0.0;
3604df
+                min_latency = 0.0;
3604df
+                max_latency = 0.0;
3604df
+
3604df
+                memset (key, 0, sizeof (key));
3604df
+                snprintf (key, sizeof (key), "%d-%d-%d-upcall-hits", brick_index,
3604df
+                          interval, i);
3604df
+                ret = dict_get_uint64 (dict, key, &hits);
3604df
+                if (ret)
3604df
+                        continue;
3604df
+
3604df
+                /* <fop> */
3604df
+                ret = xmlTextWriterStartElement (writer, (xmlChar *)"fop");
3604df
+                XML_RET_CHECK_AND_GOTO (ret, out);
3604df
+
3604df
+                ret = xmlTextWriterWriteFormatElement
3604df
+                        (writer, (xmlChar *)"name", "%s", gf_fop_list[i]);
3604df
+                XML_RET_CHECK_AND_GOTO (ret, out);
3604df
+
3604df
+                ret = xmlTextWriterWriteFormatElement
3604df
+                        (writer, (xmlChar *)"hits", "%"PRIu64, hits);
3604df
+                XML_RET_CHECK_AND_GOTO (ret, out);
3604df
+
3604df
+                ret = xmlTextWriterWriteFormatElement
3604df
+                        (writer, (xmlChar *)"avgLatency", "%f", avg_latency);
3604df
+                XML_RET_CHECK_AND_GOTO (ret, out);
3604df
+
3604df
+                ret = xmlTextWriterWriteFormatElement
3604df
+                        (writer, (xmlChar *)"minLatency", "%f", min_latency);
3604df
+                XML_RET_CHECK_AND_GOTO (ret, out);
3604df
+
3604df
+                ret = xmlTextWriterWriteFormatElement
3604df
+                        (writer, (xmlChar *)"maxLatency", "%f", max_latency);
3604df
+                XML_RET_CHECK_AND_GOTO (ret, out);
3604df
+
3604df
+                /* </fop> */
3604df
+                ret = xmlTextWriterEndElement (writer);
3604df
+                XML_RET_CHECK_AND_GOTO (ret, out);
3604df
+        }
3604df
+
3604df
         /* </fopStats> */
3604df
         ret = xmlTextWriterEndElement (writer);
3604df
         XML_RET_CHECK_AND_GOTO (ret, out);
3604df
diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c
3604df
index 50ef4db..c537971 100644
3604df
--- a/libglusterfs/src/globals.c
3604df
+++ b/libglusterfs/src/globals.c
3604df
@@ -16,6 +16,7 @@
3604df
 #include "mem-pool.h"
3604df
 #include "syncop.h"
3604df
 #include "libglusterfs-messages.h"
3604df
+#include "upcall-utils.h"
3604df
 
3604df
 const char *gf_fop_list[GF_FOP_MAXVALUE] = {
3604df
         [GF_FOP_NULL]        = "NULL",
3604df
@@ -74,6 +75,18 @@ const char *gf_fop_list[GF_FOP_MAXVALUE] = {
3604df
         [GF_FOP_GETACTIVELK] = "GETACTIVELK",
3604df
         [GF_FOP_SETACTIVELK] = "SETACTIVELK",
3604df
 };
3604df
+
3604df
+const char *gf_upcall_list[GF_UPCALL_FLAGS_MAXVALUE] = {
3604df
+        [GF_UPCALL_NULL] = "NULL",
3604df
+        [GF_UPCALL] = "UPCALL",
3604df
+        [GF_UPCALL_CI_STAT] = "CI_IATT",
3604df
+        [GF_UPCALL_CI_XATTR] = "CI_XATTR",
3604df
+        [GF_UPCALL_CI_RENAME] = "CI_RENAME",
3604df
+        [GF_UPCALL_CI_NLINK] = "CI_UNLINK",
3604df
+        [GF_UPCALL_CI_FORGET] = "CI_FORGET",
3604df
+        [GF_UPCALL_LEASE_RECALL] = "LEASE_RECALL",
3604df
+};
3604df
+
3604df
 /* THIS */
3604df
 
3604df
 /* This global ctx is a bad hack to prevent some of the libgfapi crashes.
3604df
diff --git a/libglusterfs/src/globals.h b/libglusterfs/src/globals.h
3604df
index 514109a..b12b0ad 100644
3604df
--- a/libglusterfs/src/globals.h
3604df
+++ b/libglusterfs/src/globals.h
3604df
@@ -129,6 +129,7 @@ char *glusterfs_leaseid_buf_get ();
3604df
 int glusterfs_globals_init (glusterfs_ctx_t *ctx);
3604df
 
3604df
 extern const char *gf_fop_list[];
3604df
+extern const char *gf_upcall_list[];
3604df
 
3604df
 /* mem acct enable/disable */
3604df
 int gf_global_mem_acct_enable_get (void);
3604df
diff --git a/rpc/xdr/src/glusterfs-fops.x b/rpc/xdr/src/glusterfs-fops.x
3604df
index 3b6b649..4bfdd4b 100644
3604df
--- a/rpc/xdr/src/glusterfs-fops.x
3604df
+++ b/rpc/xdr/src/glusterfs-fops.x
3604df
@@ -197,3 +197,15 @@ enum gf_seek_what_t {
3604df
         GF_SEEK_DATA,
3604df
         GF_SEEK_HOLE
3604df
 };
3604df
+
3604df
+enum gf_upcall_flags_t {
3604df
+        GF_UPCALL_NULL,
3604df
+        GF_UPCALL,
3604df
+        GF_UPCALL_CI_STAT,
3604df
+        GF_UPCALL_CI_XATTR,
3604df
+        GF_UPCALL_CI_RENAME,
3604df
+        GF_UPCALL_CI_NLINK,
3604df
+        GF_UPCALL_CI_FORGET,
3604df
+        GF_UPCALL_LEASE_RECALL,
3604df
+        GF_UPCALL_FLAGS_MAXVALUE
3604df
+};
3604df
diff --git a/tests/bugs/upcall/bug-upcall-stat.t b/tests/bugs/upcall/bug-upcall-stat.t
3604df
new file mode 100755
3604df
index 0000000..b229c13
3604df
--- /dev/null
3604df
+++ b/tests/bugs/upcall/bug-upcall-stat.t
3604df
@@ -0,0 +1,38 @@
3604df
+#!/bin/bash
3604df
+
3604df
+. $(dirname $0)/../../include.rc
3604df
+. $(dirname $0)/../../volume.rc
3604df
+
3604df
+cleanup;
3604df
+TEST glusterd;
3604df
+
3604df
+TEST $CLI volume create $V0 $H0:$B0/${V0}{1};
3604df
+
3604df
+TEST $CLI volume set $V0 performance.md-cache-timeout 600
3604df
+TEST $CLI volume set $V0 performance.cache-samba-metadata on
3604df
+TEST $CLI volume set $V0 features.cache-invalidation on
3604df
+TEST $CLI volume set $V0 features.cache-invalidation-timeout 600
3604df
+
3604df
+#TEST $CLI volume stop $V0
3604df
+TEST $CLI volume start $V0
3604df
+
3604df
+## 5. Create two gluster mounts
3604df
+TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0
3604df
+TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M1
3604df
+
3604df
+TEST $CLI volume profile $V0 start
3604df
+
3604df
+## 8. Create a file
3604df
+TEST touch $M0/file1
3604df
+
3604df
+TEST "setfattr -n user.DOSATTRIB -v "abc" $M0/file1"
3604df
+TEST "getfattr -n user.DOSATTRIB $M1/file1 | grep -q abc"
3604df
+TEST "setfattr -n user.DOSATTRIB -v "xyz" $M0/file1"
3604df
+sleep 2; #There can be a very very small window where the next getxattr
3604df
+         #reaches md-cache, before the cache-invalidation caused by previous
3604df
+         #setxattr, reaches md-cache. Hence sleeping for 2 sec.
3604df
+         #Also it should not be > 600.
3604df
+TEST "getfattr -n user.DOSATTRIB $M1/file1 | grep -q xyz"
3604df
+
3604df
+$CLI volume profile $V0 info | grep -q CI_XATTR
3604df
+EXPECT '0' echo $?
3604df
diff --git a/xlators/debug/io-stats/src/io-stats.c b/xlators/debug/io-stats/src/io-stats.c
3604df
index 43fba57..c2375d9 100644
3604df
--- a/xlators/debug/io-stats/src/io-stats.c
3604df
+++ b/xlators/debug/io-stats/src/io-stats.c
3604df
@@ -37,6 +37,7 @@
3604df
 #include "statedump.h"
3604df
 #include <pwd.h>
3604df
 #include <grp.h>
3604df
+#include "upcall-utils.h"
3604df
 
3604df
 #define MAX_LIST_MEMBERS 100
3604df
 #define DEFAULT_PWD_BUF_SZ 16384
3604df
@@ -119,6 +120,7 @@ struct ios_global_stats {
3604df
         uint64_t        block_count_write[32];
3604df
         uint64_t        block_count_read[32];
3604df
         uint64_t        fop_hits[GF_FOP_MAXVALUE];
3604df
+        uint64_t        upcall_hits[GF_UPCALL_FLAGS_MAXVALUE];
3604df
         struct timeval  started_at;
3604df
         struct ios_lat  latency[GF_FOP_MAXVALUE];
3604df
         uint64_t        nr_opens;
3604df
@@ -365,6 +367,19 @@ is_fop_latency_started (call_frame_t *frame)
3604df
                                                throughput, iosstat);           \
3604df
         } while (0)
3604df
 
3604df
+#define BUMP_UPCALL(event)                                                     \
3604df
+        do {                                                                   \
3604df
+                struct ios_conf  *conf = NULL;                                 \
3604df
+                                                                               \
3604df
+                conf = this->private;                                          \
3604df
+                if (!conf)                                                     \
3604df
+                        break;                                                 \
3604df
+                if (conf->count_fop_hits) {                                    \
3604df
+                        conf->cumulative.upcall_hits[event]++;                 \
3604df
+                        conf->incremental.upcall_hits[event]++;                \
3604df
+                }                                                              \
3604df
+        } while (0)
3604df
+
3604df
 int
3604df
 ios_fd_ctx_get (fd_t *fd, xlator_t *this, struct ios_fd **iosfd)
3604df
 {
3604df
@@ -883,6 +898,26 @@ io_stats_dump_global_to_json_logfp (xlator_t *this,
3604df
                         "\"%s.%s.fop.%s.latency_max_usec\": \"%0.2lf\",",
3604df
                         key_prefix, str_prefix, lc_fop_name, fop_lat_max);
3604df
         }
3604df
+
3604df
+        for (i = 0; i < GF_UPCALL_FLAGS_MAXVALUE; i++) {
3604df
+                lc_fop_name = strdupa (gf_upcall_list[i]);
3604df
+                for (j = 0; lc_fop_name[j]; j++) {
3604df
+                        lc_fop_name[j] = tolower (lc_fop_name[j]);
3604df
+                }
3604df
+                fop_hits = stats->upcall_hits[i];
3604df
+                if (interval == -1) {
3604df
+                        ios_log (this, logfp,
3604df
+                                "\"%s.%s.fop.%s.count\": \"%"PRId64"\",",
3604df
+                                key_prefix, str_prefix, lc_fop_name,
3604df
+                                fop_hits);
3604df
+                } else {
3604df
+                        ios_log (this, logfp,
3604df
+                                "\"%s.%s.fop.%s.per_sec\": \"%0.2lf\",",
3604df
+                                key_prefix, str_prefix, lc_fop_name,
3604df
+                                (double)(fop_hits / interval_sec));
3604df
+                }
3604df
+        }
3604df
+
3604df
         if (interval == -1) {
3604df
                 ios_log (this, logfp, "\"%s.%s.uptime\": \"%"PRId64"\",",
3604df
                          key_prefix, str_prefix,
3604df
@@ -1233,6 +1268,14 @@ io_stats_dump_global_to_logfp (xlator_t *this, struct ios_global_stats *stats,
3604df
                                  stats->fop_hits[i], stats->latency[i].avg,
3604df
                                  stats->latency[i].min, stats->latency[i].max);
3604df
         }
3604df
+
3604df
+        for (i = 0; i < GF_UPCALL_FLAGS_MAXVALUE; i++) {
3604df
+                if (stats->upcall_hits[i])
3604df
+                        ios_log (this, logfp, "%-13s %10"PRId64" %11s "
3604df
+                                 "us %11s us %11s us", gf_upcall_list[i],
3604df
+                                 stats->upcall_hits[i], "0", "0", "0");
3604df
+        }
3604df
+
3604df
         ios_log (this, logfp, "------ ----- ----- ----- ----- ----- ----- ----- "
3604df
                  " ----- ----- ----- -----\n");
3604df
 
3604df
@@ -1415,6 +1458,19 @@ io_stats_dump_global_to_dict (xlator_t *this, struct ios_global_stats *stats,
3604df
                         goto out;
3604df
                 }
3604df
         }
3604df
+        for (i = 0; i < GF_UPCALL_FLAGS_MAXVALUE; i++) {
3604df
+                if (stats->upcall_hits[i] == 0)
3604df
+                        continue;
3604df
+                snprintf (key, sizeof (key), "%d-%d-upcall-hits", interval, i);
3604df
+                ret = dict_set_uint64 (dict, key, stats->upcall_hits[i]);
3604df
+                if (ret) {
3604df
+                        gf_log (this->name, GF_LOG_ERROR, "failed to "
3604df
+                                "set %s-upcall-hits: %"PRIu64,
3604df
+                                gf_upcall_list[i],
3604df
+                                stats->upcall_hits[i]);
3604df
+                        goto out;
3604df
+                }
3604df
+        }
3604df
 out:
3604df
         gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret);
3604df
         return ret;
3604df
@@ -3780,6 +3836,8 @@ notify (xlator_t *this, int32_t event, void *data, ...)
3604df
         double        time = 0;
3604df
         gf_boolean_t  is_peek = _gf_false;
3604df
         va_list ap;
3604df
+        struct gf_upcall *up_data = NULL;
3604df
+        struct gf_upcall_cache_invalidation *up_ci = NULL;
3604df
 
3604df
         dict = data;
3604df
         va_start (ap, data);
3604df
@@ -3875,6 +3933,35 @@ notify (xlator_t *this, int32_t event, void *data, ...)
3604df
                         }
3604df
                 }
3604df
                 break;
3604df
+        case GF_EVENT_UPCALL:
3604df
+                up_data = (struct gf_upcall *)data;
3604df
+                BUMP_UPCALL (GF_UPCALL);
3604df
+
3604df
+                switch (up_data->event_type) {
3604df
+                case GF_UPCALL_RECALL_LEASE:
3604df
+                        BUMP_UPCALL (GF_UPCALL_LEASE_RECALL);
3604df
+                        break;
3604df
+                case GF_UPCALL_CACHE_INVALIDATION:
3604df
+                        up_ci = (struct gf_upcall_cache_invalidation *)up_data->data;
3604df
+                        if (up_ci->flags & (UP_XATTR | UP_XATTR_RM))
3604df
+                                BUMP_UPCALL (GF_UPCALL_CI_XATTR);
3604df
+                        if (up_ci->flags & IATT_UPDATE_FLAGS)
3604df
+                                BUMP_UPCALL (GF_UPCALL_CI_STAT);
3604df
+                        if (up_ci->flags & UP_RENAME_FLAGS)
3604df
+                                BUMP_UPCALL (GF_UPCALL_CI_RENAME);
3604df
+                        if (up_ci->flags & UP_FORGET)
3604df
+                                BUMP_UPCALL (GF_UPCALL_CI_FORGET);
3604df
+                        if (up_ci->flags & UP_NLINK)
3604df
+                                BUMP_UPCALL (GF_UPCALL_CI_NLINK);
3604df
+                        break;
3604df
+                default:
3604df
+                        gf_msg_debug (this->name, 0, "Unknown upcall event "
3604df
+                                      "type :%d", up_data->event_type);
3604df
+                        break;
3604df
+                }
3604df
+
3604df
+                default_notify (this, event, data);
3604df
+                break;
3604df
         default:
3604df
                 default_notify (this, event, data);
3604df
                 break;
3604df
-- 
3604df
1.7.1
3604df