summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
authorGaurav Kumar Garg <ggarg@redhat.com>2015-03-25 18:07:24 +0530
committerAtin Mukherjee <amukherj@redhat.com>2015-11-19 19:41:43 -0800
commit097e131481d25e5b1f859f4ea556b8bf56155472 (patch)
tree0086afbddcf7ea8706a5560484ea30fa9488e102 /xlators
parentb479e086ddbcb5cde83c11b67d542dbd4f2bd739 (diff)
glusterd: cli command implementation for bitrot scrub status
CLI command for bitrot scrub status will be : gluster volume bitrot <volname> scrub status Above command will show the statistics of bitrot scrubber. Upon execution of this command it will show some common scrubber tunable value of volume <VOLNAME> followed by statistics of scrubber statistics of individual nodes. sample ouput for single node: Volume name : <VOLNAME> State of scrub: Active Scrub frequency: biweekly Bitrot error log location: /var/log/glusterfs/bitd.log Scrubber error log location: /var/log/glusterfs/scrub.log ========================================================= Node name: Number of Scrubbed files: Number of Unsigned files: Last completed scrub time: Duration of last scrub: Error count: ========================================================= This is just infrastructure. list of bad file, last scrub time, error count value will be taken care by http://review.gluster.org/#/c/12503/ and http://review.gluster.org/#/c/12654/ patches. Change-Id: I3ed3c7057c9d0c894233f4079a7f185d90c202d1 BUG: 1207627 Signed-off-by: Gaurav Kumar Garg <ggarg@redhat.com> Reviewed-on: http://review.gluster.org/10231 Reviewed-by: Atin Mukherjee <amukherj@redhat.com> Tested-by: NetBSD Build System <jenkins@build.gluster.org> Tested-by: Gluster Build System <jenkins@build.gluster.com>
Diffstat (limited to 'xlators')
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot.c18
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-bitrot.c46
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.c93
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-rpc-ops.c2
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-syncop.c5
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c394
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h5
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.h18
8 files changed, 571 insertions, 10 deletions
diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.c b/xlators/features/bit-rot/src/bitd/bit-rot.c
index d6ae5e2..c4ed7de 100644
--- a/xlators/features/bit-rot/src/bitd/bit-rot.c
+++ b/xlators/features/bit-rot/src/bitd/bit-rot.c
@@ -1550,9 +1550,12 @@ int
notify (xlator_t *this, int32_t event, void *data, ...)
{
int idx = -1;
+ int ret = -1;
xlator_t *subvol = NULL;
br_child_t *child = NULL;
br_private_t *priv = NULL;
+ dict_t *output = NULL;
+ va_list ap;
subvol = (xlator_t *)data;
priv = this->private;
@@ -1619,6 +1622,21 @@ notify (xlator_t *this, int32_t event, void *data, ...)
default_notify (this, event, data);
break;
+ case GF_EVENT_SCRUB_STATUS:
+ gf_log (this->name, GF_LOG_INFO, "BitRot scrub status "
+ "called");
+ va_start (ap, data);
+ output = va_arg (ap, dict_t *);
+
+ /* As of now hardcoding last-scrub-time value. At the time of
+ * Final patch submission this option value along with other
+ * few option value will be calculate based on real time */
+ ret = dict_set_uint64 (output, "last-scrub-time", 12);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG, "Failed to set last "
+ "scrub time value");
+ }
+ break;
default:
default_notify (this, event, data);
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-bitrot.c b/xlators/mgmt/glusterd/src/glusterd-bitrot.c
index c9cf929..6e91106 100644
--- a/xlators/mgmt/glusterd/src/glusterd-bitrot.c
+++ b/xlators/mgmt/glusterd/src/glusterd-bitrot.c
@@ -39,15 +39,16 @@ const char *gd_bitrot_op_list[GF_BITROT_OPTION_TYPE_MAX] = {
int
__glusterd_handle_bitrot (rpcsvc_request_t *req)
{
- int32_t ret = -1;
- gf_cli_req cli_req = { {0,} };
- dict_t *dict = NULL;
- glusterd_op_t cli_op = GD_OP_BITROT;
- char *volname = NULL;
- int32_t type = 0;
+ int32_t ret = -1;
+ gf_cli_req cli_req = { {0,} };
+ dict_t *dict = NULL;
+ glusterd_op_t cli_op = GD_OP_BITROT;
+ char *volname = NULL;
+ char *scrub = NULL;
+ int32_t type = 0;
char msg[2048] = {0,};
- xlator_t *this = NULL;
- glusterd_conf_t *conf = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
GF_ASSERT (req);
@@ -109,6 +110,34 @@ __glusterd_handle_bitrot (rpcsvc_request_t *req)
goto out;
}
+ if (type == GF_BITROT_CMD_SCRUB_STATUS) {
+ /* Backward compatibility handling for scrub status command*/
+ if (conf->op_version < GD_OP_VERSION_3_7_7) {
+ snprintf (msg, sizeof (msg), "Cannot execute command. "
+ "The cluster is operating at version %d. "
+ "Bitrot scrub status command unavailable in "
+ "this version", conf->op_version);
+ ret = -1;
+ goto out;
+ }
+
+ ret = dict_get_str (dict, "scrub-value", &scrub);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_GET_FAILED,
+ "Failed to get scrub value.");
+ ret = -1;
+ goto out;
+ }
+
+ if (!strncmp (scrub, "status", strlen ("status"))) {
+ ret = glusterd_op_begin_synctask (req,
+ GD_OP_SCRUB_STATUS,
+ dict);
+ goto out;
+ }
+ }
+
ret = glusterd_op_begin_synctask (req, GD_OP_BITROT, dict);
out:
@@ -542,6 +571,7 @@ glusterd_op_bitrot (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
op_errstr);
if (ret)
goto out;
+ case GF_BITROT_CMD_SCRUB_STATUS:
break;
default:
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
index 7db62e9..8bc47fc 100644
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
@@ -685,6 +685,8 @@ glusterd_node_op_build_payload (glusterd_op_t op, gd1_mgmt_brick_op_req **req,
{
int ret = -1;
gd1_mgmt_brick_op_req *brick_req = NULL;
+ char xlname[1024] = {0,};
+ char *volname = NULL;
GF_ASSERT (op < GD_OP_MAX);
GF_ASSERT (op > GD_OP_NONE);
@@ -713,6 +715,20 @@ glusterd_node_op_build_payload (glusterd_op_t op, gd1_mgmt_brick_op_req **req,
break;
+ case GD_OP_SCRUB_STATUS:
+ brick_req = GF_CALLOC (1, sizeof(*brick_req),
+ gf_gld_mt_mop_brick_req_t);
+ if (!brick_req)
+ goto out;
+
+ brick_req->op = GLUSTERD_NODE_BITROT;
+
+ ret = dict_get_str (dict, "volname", &volname);
+ if (ret)
+ goto out;
+
+ brick_req->name = gf_strdup (volname);
+ break;
default:
goto out;
}
@@ -4035,6 +4051,7 @@ glusterd_op_build_payload (dict_t **req, char **op_errstr, dict_t *op_ctx)
case GD_OP_DEFRAG_BRICK_VOLUME:
case GD_OP_BARRIER:
case GD_OP_BITROT:
+ case GD_OP_SCRUB_STATUS:
{
do_common = _gf_true;
}
@@ -4616,6 +4633,7 @@ glusterd_op_modify_op_ctx (glusterd_op_t op, void *ctx)
* same
*/
case GD_OP_DEFRAG_BRICK_VOLUME:
+ case GD_OP_SCRUB_STATUS:
ret = dict_get_int32 (op_ctx, "count", &count);
if (ret) {
gf_msg_debug (this->name, 0,
@@ -4663,6 +4681,13 @@ glusterd_op_modify_op_ctx (glusterd_op_t op, void *ctx)
GD_MSG_CONVERSION_FAILED,
"Failed uuid to hostname conversion");
+ /* Since Both rebalance and bitrot scrub status are going to
+ * use same code path till here, we should break in case
+ * of scrub status */
+ if (op == GD_OP_SCRUB_STATUS) {
+ break;
+ }
+
ret = glusterd_op_check_peer_defrag_status (op_ctx, count);
if (ret)
gf_msg (this->name, GF_LOG_ERROR, 0,
@@ -5258,6 +5283,7 @@ glusterd_need_brick_op (glusterd_op_t op)
case GD_OP_STATUS_VOLUME:
case GD_OP_DEFRAG_BRICK_VOLUME:
case GD_OP_HEAL_VOLUME:
+ case GD_OP_SCRUB_STATUS:
ret = _gf_true;
break;
default:
@@ -5520,6 +5546,7 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr,
break;
case GD_OP_BITROT:
+ case GD_OP_SCRUB_STATUS:
ret = glusterd_op_stage_bitrot (dict, op_errstr,
rsp_dict);
break;
@@ -5644,6 +5671,7 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr,
break;
case GD_OP_BITROT:
+ case GD_OP_SCRUB_STATUS:
ret = glusterd_op_bitrot (dict, op_errstr, rsp_dict);
break;
@@ -6808,6 +6836,68 @@ out:
return ret;
}
+static int
+glusterd_bricks_select_scrub (dict_t *dict, char **op_errstr,
+ struct cds_list_head *selected)
+{
+ int ret = -1;
+ char *volname = NULL;
+ char msg[2048] = {0,};
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ glusterd_volinfo_t *volinfo = NULL;
+ glusterd_brickinfo_t *brickinfo = NULL;
+ glusterd_pending_node_t *pending_node = NULL;
+
+ this = THIS;
+ priv = this->private;
+ GF_ASSERT (this);
+ GF_ASSERT (priv);
+
+ GF_ASSERT (dict);
+
+ ret = dict_get_str (dict, "volname", &volname);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_GET_FAILED, "Unable to get"
+ " volname");
+ goto out;
+ }
+
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (ret) {
+ snprintf (msg, sizeof (msg), "Volume %s does not exist",
+ volname);
+
+ *op_errstr = gf_strdup (msg);
+ gf_msg (this->name, GF_LOG_ERROR, EINVAL,
+ GD_MSG_VOL_NOT_FOUND, "%s", msg);
+ goto out;
+ }
+
+ if (!priv->scrub_svc.online) {
+ ret = 0;
+ snprintf (msg, sizeof (msg), "Scrubber daemon is not running");
+
+ gf_msg_debug (this->name, 0, "%s", msg);
+ goto out;
+ }
+
+ pending_node = GF_CALLOC (1, sizeof (*pending_node),
+ gf_gld_mt_pending_node_t);
+ if (!pending_node) {
+ ret = -1;
+ goto out;
+ }
+
+ pending_node->node = &(priv->scrub_svc);
+ pending_node->type = GD_NODE_SCRUB;
+ cds_list_add_tail (&pending_node->list, selected);
+ pending_node = NULL;
+out:
+ gf_msg_debug (this->name, 0, "Returning %d", ret);
+ return ret;
+}
/* Select the bricks to send the barrier request to.
* This selects the bricks of the given volume which are present on this peer
* and are running
@@ -7021,6 +7111,9 @@ glusterd_op_bricks_select (glusterd_op_t op, dict_t *dict, char **op_errstr,
case GD_OP_SNAP:
ret = glusterd_bricks_select_snap (dict, op_errstr, selected);
break;
+ case GD_OP_SCRUB_STATUS:
+ ret = glusterd_bricks_select_scrub (dict, op_errstr, selected);
+ break;
default:
break;
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
index 8a82652..fd51255 100644
--- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
+++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
@@ -142,6 +142,7 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret,
case GD_OP_SNAP:
case GD_OP_BARRIER:
case GD_OP_BITROT:
+ case GD_OP_SCRUB_STATUS:
{
/*nothing specific to be done*/
break;
@@ -2234,6 +2235,7 @@ glusterd_brick_op (call_frame_t *frame, xlator_t *this,
if ((pending_node->type == GD_NODE_NFS) ||
(pending_node->type == GD_NODE_QUOTAD) ||
(pending_node->type == GD_NODE_SNAPD) ||
+ (pending_node->type == GD_NODE_SCRUB) ||
((pending_node->type == GD_NODE_SHD) &&
(req_ctx->op == GD_OP_STATUS_VOLUME)))
ret = glusterd_node_op_build_payload
diff --git a/xlators/mgmt/glusterd/src/glusterd-syncop.c b/xlators/mgmt/glusterd/src/glusterd-syncop.c
index 0640772..a0b8561 100644
--- a/xlators/mgmt/glusterd/src/glusterd-syncop.c
+++ b/xlators/mgmt/glusterd/src/glusterd-syncop.c
@@ -304,6 +304,9 @@ glusterd_syncop_aggr_rsp_dict (glusterd_op_t op, dict_t *aggr, dict_t *rsp)
goto out;
break;
+ case GD_OP_SCRUB_STATUS:
+ ret = glusterd_volume_bitrot_scrub_use_rsp_dict (aggr, rsp);
+ break;
default:
break;
}
@@ -932,7 +935,7 @@ gd_syncop_mgmt_brick_op (struct rpc_clnt *rpc, glusterd_pending_node_t *pnode,
args.op_errno = ENOTCONN;
if ((pnode->type == GD_NODE_NFS) ||
- (pnode->type == GD_NODE_QUOTAD) ||
+ (pnode->type == GD_NODE_QUOTAD) || (pnode->type == GD_NODE_SCRUB) ||
((pnode->type == GD_NODE_SHD) && (op == GD_OP_STATUS_VOLUME))) {
ret = glusterd_node_op_build_payload (op, &req, dict_out);
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index 6f24e92..c31c394 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -4222,7 +4222,8 @@ glusterd_pending_node_get_rpc (glusterd_pending_node_t *pending_node)
} else if (pending_node->type == GD_NODE_SHD ||
pending_node->type == GD_NODE_NFS ||
- pending_node->type == GD_NODE_QUOTAD) {
+ pending_node->type == GD_NODE_QUOTAD ||
+ pending_node->type == GD_NODE_SCRUB) {
svc = pending_node->node;
rpc = svc->conn.rpc;
} else if (pending_node->type == GD_NODE_REBALANCE) {
@@ -8241,6 +8242,393 @@ out:
}
int
+glusterd_volume_bitrot_scrub_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict)
+{
+ int ret = -1;
+ uint64_t value = 0;
+ int32_t count = 0;
+ char key[256] = {0,};
+ uint64_t error_count = 0;
+ uint64_t scrubbed_files = 0;
+ uint64_t unsigned_files = 0;
+ uint64_t scrub_duration = 0;
+ uint64_t last_scrub_time = 0;
+ char *volname = NULL;
+ char *node_uuid = NULL;
+ char *node_uuid_str = NULL;
+ char *bitd_log = NULL;
+ char *scrub_log = NULL;
+ char *scrub_freq = NULL;
+ char *scrub_state = NULL;
+ char *scrub_impact = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ glusterd_volinfo_t *volinfo = NULL;
+ int src_count = 0;
+ int dst_count = 0;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ ret = dict_get_str (aggr, "volname", &volname);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
+ "Unable to get volume name");
+ goto out;
+ }
+
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (ret) {
+ gf_msg (THIS->name, GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND,
+ "Unable to find volinfo for volume: %s", volname);
+ goto out;
+ }
+
+ ret = dict_get_int32 (aggr, "count", &dst_count);
+
+ ret = dict_get_int32 (rsp_dict, "count", &src_count);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
+ "failed to get count value");
+ ret = 0;
+ goto out;
+ }
+
+ ret = dict_set_int32 (aggr, "count", src_count+dst_count);
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
+ "Failed to set count in dictonary");
+
+ snprintf (key, 256, "node-uuid-%d", src_count);
+ ret = dict_get_str (rsp_dict, key, &node_uuid);
+ if (!ret) {
+ node_uuid_str = gf_strdup (node_uuid);
+
+ memset (key, 0, 256);
+ snprintf (key, 256, "node-uuid-%d", src_count+dst_count);
+ ret = dict_set_dynstr (aggr, key, node_uuid_str);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "failed to set node-uuid");
+ }
+ }
+
+ memset (key, 0, 256);
+ snprintf (key, 256, "scrubbed-files-%d", src_count);
+ ret = dict_get_uint64 (rsp_dict, key, &value);
+ if (!ret) {
+ memset (key, 0, 256);
+ snprintf (key, 256, "scrubbed-files-%d", src_count+dst_count);
+ ret = dict_set_uint64 (aggr, key, value);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrubbed-file value");
+ }
+ }
+
+ memset (key, 0, 256);
+ snprintf (key, 256, "unsigned-files-%d", src_count);
+ ret = dict_get_uint64 (rsp_dict, key, &value);
+ if (!ret) {
+ memset (key, 0, 256);
+ snprintf (key, 256, "unsigned-files-%d", src_count+dst_count);
+ ret = dict_set_uint64 (aggr, key, value);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "unsigned-file value");
+ }
+ }
+
+ memset (key, 0, 256);
+ snprintf (key, 256, "last-scrub-time-%d", src_count);
+ ret = dict_get_uint64 (rsp_dict, key, &value);
+ if (!ret) {
+ memset (key, 0, 256);
+ snprintf (key, 256, "last-scrub-time-%d", src_count+dst_count);
+ ret = dict_set_uint64 (aggr, key, value);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "last scrub time value");
+ }
+ }
+
+ memset (key, 0, 256);
+ snprintf (key, 256, "scrub-duration-%d", src_count);
+ ret = dict_get_uint64 (rsp_dict, key, &value);
+ if (!ret) {
+ memset (key, 0, 256);
+ snprintf (key, 256, "scrub-duration-%d", src_count+dst_count);
+ ret = dict_set_uint64 (aggr, key, value);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrubbed-duration value");
+ }
+ }
+
+ memset (key, 0, 256);
+ snprintf (key, 256, "error-count-%d", src_count);
+ ret = dict_get_uint64 (rsp_dict, key, &value);
+ if (!ret) {
+ memset (key, 0, 256);
+ snprintf (key, 256, "error-count-%d", src_count+dst_count);
+ ret = dict_set_uint64 (aggr, key, value);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set error "
+ "count value");
+ }
+ }
+
+ ret = dict_get_str (rsp_dict, "bitrot_log_file", &bitd_log);
+ if (!ret) {
+ ret = dict_set_str (aggr, "bitrot_log_file", bitd_log);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "bitrot log file location");
+ goto out;
+ }
+ }
+
+ ret = dict_get_str (rsp_dict, "scrub_log_file", &scrub_log);
+ if (!ret) {
+ ret = dict_set_str (aggr, "scrub_log_file", scrub_log);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrubber log file location");
+ goto out;
+ }
+ }
+
+ ret = dict_get_str (rsp_dict, "features.scrub-freq", &scrub_freq);
+ if (!ret) {
+ ret = dict_set_str (aggr, "features.scrub-freq", scrub_freq);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrub-frequency value to dictionary");
+ goto out;
+ }
+ }
+
+ ret = dict_get_str (rsp_dict, "features.scrub-throttle", &scrub_impact);
+ if (!ret) {
+ ret = dict_set_str (aggr, "features.scrub-throttle",
+ scrub_impact);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrub-throttle value to dictionary");
+ goto out;
+ }
+ }
+
+ ret = dict_get_str (rsp_dict, "features.scrub", &scrub_state);
+ if (!ret) {
+ ret = dict_set_str (aggr, "features.scrub", scrub_state);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrub state value to dictionary");
+ goto out;
+ }
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int
+glusterd_bitrot_volume_node_rsp (dict_t *aggr, dict_t *rsp_dict)
+{
+ int ret = -1;
+ uint64_t value = 0;
+ int32_t count = 0;
+ int32_t index = 0;
+ char key[256] = {0,};
+ char buf[1024] = {0,};
+ uint64_t error_count = 0;
+ int32_t i = 0;
+ uint64_t scrubbed_files = 0;
+ uint64_t unsigned_files = 0;
+ uint64_t scrub_duration = 0;
+ uint64_t last_scrub_time = 0;
+ char *volname = NULL;
+ char *node_str = NULL;
+ char *scrub_freq = NULL;
+ char *scrub_state = NULL;
+ char *scrub_impact = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ glusterd_volinfo_t *volinfo = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ ret = dict_set_str (aggr, "bitrot_log_file",
+ (priv->bitd_svc.proc.logfile));
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
+ "Failed to set bitrot log file location");
+ goto out;
+ }
+
+ ret = dict_set_str (aggr, "scrub_log_file",
+ (priv->scrub_svc.proc.logfile));
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
+ "Failed to set scrubber log file location");
+ goto out;
+ }
+
+ ret = dict_get_str (aggr, "volname", &volname);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
+ "Unable to get volume name");
+ goto out;
+ }
+
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_VOL_NOT_FOUND,
+ "Unable to find volinfo for volume: %s", volname);
+ goto out;
+ }
+
+ ret = dict_get_int32 (aggr, "count", &i);
+ i++;
+
+ ret = dict_set_int32 (aggr, "count", i);
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
+ "Failed to set count");
+
+ snprintf (buf, 1024, "%s", uuid_utoa (MY_UUID));
+
+ snprintf (key, 256, "node-uuid-%d", i);
+ ret = dict_set_dynstr_with_alloc (aggr, key, buf);
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
+ "failed to set node-uuid");
+
+ ret = dict_get_str (volinfo->dict, "features.scrub-freq", &scrub_freq);
+ if (!ret) {
+ ret = dict_set_str (aggr, "features.scrub-freq", scrub_freq);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrub-frequency value to dictionary");
+ }
+ } else {
+ /* By Default scrub-frequency is bi-weekly. So when user
+ * enable bitrot then scrub-frequency value will not be
+ * present in volinfo->dict. Setting by-default value of
+ * scrub-frequency explicitly for presenting it to scrub
+ * status.
+ */
+ ret = dict_set_dynstr_with_alloc (aggr, "features.scrub-freq",
+ "biweekly");
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrub-frequency value to dictionary");
+ }
+ }
+
+ ret = dict_get_str (volinfo->dict, "features.scrub-throttle",
+ &scrub_impact);
+ if (!ret) {
+ ret = dict_set_str (aggr, "features.scrub-throttle",
+ scrub_impact);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrub-throttle value to dictionary");
+ }
+ } else {
+ /* By Default scrub-throttle is lazy. So when user
+ * enable bitrot then scrub-throttle value will not be
+ * present in volinfo->dict. Setting by-default value of
+ * scrub-throttle explicitly for presenting it to
+ * scrub status.
+ */
+ ret = dict_set_dynstr_with_alloc (aggr,
+ "features.scrub-throttle",
+ "lazy");
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrub-throttle value to dictionary");
+ }
+ }
+
+ ret = dict_get_str (volinfo->dict, "features.scrub", &scrub_state);
+ if (!ret) {
+ ret = dict_set_str (aggr, "features.scrub", scrub_state);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrub state value to dictionary");
+ }
+ }
+
+ ret = dict_get_uint64 (rsp_dict, "scrubbed-files", &value);
+ if (!ret) {
+ memset (key, 0, 256);
+ snprintf (key, 256, "scrubbed-files-%d", i);
+ ret = dict_set_uint64 (aggr, key, value);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrubbed-file value");
+ }
+ }
+
+ ret = dict_get_uint64 (rsp_dict, "unsigned-files", &value);
+ if (!ret) {
+ memset (key, 0, 256);
+ snprintf (key, 256, "unsigned-files-%d", i);
+ ret = dict_set_uint64 (aggr, key, value);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "unsigned-file value");
+ }
+ }
+
+ ret = dict_get_uint64 (rsp_dict, "last-scrub-time", &value);
+ if (!ret) {
+ memset (key, 0, 256);
+ snprintf (key, 256, "last-scrub-time-%d", i);
+ ret = dict_set_uint64 (aggr, key, value);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "last scrub time value");
+ }
+ }
+
+ ret = dict_get_uint64 (rsp_dict, "scrub-duration", &value);
+ if (!ret) {
+ memset (key, 0, 256);
+ snprintf (key, 256, "scrub-duration-%d", i);
+ ret = dict_set_uint64 (aggr, key, value);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set "
+ "scrubbed-duration value");
+ }
+ }
+
+ ret = dict_get_uint64 (rsp_dict, "error-count", &value);
+ if (!ret) {
+ memset (key, 0, 256);
+ snprintf (key, 256, "error-count-%d", i);
+ ret = dict_set_uint64 (aggr, key, value);
+ if (ret) {
+ gf_msg_debug (this->name, 0, "Failed to set error "
+ "count value");
+ }
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int
glusterd_volume_rebalance_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict)
{
char key[256] = {0,};
@@ -9139,6 +9527,10 @@ glusterd_handle_node_rsp (dict_t *req_dict, void *pending_entry,
ret = glusterd_heal_volume_brick_rsp (req_dict, rsp_dict,
op_ctx, op_errstr);
break;
+ case GD_OP_SCRUB_STATUS:
+ ret = glusterd_bitrot_volume_node_rsp (op_ctx, rsp_dict);
+
+ break;
default:
break;
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
index b7302c8..f3895db 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
@@ -436,6 +436,11 @@ int32_t
glusterd_handle_node_rsp (dict_t *req_ctx, void *pending_entry,
glusterd_op_t op, dict_t *rsp_dict, dict_t *op_ctx,
char **op_errstr, gd_node_type type);
+int
+glusterd_volume_bitrot_scrub_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict);
+
+int
+glusterd_volume_heal_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict);
int32_t
glusterd_check_if_quota_trans_enabled (glusterd_volinfo_t *volinfo);
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
index 124c6cf..817112e 100644
--- a/xlators/mgmt/glusterd/src/glusterd.h
+++ b/xlators/mgmt/glusterd/src/glusterd.h
@@ -116,6 +116,7 @@ typedef enum glusterd_op_ {
GD_OP_BITROT,
GD_OP_DETACH_TIER,
GD_OP_TIER_MIGRATE,
+ GD_OP_SCRUB_STATUS,
GD_OP_MAX,
} glusterd_op_t;
@@ -276,6 +277,20 @@ typedef struct _auth auth_t;
#define CAPS_OFFLOAD_SNAPSHOT 0x00000008
#define CAPS_OFFLOAD_ZERO 0x00000020
+struct glusterd_bitrot_scrub_ {
+ char *scrub_state;
+ char *scrub_impact;
+ char *scrub_freq;
+ uint64_t scrubbed_files;
+ uint64_t unsigned_files;
+ uint64_t last_scrub_time;
+ uint64_t scrub_duration;
+ uint64_t error_count;
+};
+
+typedef struct glusterd_bitrot_scrub_ glusterd_bitrot_scrub_t;
+
+
struct glusterd_rebalance_ {
gf_defrag_status_t defrag_status;
uint64_t rebalance_files;
@@ -382,6 +397,9 @@ struct glusterd_volinfo_ {
/* Replace brick status */
glusterd_replace_brick_t rep_brick;
+ /* Bitrot scrub status*/
+ glusterd_bitrot_scrub_t bitrot_scrub;
+
int version;
uint32_t quota_conf_version;
uint32_t cksum;