diff options
Diffstat (limited to 'xlators/features/bit-rot/src/bitd/bit-rot.c')
-rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot.c | 146 |
1 files changed, 117 insertions, 29 deletions
diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.c b/xlators/features/bit-rot/src/bitd/bit-rot.c index 880b16edfa8..eea81aec53a 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.c +++ b/xlators/features/bit-rot/src/bitd/bit-rot.c @@ -29,15 +29,6 @@ #define BR_HASH_CALC_READ_SIZE (128 * 1024) -br_tbf_opspec_t opthrottle[] = { - { - .op = BR_TBF_OP_HASH, - .rate = BR_HASH_CALC_READ_SIZE, - .maxlimit = (2 * BR_WORKERS * BR_HASH_CALC_READ_SIZE), - }, - /** TODO: throttle getdents(), read() request(s) */ -}; - static int br_find_child_index (xlator_t *this, xlator_t *child) { @@ -1066,6 +1057,7 @@ br_enact_signer (xlator_t *this, br_child_t *child, br_stub_init_t *stub) child->threadrunning = 1; /* it's OK to continue, "old" objects would be signed when modified */ + list_del_init (&child->list); return 0; dealloc: @@ -1078,14 +1070,45 @@ static inline int32_t br_enact_scrubber (xlator_t *this, br_child_t *child) { int32_t ret = 0; + br_private_t *priv = NULL; + struct br_scanfs *fsscan = NULL; + struct br_scrubber *fsscrub = NULL; + + priv = this->private; + + fsscan = &child->fsscan; + fsscrub = &priv->fsscrub; + + LOCK_INIT (&fsscan->entrylock); + pthread_mutex_init (&fsscan->waitlock, NULL); + pthread_cond_init (&fsscan->waitcond, NULL); - ret = gf_thread_create (&child->thread, NULL, br_scrubber, child); + fsscan->entries = 0; + INIT_LIST_HEAD (&fsscan->queued); + INIT_LIST_HEAD (&fsscan->ready); + + ret = gf_thread_create (&child->thread, NULL, br_fsscanner, child); if (ret != 0) { - ret = -1; - gf_log (this->name, GF_LOG_ERROR, "failed to spawn scrubber"); + gf_log (this->name, GF_LOG_ALERT, "failed to spawn bitrot " + "scrubber daemon [Brick: %s]", child->brick_path); + goto error_return; } - return ret; + /** + * Everything has been setup.. add this subvolume to scrubbers + * list. + */ + pthread_mutex_lock (&fsscrub->mutex); + { + list_move (&child->list, &fsscrub->scrublist); + pthread_cond_broadcast (&fsscrub->cond); + } + pthread_mutex_unlock (&fsscrub->mutex); + + return 0; + + error_return: + return -1; } /** @@ -1202,8 +1225,7 @@ br_handle_events (void *arg) "failed to connect to the " "child (subvolume: %s)", child->xl->name); - else - list_del_init (&child->list); + } } @@ -1379,16 +1401,72 @@ br_init_signer (xlator_t *this, br_private_t *priv) return -1; } -int32_t -br_init_rate_limiter (br_private_t *priv) +/** + * For signer, only rate limit CPU usage (during hash calculation) when + * compiled with -DBR_RATE_LIMIT_SIGNER cflags, else let it run full + * throttle. + */ +static int32_t +br_rate_limit_signer (xlator_t *this, int child_count, int numbricks) { - br_tbf_opspec_t *spec = opthrottle; - priv->tbf = br_tbf_init (spec, sizeof (opthrottle) - / sizeof (br_tbf_opspec_t)); + br_private_t *priv = NULL; + br_tbf_opspec_t spec = {0,}; + + priv = this->private; + + spec.op = BR_TBF_OP_HASH; + spec.rate = 0; + spec.maxlimit = 0; + +#ifdef BR_RATE_LIMIT_SIGNER + + double contribution = 0; + contribution = ((double)1 - ((double)child_count / (double)numbricks)); + if (contribution == 0) + contribution = 1; + spec.rate = BR_HASH_CALC_READ_SIZE * contribution; + spec.maxlimit = BR_WORKERS * BR_HASH_CALC_READ_SIZE; + +#endif + + if (!spec.rate) + gf_log (this->name, + GF_LOG_INFO, "[Rate Limit Info] \"FULL THROTTLE\""); + else + gf_log (this->name, GF_LOG_INFO, + "[Rate Limit Info] \"tokens/sec (rate): %lu, " + "maxlimit: %lu\"", spec.rate, spec.maxlimit); + priv->tbf = br_tbf_init (&spec, 1); return priv->tbf ? 0 : -1; } +static int32_t +br_signer_init (xlator_t *this, br_private_t *priv) +{ + int32_t ret = 0; + int numbricks = 0; + + GF_OPTION_INIT ("expiry-time", priv->expiry_time, int32, error_return); + GF_OPTION_INIT ("brick-count", numbricks, int32, error_return); + + ret = br_rate_limit_signer (this, priv->child_count, numbricks); + if (ret) + goto error_return; + + ret = br_init_signer (this, priv); + if (ret) + goto cleanup_tbf; + + return 0; + + cleanup_tbf: + /* cleanup TBF */ + error_return: + return -1; + +} + int32_t init (xlator_t *this) { @@ -1410,7 +1488,6 @@ init (xlator_t *this) } GF_OPTION_INIT ("scrubber", priv->iamscrubber, bool, out); - GF_OPTION_INIT ("expiry-time", priv->expiry_time, int32, out); priv->child_count = xlator_subvolume_count (this); priv->children = GF_CALLOC (priv->child_count, sizeof (*priv->children), @@ -1443,18 +1520,19 @@ init (xlator_t *this) INIT_LIST_HEAD (&priv->children[i].list); INIT_LIST_HEAD (&priv->bricks); - ret = br_init_rate_limiter (priv); - if (ret) - goto cleanup_mutex; - this->private = priv; if (!priv->iamscrubber) { - ret = br_init_signer (this, priv); - if (ret) - goto cleanup_tbf; + ret = br_signer_init (this, priv); + } else { + ret = br_scrubber_init (this, priv); + if (!ret) + ret = br_scrubber_handle_options (this, priv, NULL); } + if (ret) + goto cleanup_mutex; + ret = gf_thread_create (&priv->thread, NULL, br_handle_events, this); if (ret != 0) { gf_log (this->name, GF_LOG_ERROR, @@ -1469,7 +1547,6 @@ init (xlator_t *this) return 0; } - cleanup_tbf: cleanup_mutex: (void) pthread_cond_destroy (&priv->cond); (void) pthread_mutex_destroy (&priv->lock); @@ -1505,6 +1582,17 @@ fini (xlator_t *this) return; } +int +reconfigure (xlator_t *this, dict_t *options) +{ + br_private_t *priv = this->private; + + if (!priv->iamscrubber) + return 0; + + return br_scrubber_handle_options (this, priv, options); +} + struct xlator_fops fops; struct xlator_cbks cbks; |