summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGaurav Kumar Garg <ggarg@redhat.com>2015-05-06 14:23:34 +0530
committerVijay Bellur <vbellur@redhat.com>2015-05-10 00:26:01 -0700
commit7c1415fa591172765ab1e7dc1b049bf162d53788 (patch)
tree8fa72a5b9968b7bf35cb7846441e08291ebcaf9e
parent1a27c2edd6d49118a73da2f30deccb4a91bebad2 (diff)
features/bitrot: scrubber should crawl based on the scrubber frequency value
Currently scrubber is crawling all the files continuously. It should crawl files based on the scrubber frequency which user have set. By default scrubber crawling frequency value will be biweekly. Change-Id: I5762a92c1e700134cfe4283d1f631904adbfe31d BUG: 1208131 Signed-off-by: Gaurav Kumar Garg <ggarg@redhat.com> Reviewed-on: http://review.gluster.org/10602 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Raghavendra Bhat <raghavendra@redhat.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot-scrub.c191
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot.c1
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot.h5
3 files changed, 192 insertions, 5 deletions
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 e96d82d6282..390148fdb06 100644
--- a/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c
+++ b/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c
@@ -508,13 +508,121 @@ br_fsscanner_handle_entry (xlator_t *subvol,
return -1;
}
+/*scrubber frequency tunable value in second (day * hour * minut * second)*/
+#define DAILY (1*24*60*60)
+#define WEEKLY (7*24*60*60)
+#define BIWEEKLY (14*24*60*60)
+#define MONTHLY (30*24*60*60)
+
+struct timeval
+br_scrubber_calc_freq (xlator_t *this)
+{
+ br_private_t *priv = NULL;
+ struct timeval scrub_sec = {0,};
+
+ priv = this->private;
+
+ /*By default scrubber frequency will be biweekly*/
+ if (!strncmp (priv->scrub_freq, "daily", strlen("daily"))) {
+ scrub_sec.tv_sec = DAILY;
+ } else if (!strncmp (priv->scrub_freq, "weekly", strlen("weekly"))) {
+ scrub_sec.tv_sec = WEEKLY;
+ } else if (!strncmp (priv->scrub_freq, "monthly", strlen("monthly"))) {
+ scrub_sec.tv_sec = MONTHLY;
+ } else if (!strncmp (priv->scrub_freq, "biweekly",
+ strlen("biweekly"))) {
+ scrub_sec.tv_sec = BIWEEKLY;
+ } else {
+ gf_log (this->name, GF_LOG_ERROR, "Invalid scrub-frequency %s"
+ "value.", priv->scrub_freq);
+ scrub_sec.tv_sec = -1;
+ }
+
+ return scrub_sec;
+}
+
+#define SCRUBBER_SLEEP(freq_diff, elapse_time) do { \
+ \
+ if (freq_diff < 0) { \
+ return 0; \
+ } else if (freq_diff <= DAILY) { \
+ gf_log (this->name, GF_LOG_INFO, \
+ "Scrubber is sleeping for %ld " \
+ "sec", freq_diff); \
+ sleep (freq_diff); \
+ return 0; \
+ } else { \
+ gf_log (this->name, GF_LOG_INFO, \
+ "Scrubber is sleeping for %ld " \
+ "sec", freq_diff); \
+ sleep (DAILY); \
+ elapse_time += DAILY; \
+ } \
+ } while (0)
+
+static int
+br_scrubber_sleep_check (struct timeval *begin, struct timeval *end,
+ xlator_t *this)
+{
+ br_private_t *priv = NULL;
+ struct timeval elapse_time = {0,};
+ struct timeval freq_diff = {0,};
+ struct timeval scrub_sec = {0,};
+ struct timeval temp = {0,};
+
+ priv = this->private;
+
+ scrub_sec = br_scrubber_calc_freq (this);
+ if (scrub_sec.tv_sec == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "Unable to calculate scrub "
+ "frequency %s value", priv->scrub_freq);
+ return -1;
+ }
+
+ if ((end->tv_sec - begin->tv_sec) < scrub_sec.tv_sec) {
+ /* Sleep, if scrubber have completed its job before schedule
+ * scrub frequency based on current scrub frequency value */
+ do {
+ scrub_sec = br_scrubber_calc_freq (this);
+ freq_diff.tv_sec = scrub_sec.tv_sec - (end->tv_sec -
+ begin->tv_sec) -
+ elapse_time.tv_sec;
+ SCRUBBER_SLEEP(freq_diff.tv_sec, elapse_time.tv_sec);
+ } while (1);
+
+
+ } else {
+ /* Sleep, if scrubber have completed its job after schedule
+ * scrub frequency based on current scrub frequency value */
+ temp.tv_sec = (end->tv_sec - begin->tv_sec) % scrub_sec.tv_sec;
+ if (temp.tv_sec != 0) {
+ do {
+ scrub_sec = br_scrubber_calc_freq (this);
+ freq_diff.tv_sec = scrub_sec.tv_sec
+ - temp.tv_sec
+ - elapse_time.tv_sec;
+ SCRUBBER_SLEEP(freq_diff.tv_sec,
+ elapse_time.tv_sec);
+ } while (1);
+ }
+ }
+
+ return 0;
+}
+
void *
br_fsscanner (void *arg)
{
- loc_t loc = {0,};
- xlator_t *this = NULL;
- br_child_t *child = NULL;
- struct br_scanfs *fsscan = NULL;
+ int32_t ret = -1;
+ loc_t loc = {0,};
+ char timestr[1024] = {0,};
+ xlator_t *this = NULL;
+ br_child_t *child = NULL;
+ struct br_scanfs *fsscan = NULL;
+ br_private_t *priv = NULL;
+ struct timeval elapse_time = {0,};
+ struct timeval scrub_sec = {0,};
+ struct timeval freq_diff = {0,};
child = arg;
this = child->this;
@@ -522,13 +630,73 @@ br_fsscanner (void *arg)
THIS = this;
+ priv = this->private;
+
loc.inode = child->table->root;
+
+ /* Scrubber should start scrubbing the filesystem *after* the
+ * schedueled scrub-frequency has expired.*/
+ do {
+ /*Calculate current scrub frequency value in second*/
+ scrub_sec = br_scrubber_calc_freq (this);
+ if (scrub_sec.tv_sec == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "Unable to calculate "
+ "scrub frequency %s value", priv->scrub_freq);
+ return NULL;
+ }
+
+ freq_diff.tv_sec = scrub_sec.tv_sec - elapse_time.tv_sec;
+
+ if (freq_diff.tv_sec < 0) {
+ break;
+ } else if (freq_diff.tv_sec == DAILY) {
+ sleep (DAILY);
+ break;
+ } else {
+ sleep (DAILY);
+ elapse_time.tv_sec += DAILY;
+ }
+
+ } while (1);
+
while (1) {
+ /* log scrub start time */
+ gettimeofday (&priv->tv_before_scrub, NULL);
+ gf_time_fmt (timestr, sizeof timestr,
+ priv->tv_before_scrub.tv_sec, gf_timefmt_FT);
+ gf_log (this->name, GF_LOG_INFO,
+ "Scrubbing \"%s\" started at %s",
+ child->brick_path, timestr);
+
+ /* scrub */
(void) syncop_ftw (child->xl, &loc,
GF_CLIENT_PID_SCRUB,
child, br_fsscanner_handle_entry);
if (!list_empty (&fsscan->queued))
wait_for_scrubbing (this, fsscan);
+
+ gettimeofday (&priv->tv_after_scrub, NULL);
+ /* log scrub finish time */
+ gf_time_fmt (timestr, sizeof timestr,
+ priv->tv_after_scrub.tv_sec, gf_timefmt_FT);
+ gf_log (this->name, GF_LOG_INFO,
+ "Scrubbing \"%s\" finished at %s",
+ child->brick_path, timestr);
+
+ /* Scrubber should sleep if it have completed scrubbing
+ * of filesystem before the scheduled scrub-frequency*/
+ ret = br_scrubber_sleep_check (&priv->tv_before_scrub,
+ &priv->tv_after_scrub,
+ this);
+ if (!ret) {
+ gf_log (this->name, GF_LOG_DEBUG, "scrubber is crawling"
+ " file system with scrubber frequency %s",
+ priv->scrub_freq);
+ } else {
+ gf_log (this->name, GF_LOG_ERROR, "Unable to perform "
+ "scrubber sleep check for scrubber frequency");
+ return NULL;
+ }
}
return NULL;
@@ -920,7 +1088,16 @@ br_scrubber_handle_stall (xlator_t *this, br_private_t *priv,
return -1;
}
-/* TODO: frequency */
+static int32_t
+br_scrubber_handle_freq (xlator_t *this, br_private_t *priv, dict_t *options)
+{
+ int32_t ret = -1;
+
+ ret = br_scrubber_fetch_option (this, "scrub-freq", options,
+ &priv->scrub_freq);
+ return ret;
+}
+
int32_t
br_scrubber_handle_options (xlator_t *this, br_private_t *priv, dict_t *options)
{
@@ -935,6 +1112,10 @@ br_scrubber_handle_options (xlator_t *this, br_private_t *priv, dict_t *options)
if (ret)
goto error_return;
+ ret = br_scrubber_handle_freq (this, priv, options);
+ if (ret)
+ goto error_return;
+
return 0;
error_return:
diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.c b/xlators/features/bit-rot/src/bitd/bit-rot.c
index 61d461f897b..b9adbd6647c 100644
--- a/xlators/features/bit-rot/src/bitd/bit-rot.c
+++ b/xlators/features/bit-rot/src/bitd/bit-rot.c
@@ -1728,6 +1728,7 @@ struct volume_options options[] = {
},
{ .key = {"scrub-freq"},
.type = GF_OPTION_TYPE_STR,
+ .default_value = "biweekly",
.description = "Scrub frequency for volume <VOLNAME>",
},
{ .key = {"scrub-state"},
diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.h b/xlators/features/bit-rot/src/bitd/bit-rot.h
index bbaf86fa65f..1705f715f0c 100644
--- a/xlators/features/bit-rot/src/bitd/bit-rot.h
+++ b/xlators/features/bit-rot/src/bitd/bit-rot.h
@@ -139,6 +139,11 @@ struct br_private {
gf_boolean_t iamscrubber; /* function as a fs scrubber */
struct br_scrubber fsscrub; /* scrubbers for this subvolume */
+
+ char *scrub_freq; /* Scrubber frequency*/
+
+ struct timeval tv_before_scrub; /* time before starting scrubbing*/
+ struct timeval tv_after_scrub; /* time after scrubbing completion*/
};
typedef struct br_private br_private_t;