diff options
-rw-r--r-- | cli/src/cli-rpc-ops.c | 30 | ||||
-rw-r--r-- | tests/bitrot/bug-1207627-bitrot-scrub-status.t | 7 | ||||
-rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot-scrub.c | 137 | ||||
-rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot.c | 45 | ||||
-rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot.h | 25 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 17 |
6 files changed, 220 insertions, 41 deletions
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 022f5a1d5f3..d59ff8b6d2c 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -10730,7 +10730,11 @@ gf_cli_print_bitrot_scrub_status (dict_t *dict) uint64_t scrub_files = 0; uint64_t unsigned_files = 0; uint64_t scrub_time = 0; - uint64_t last_scrub = 0; + uint64_t days = 0; + uint64_t hour = 0; + uint64_t minut = 0; + uint64_t second = 0; + char *last_scrub = NULL; uint64_t error_count = 0; @@ -10784,8 +10788,12 @@ gf_cli_print_bitrot_scrub_status (dict_t *dict) for (i = 1; i <= count; i++) { /* Reset the variables to prevent carryover of values */ node_name = NULL; - last_scrub = 0; + last_scrub = NULL; scrub_time = 0; + days = 0; + hour = 0; + minut = 0; + second = 0; error_count = 0; scrub_files = 0; unsigned_files = 0; @@ -10819,7 +10827,7 @@ gf_cli_print_bitrot_scrub_status (dict_t *dict) memset (key, 0, 256); snprintf (key, 256, "last-scrub-time-%d", i); - ret = dict_get_uint64 (dict, key, &last_scrub); + ret = dict_get_str (dict, key, &last_scrub); if (ret) gf_log ("cli", GF_LOG_TRACE, "failed to get last scrub" " time"); @@ -10842,11 +10850,17 @@ gf_cli_print_bitrot_scrub_status (dict_t *dict) cli_out ("%s: %"PRIu64 "\n", "Number of Unsigned files", unsigned_files); - cli_out ("%s: %"PRIu64 "\n", "Last completed scrub time", - scrub_time); - - cli_out ("%s: %"PRIu64 "\n", "Duration of last scrub", - last_scrub); + cli_out ("%s: %s\n", "Last completed scrub time", + (*last_scrub) ? last_scrub : "Scrubber pending to " + "complete."); + + /* Printing last scrub duration time in human readable form*/ + days = scrub_time/86400; + hour = (scrub_time%86400)/3600; + minut = (scrub_time%86400%3600)/60; + second = (scrub_time%86400%3600%60); + cli_out ("%s: %"PRIu64 ":%"PRIu64 ":%"PRIu64 ":%"PRIu64 "\n", + "Duration of last scrub", days, hour, minut, second); cli_out ("%s: %"PRIu64 "\n", "Error count", error_count); diff --git a/tests/bitrot/bug-1207627-bitrot-scrub-status.t b/tests/bitrot/bug-1207627-bitrot-scrub-status.t index 0bbcb38cde2..bca3919e2ac 100644 --- a/tests/bitrot/bug-1207627-bitrot-scrub-status.t +++ b/tests/bitrot/bug-1207627-bitrot-scrub-status.t @@ -33,11 +33,4 @@ EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'hourly' scrub_status $V0 'Scrub frequency' EXPECT_WITHIN $PROCESS_UP_TIMEOUT '/var/log/glusterfs/bitd.log' scrub_status $V0 'Bitrot error log location' EXPECT_WITHIN $PROCESS_UP_TIMEOUT '/var/log/glusterfs/scrub.log' scrub_status $V0 'Scrubber error log location' -EXPECT_WITHIN $PROCESS_UP_TIMEOUT '0' scrub_status $V0 'Number of Scrubbed files' -EXPECT_WITHIN $PROCESS_UP_TIMEOUT '0' scrub_status $V0 'Number of Unsigned files' -EXPECT_WITHIN $PROCESS_UP_TIMEOUT '0' scrub_status $V0 'Last completed scrub time' -EXPECT_WITHIN $PROCESS_UP_TIMEOUT '0' scrub_status $V0 'Duration of last scrub' -EXPECT_WITHIN $PROCESS_UP_TIMEOUT '0' scrub_status $V0 'Error count' - - cleanup; diff --git a/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c b/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c index f776347e6d5..0a7212cd828 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c +++ b/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c @@ -74,6 +74,20 @@ bitd_fetch_signature (xlator_t *this, br_child_t *child, } +static void +br_inc_unsigned_file_count (xlator_t *this) +{ + br_private_t *priv = NULL; + + priv = this->private; + + pthread_mutex_lock (&priv->scrub_stat.lock); + { + priv->scrub_stat.unsigned_files++; + } + pthread_mutex_unlock (&priv->scrub_stat.lock); +} + /** * POST COMPUTE CHECK * @@ -107,6 +121,7 @@ bitd_scrub_post_compute_check (xlator_t *this, * The log entry looks pretty ugly, but helps in debugging.. */ if (signptr->stale || (signptr->version != version)) { + br_inc_unsigned_file_count (this); gf_msg_debug (this->name, 0, "<STAGE: POST> Object [GFID: %s] " "either has a stale signature OR underwent " "signing during checksumming {Stale: %d | " @@ -181,6 +196,7 @@ bitd_scrub_pre_compute_check (xlator_t *this, br_child_t *child, ret = bitd_signature_staleness (this, child, fd, &stale, version); if (!ret && stale) { + br_inc_unsigned_file_count (this); gf_msg_debug (this->name, 0, "<STAGE: PRE> Object [GFID: %s] " "has stale signature", uuid_utoa (fd->inode->gfid)); @@ -256,6 +272,16 @@ bitd_compare_ckum (xlator_t *this, return ret; } +static void +br_inc_scrubbed_file (br_private_t *priv) +{ + pthread_mutex_lock (&priv->scrub_stat.lock); + { + priv->scrub_stat.scrubbed_files++; + } + pthread_mutex_unlock (&priv->scrub_stat.lock); +} + /** * "The Scrubber" * @@ -266,19 +292,20 @@ bitd_compare_ckum (xlator_t *this, int br_scrubber_scrub_begin (xlator_t *this, struct br_fsscan_entry *fsentry) { - int32_t ret = -1; - fd_t *fd = NULL; - loc_t loc = {0, }; - struct iatt iatt = {0, }; - struct iatt parent_buf = {0, }; - pid_t pid = 0; - br_child_t *child = NULL; - unsigned char *md = NULL; - inode_t *linked_inode = NULL; - br_isignature_out_t *sign = NULL; - unsigned long signedversion = 0; - gf_dirent_t *entry = NULL; - loc_t *parent = NULL; + int32_t ret = -1; + fd_t *fd = NULL; + loc_t loc = {0, }; + struct iatt iatt = {0, }; + struct iatt parent_buf = {0, }; + pid_t pid = 0; + br_child_t *child = NULL; + unsigned char *md = NULL; + inode_t *linked_inode = NULL; + br_isignature_out_t *sign = NULL; + unsigned long signedversion = 0; + gf_dirent_t *entry = NULL; + br_private_t *priv = NULL; + loc_t *parent = NULL; GF_VALIDATE_OR_GOTO ("bit-rot", fsentry, out); @@ -286,9 +313,12 @@ br_scrubber_scrub_begin (xlator_t *this, struct br_fsscan_entry *fsentry) parent = &fsentry->parent; child = fsentry->data; + priv = this->private; + GF_VALIDATE_OR_GOTO ("bit-rot", entry, out); GF_VALIDATE_OR_GOTO ("bit-rot", parent, out); GF_VALIDATE_OR_GOTO ("bit-rot", child, out); + GF_VALIDATE_OR_GOTO ("bit-rot", priv, out); pid = GF_CLIENT_PID_SCRUB; @@ -375,6 +405,9 @@ br_scrubber_scrub_begin (xlator_t *this, struct br_fsscan_entry *fsentry) ret = bitd_compare_ckum (this, sign, md, linked_inode, entry, fd, child, &loc); + /* Increment of total number of scrubbed file counter */ + br_inc_scrubbed_file (priv); + GF_FREE (sign); /* alloced on post-compute */ /** fd_unref() takes care of closing fd.. like syncop_close() */ @@ -553,21 +586,72 @@ br_fsscan_deactivate (xlator_t *this, br_child_t *child) return 0; } +static void +br_update_scrub_start_time (xlator_t *this, struct timeval *tv) +{ + br_private_t *priv = NULL; + static int child; + + priv = this->private; + + + /* Setting scrubber starting time for first child only */ + if (child == 0) { + pthread_mutex_lock (&priv->scrub_stat.lock); + { + priv->scrub_stat.scrub_start_tv.tv_sec = tv->tv_sec; + } + pthread_mutex_unlock (&priv->scrub_stat.lock); + } + + if (++child == priv->up_children) { + child = 0; + } +} + +static void +br_update_scrub_finish_time (xlator_t *this, char *timestr, struct timeval *tv) +{ + br_private_t *priv = NULL; + static int child; + + priv = this->private; + + /*Setting scrubber finishing time at time time of last child operation*/ + if (++child == priv->up_children) { + pthread_mutex_lock (&priv->scrub_stat.lock); + { + priv->scrub_stat.scrub_end_tv.tv_sec = tv->tv_sec; + + priv->scrub_stat.scrub_duration = + priv->scrub_stat.scrub_end_tv.tv_sec - + priv->scrub_stat.scrub_start_tv.tv_sec; + + strncpy (priv->scrub_stat.last_scrub_time, timestr, + sizeof (priv->scrub_stat.last_scrub_time)); + + child = 0; + } + pthread_mutex_unlock (&priv->scrub_stat.lock); + } +} static void br_fsscanner_log_time (xlator_t *this, br_child_t *child, const char *sfx) { - struct timeval tv = {0,}; - char timestr[1024] = {0,}; + char timestr[1024] = {0,}; + struct timeval tv = {0,}; gettimeofday (&tv, NULL); gf_time_fmt (timestr, sizeof (timestr), tv.tv_sec, gf_timefmt_FT); if (strcasecmp (sfx, "started") == 0) { + br_update_scrub_start_time (this, &tv); gf_msg (this->name, GF_LOG_INFO, 0, BRB_MSG_SCRUB_START, "Scrubbing \"%s\" %s at %s", child->brick_path, sfx, timestr); } else { + br_update_scrub_finish_time (this, timestr, &tv); gf_msg (this->name, GF_LOG_INFO, 0, BRB_MSG_SCRUB_FINISH, "Scrubbing \"%s\" %s at %s", child->brick_path, sfx, timestr); @@ -575,14 +659,33 @@ br_fsscanner_log_time (xlator_t *this, br_child_t *child, const char *sfx) } static void -br_fsscanner_wait_until_kicked (struct br_scanfs *fsscan) +br_fsscanner_wait_until_kicked (xlator_t *this, struct br_scanfs *fsscan) { + static int i; + br_private_t *priv = NULL; + + priv = this->private; + pthread_cleanup_push (_br_lock_cleaner, &fsscan->wakelock); pthread_mutex_lock (&fsscan->wakelock); { while (!fsscan->kick) pthread_cond_wait (&fsscan->wakecond, &fsscan->wakelock); + + /* resetting total number of scrubbed file when scrubbing + * done for all of its children */ + if (i == priv->up_children) { + pthread_mutex_lock (&priv->scrub_stat.lock); + { + priv->scrub_stat.scrubbed_files = 0; + priv->scrub_stat.unsigned_files = 0; + i = 0; + } + pthread_mutex_unlock (&priv->scrub_stat.lock); + } + ++i; + fsscan->kick = _gf_false; } pthread_mutex_unlock (&fsscan->wakelock); @@ -640,7 +743,7 @@ br_fsscanner (void *arg) loc.inode = child->table->root; while (1) { - br_fsscanner_wait_until_kicked (fsscan); + br_fsscanner_wait_until_kicked (this, fsscan); { /* precursor for scrub */ br_fsscanner_entry_control (this, child); diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.c b/xlators/features/bit-rot/src/bitd/bit-rot.c index b28bf2622af..4ee2020aaf1 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.c +++ b/xlators/features/bit-rot/src/bitd/bit-rot.c @@ -1550,7 +1550,16 @@ int br_scrubber_status_get (xlator_t *this, dict_t **dict) { - int ret = -1; + int ret = -1; + char key[256] = {0,}; + br_private_t *priv = NULL; + struct br_scrub_stats *scrub_stats = NULL; + + priv = this->private; + + GF_VALIDATE_OR_GOTO ("bit-rot", priv, out); + + scrub_stats = &priv->scrub_stat; ret = br_get_bad_objects_list (this, dict); if (ret) { @@ -1558,6 +1567,40 @@ br_scrubber_status_get (xlator_t *this, dict_t **dict) "files"); } + memset (key, 0, 256); + snprintf (key, 256, "scrubbed-files"); + ret = dict_set_uint32 (*dict, key, scrub_stats->scrubbed_files); + if (ret) { + gf_msg_debug (this->name, 0, "Failed to setting scrubbed file " + "entry to the dictionary"); + } + + memset (key, 0, 256); + snprintf (key, 256, "unsigned-files"); + ret = dict_set_uint32 (*dict, key, scrub_stats->unsigned_files); + if (ret) { + gf_msg_debug (this->name, 0, "Failed to set unsigned file count" + " entry to the dictionary"); + } + + memset (key, 0, 256); + snprintf (key, 256, "scrub-duration"); + ret = dict_set_uint32 (*dict, key, scrub_stats->scrub_duration); + if (ret) { + gf_msg_debug (this->name, 0, "Failed to set scrub duration" + " entry to the dictionary"); + } + + memset (key, 0, 256); + snprintf (key, 256, "last-scrub-time"); + ret = dict_set_dynstr_with_alloc (*dict, key, + scrub_stats->last_scrub_time); + if (ret) { + gf_msg_debug (this->name, 0, "Failed to set " + "last scrub time value"); + } + +out: return ret; } diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.h b/xlators/features/bit-rot/src/bitd/bit-rot.h index 16892a7e3fd..04336e641d0 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.h +++ b/xlators/features/bit-rot/src/bitd/bit-rot.h @@ -154,6 +154,26 @@ struct br_scrubber { typedef struct br_obj_n_workers br_obj_n_workers_t; +typedef struct br_private br_private_t; + +typedef void (*br_scrubbed_file_update) (br_private_t *priv); + +struct br_scrub_stats { + uint32_t scrubbed_files; /* Total number of scrubbed file */ + + uint32_t unsigned_files; /* Total number of unsigned file */ + + uint32_t scrub_duration; /* Duration of last scrub */ + + char last_scrub_time[1024]; /*last scrub completion time */ + + struct timeval scrub_start_tv; /* Scrubbing starting time*/ + + struct timeval scrub_end_tv; /* Scrubbing finishing time */ + + pthread_mutex_t lock; +}; + struct br_private { pthread_mutex_t lock; @@ -179,17 +199,18 @@ struct br_private { and ready to be picked up for signing and the workers which sign the objects */ + uint32_t expiry_time; /* objects "wait" time */ br_tbf_t *tbf; /* token bucket filter */ gf_boolean_t iamscrubber; /* function as a fs scrubber */ + struct br_scrub_stats scrub_stat; /* statistics of scrub*/ + struct br_scrubber fsscrub; /* scrubbers for this subvolume */ }; -typedef struct br_private br_private_t; - struct br_object { xlator_t *this; diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index d24c3dff12d..a388ac113c8 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -8326,7 +8326,8 @@ glusterd_volume_bitrot_scrub_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict) uint64_t scrubbed_files = 0; uint64_t unsigned_files = 0; uint64_t scrub_duration = 0; - uint64_t last_scrub_time = 0; + char *last_scrub_time = NULL; + char *scrub_time = NULL; char *volname = NULL; char *node_uuid = NULL; char *node_uuid_str = NULL; @@ -8418,11 +8419,12 @@ glusterd_volume_bitrot_scrub_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict) memset (key, 0, 256); snprintf (key, 256, "last-scrub-time-%d", src_count); - ret = dict_get_uint64 (rsp_dict, key, &value); + ret = dict_get_str (rsp_dict, key, &last_scrub_time); if (!ret) { + scrub_time = gf_strdup (last_scrub_time); memset (key, 0, 256); snprintf (key, 256, "last-scrub-time-%d", src_count+dst_count); - ret = dict_set_uint64 (aggr, key, value); + ret = dict_set_dynstr (aggr, key, scrub_time); if (ret) { gf_msg_debug (this->name, 0, "Failed to set " "last scrub time value"); @@ -8544,7 +8546,8 @@ glusterd_bitrot_volume_node_rsp (dict_t *aggr, dict_t *rsp_dict) uint64_t scrubbed_files = 0; uint64_t unsigned_files = 0; uint64_t scrub_duration = 0; - uint64_t last_scrub_time = 0; + char *last_scrub_time = NULL; + char *scrub_time = NULL; char *volname = NULL; char *node_str = NULL; char *scrub_freq = NULL; @@ -8685,11 +8688,13 @@ glusterd_bitrot_volume_node_rsp (dict_t *aggr, dict_t *rsp_dict) } } - ret = dict_get_uint64 (rsp_dict, "last-scrub-time", &value); + ret = dict_get_str (rsp_dict, "last-scrub-time", &last_scrub_time); if (!ret) { memset (key, 0, 256); snprintf (key, 256, "last-scrub-time-%d", i); - ret = dict_set_uint64 (aggr, key, value); + + scrub_time = gf_strdup (last_scrub_time); + ret = dict_set_dynstr (aggr, key, scrub_time); if (ret) { gf_msg_debug (this->name, 0, "Failed to set " "last scrub time value"); |