diff options
| author | Gaurav Kumar Garg <ggarg@redhat.com> | 2015-05-06 14:23:34 +0530 | 
|---|---|---|
| committer | Niels de Vos <ndevos@redhat.com> | 2015-05-10 06:03:46 -0700 | 
| commit | d1d54d027fc616ccae5c329d5b5f02ee9aab1549 (patch) | |
| tree | 52f30156f7174ede081bfd47142c66a4135045eb | |
| parent | 1075351f0289a7a9774e8fb221a082aaeaf848f3 (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: 1220068
Signed-off-by: Gaurav Kumar Garg <ggarg@redhat.com>
Reviewed-on: http://review.gluster.org/10739
Tested-by: NetBSD Build System
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Niels de Vos <ndevos@redhat.com>
| -rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot-scrub.c | 191 | ||||
| -rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot.c | 1 | ||||
| -rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot.h | 5 | 
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 5638b0f348b..0bb2f2ab8e6 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.c +++ b/xlators/features/bit-rot/src/bitd/bit-rot.c @@ -1622,6 +1622,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 66515e3213c..d2cf3b07b4d 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;  | 
