diff options
author | Kotresh HR <khiremat@redhat.com> | 2020-02-03 18:10:17 +0530 |
---|---|---|
committer | Kotresh HR <khiremat@redhat.com> | 2020-02-07 12:00:19 +0530 |
commit | 8fad76650bd85463708f59d2518f5b764ae4c702 (patch) | |
tree | e72357381dffcdeb2d08fa59bca805eec21664c2 | |
parent | 2dbbdc92be205d12901ce2770570bbcb17040838 (diff) |
bitrot: Make number of signer threads configurable
The number of signing process threads (glfs_brpobj)
is set to 4 by default. The recommendation is to set
it to number of cores available. This patch makes it
configurable as follows
gluster vol bitrot <volname> signer-threads <count>
fixes: bz#1797869
Change-Id: Ia883b3e5e34e0bc8d095243508d320c9c9c58adc
Signed-off-by: Kotresh HR <khiremat@redhat.com>
-rw-r--r-- | cli/src/cli-cmd-parser.c | 33 | ||||
-rw-r--r-- | cli/src/cli-cmd-volume.c | 12 | ||||
-rw-r--r-- | doc/gluster.8 | 6 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs/common-utils.h | 1 | ||||
-rw-r--r-- | rpc/xdr/src/cli1-xdr.x | 1 | ||||
-rw-r--r-- | tests/bitrot/br-signer-threads-config-1797869.t | 73 | ||||
-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 | 20 | ||||
-rw-r--r-- | xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-bitrot.c | 85 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 6 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-set.c | 9 |
12 files changed, 267 insertions, 25 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index aeac4c7c697..875f1c3fbe3 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -5587,9 +5587,9 @@ cli_cmd_bitrot_parse(const char **words, int wordcount, dict_t **options) int32_t ret = -1; char *w = NULL; char *volname = NULL; - static char *opwords[] = { - "enable", "disable", "scrub-throttle", "scrub-frequency", "scrub", - "signing-time", NULL}; + static char *opwords[] = {"enable", "disable", "scrub-throttle", + "scrub-frequency", "scrub", "signing-time", + "signer-threads", NULL}; static char *scrub_throt_values[] = {"lazy", "normal", "aggressive", NULL}; static char *scrub_freq_values[] = { "hourly", "daily", "weekly", "biweekly", "monthly", "minute", NULL}; @@ -5598,6 +5598,7 @@ cli_cmd_bitrot_parse(const char **words, int wordcount, dict_t **options) dict_t *dict = NULL; gf_bitrot_type type = GF_BITROT_OPTION_TYPE_NONE; int32_t expiry_time = 0; + int32_t signer_th_count = 0; GF_ASSERT(words); GF_ASSERT(options); @@ -5778,6 +5779,31 @@ cli_cmd_bitrot_parse(const char **words, int wordcount, dict_t **options) } goto set_type; } + } else if (!strcmp(words[3], "signer-threads")) { + if (!words[4]) { + cli_err( + "Missing signer-thread value for bitrot " + "option"); + ret = -1; + goto out; + } else { + type = GF_BITROT_OPTION_TYPE_SIGNER_THREADS; + + signer_th_count = strtol(words[4], NULL, 0); + if (signer_th_count < 1) { + cli_err("signer-thread count should not be less than 1"); + ret = -1; + goto out; + } + + ret = dict_set_uint32(dict, "signer-threads", + (unsigned int)signer_th_count); + if (ret) { + cli_out("Failed to set dict for bitrot"); + goto out; + } + goto set_type; + } } else { cli_err( "Invalid option %s for bitrot. Please enter valid " @@ -5786,7 +5812,6 @@ cli_cmd_bitrot_parse(const char **words, int wordcount, dict_t **options) ret = -1; goto out; } - set_type: ret = dict_set_int32(dict, "type", type); if (ret < 0) diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index e6144932144..82b4a7da225 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -2967,6 +2967,16 @@ struct cli_cmd bitrot_cmds[] = { {"volume bitrot <VOLNAME> {enable|disable}", NULL, /*cli_cmd_bitrot_cbk,*/ "Enable/disable bitrot for volume <VOLNAME>"}, + {"volume bitrot <VOLNAME> signing-time <time-in-secs>", + NULL, /*cli_cmd_bitrot_cbk,*/ + "Waiting time for an object after last fd is closed to start signing " + "process"}, + + {"volume bitrot <VOLNAME> signer-threads <count>", + NULL, /*cli_cmd_bitrot_cbk,*/ + "Number of signing process threads. Usually set to number of available " + "cores"}, + {"volume bitrot <VOLNAME> scrub-throttle {lazy|normal|aggressive}", NULL, /*cli_cmd_bitrot_cbk,*/ "Set the speed of the scrubber for volume <VOLNAME>"}, @@ -2982,6 +2992,8 @@ struct cli_cmd bitrot_cmds[] = { "the scrubber. ondemand starts the scrubber immediately."}, {"volume bitrot <VOLNAME> {enable|disable}\n" + "volume bitrot <VOLNAME> signing-time <time-in-secs>\n" + "volume bitrot <VOLNAME> signer-threads <count>\n" "volume bitrot <volname> scrub-throttle {lazy|normal|aggressive}\n" "volume bitrot <volname> scrub-frequency {hourly|daily|weekly|biweekly" "|monthly}\n" diff --git a/doc/gluster.8 b/doc/gluster.8 index f9f7d400663..d2bb4a087d1 100644 --- a/doc/gluster.8 +++ b/doc/gluster.8 @@ -218,6 +218,12 @@ Use "!<OPTION>" to reset option <OPTION> to default value. \fB\ volume bitrot <VOLNAME> {enable|disable} \fR Enable/disable bitrot for volume <VOLNAME> .TP +\fB\ volume bitrot <VOLNAME> signing-time <time-in-secs> \fR +Waiting time for an object after last fd is closed to start signing process. +.TP +\fB\ volume bitrot <VOLNAME> signer-threads <count> \fR +Number of signing process threads. Usually set to number of available cores. +.TP \fB\ volume bitrot <VOLNAME> scrub-throttle {lazy|normal|aggressive} \fR Scrub-throttle value is a measure of how fast or slow the scrubber scrubs the filesystem for volume <VOLNAME> .TP diff --git a/libglusterfs/src/glusterfs/common-utils.h b/libglusterfs/src/glusterfs/common-utils.h index f6d82cc0b85..dd73a240c59 100644 --- a/libglusterfs/src/glusterfs/common-utils.h +++ b/libglusterfs/src/glusterfs/common-utils.h @@ -123,6 +123,7 @@ trap(void); /* Default value of signing waiting time to sign a file for bitrot */ #define SIGNING_TIMEOUT "120" +#define BR_WORKERS "4" /* xxhash */ #define GF_XXH64_DIGEST_LENGTH 8 diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index a32c8645708..777cb0046a2 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -68,6 +68,7 @@ enum gf_bitrot_type { GF_BITROT_OPTION_TYPE_EXPIRY_TIME, GF_BITROT_CMD_SCRUB_STATUS, GF_BITROT_CMD_SCRUB_ONDEMAND, + GF_BITROT_OPTION_TYPE_SIGNER_THREADS, GF_BITROT_OPTION_TYPE_MAX }; diff --git a/tests/bitrot/br-signer-threads-config-1797869.t b/tests/bitrot/br-signer-threads-config-1797869.t new file mode 100644 index 00000000000..657ef3eedaf --- /dev/null +++ b/tests/bitrot/br-signer-threads-config-1797869.t @@ -0,0 +1,73 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../cluster.rc + +function get_bitd_count_1 { + ps auxww | grep glusterfs | grep bitd.pid | grep -v grep | grep $H1 | wc -l +} + +function get_bitd_count_2 { + ps auxww | grep glusterfs | grep bitd.pid | grep -v grep | grep $H2 | wc -l +} + +function get_bitd_pid_1 { + ps auxww | grep glusterfs | grep bitd.pid | grep -v grep | grep $H1 | awk '{print $2}' +} + +function get_bitd_pid_2 { + ps auxww | grep glusterfs | grep bitd.pid | grep -v grep | grep $H2 | awk '{print $2}' +} + +function get_signer_th_count_1 { + ps -eL | grep $(get_bitd_pid_1) | grep glfs_brpobj | wc -l +} + +function get_signer_th_count_2 { + ps -eL | grep $(get_bitd_pid_2) | grep glfs_brpobj | wc -l +} + +cleanup; + +TEST launch_cluster 2 + +TEST $CLI_1 peer probe $H2; +EXPECT_WITHIN $PROBE_TIMEOUT 1 peer_count; + +TEST $CLI_1 volume create $V0 $H1:$B1 +TEST $CLI_1 volume create $V1 $H2:$B2 +EXPECT 'Created' volinfo_field_1 $V0 'Status'; +EXPECT 'Created' volinfo_field_1 $V1 'Status'; + +TEST $CLI_1 volume start $V0 +TEST $CLI_1 volume start $V1 +EXPECT 'Started' volinfo_field_1 $V0 'Status'; +EXPECT 'Started' volinfo_field_1 $V1 'Status'; + +#Enable bitrot +TEST $CLI_1 volume bitrot $V0 enable +TEST $CLI_1 volume bitrot $V1 enable +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count_1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count_2 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "4" get_signer_th_count_1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "4" get_signer_th_count_2 + +old_bitd_pid_1=$(get_bitd_pid_1) +old_bitd_pid_2=$(get_bitd_pid_2) +TEST $CLI_1 volume bitrot $V0 signer-threads 1 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_signer_th_count_1 +EXPECT_NOT "$old_bitd_pid_1" get_bitd_pid_1; +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "4" get_signer_th_count_2 +EXPECT "$old_bitd_pid_2" get_bitd_pid_2; + +old_bitd_pid_1=$(get_bitd_pid_1) +old_bitd_pid_2=$(get_bitd_pid_2) +TEST $CLI_1 volume bitrot $V1 signer-threads 2 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "2" get_signer_th_count_2 +EXPECT_NOT "$old_bitd_pid_2" get_bitd_pid_2; +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_signer_th_count_1 +EXPECT "$old_bitd_pid_1" get_bitd_pid_1; + +cleanup; diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.c b/xlators/features/bit-rot/src/bitd/bit-rot.c index abb078b21cf..a2f1c343a1d 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.c +++ b/xlators/features/bit-rot/src/bitd/bit-rot.c @@ -1717,22 +1717,26 @@ out: return 0; } -/** - * Initialize signer specific structures, spawn worker threads. - */ - static void br_fini_signer(xlator_t *this, br_private_t *priv) { int i = 0; - for (; i < BR_WORKERS; i++) { + if (priv == NULL) + return; + + for (; i < priv->signer_th_count; i++) { (void)gf_thread_cleanup_xint(priv->obj_queue->workers[i]); } + GF_FREE(priv->obj_queue->workers); pthread_cond_destroy(&priv->object_cond); } +/** + * Initialize signer specific structures, spawn worker threads. + */ + static int32_t br_init_signer(xlator_t *this, br_private_t *priv) { @@ -1752,7 +1756,12 @@ br_init_signer(xlator_t *this, br_private_t *priv) goto cleanup_cond; INIT_LIST_HEAD(&priv->obj_queue->objects); - for (i = 0; i < BR_WORKERS; i++) { + priv->obj_queue->workers = GF_CALLOC( + priv->signer_th_count, sizeof(pthread_t), gf_br_mt_br_worker_t); + if (!priv->obj_queue->workers) + goto cleanup_obj_queue; + + for (i = 0; i < priv->signer_th_count; i++) { ret = gf_thread_create(&priv->obj_queue->workers[i], NULL, br_process_object, this, "brpobj"); if (ret != 0) { @@ -1769,7 +1778,9 @@ cleanup_threads: for (i--; i >= 0; i--) { (void)gf_thread_cleanup_xint(priv->obj_queue->workers[i]); } + GF_FREE(priv->obj_queue->workers); +cleanup_obj_queue: GF_FREE(priv->obj_queue); cleanup_cond: @@ -1822,7 +1833,7 @@ br_rate_limit_signer(xlator_t *this, int child_count, int numbricks) if (contribution == 0) contribution = 1; spec.rate = BR_HASH_CALC_READ_SIZE * contribution; - spec.maxlimit = BR_WORKERS * BR_HASH_CALC_READ_SIZE; + spec.maxlimit = priv->signer_th_count * BR_HASH_CALC_READ_SIZE; #endif @@ -1841,11 +1852,16 @@ br_rate_limit_signer(xlator_t *this, int child_count, int numbricks) static int32_t br_signer_handle_options(xlator_t *this, br_private_t *priv, dict_t *options) { - if (options) + if (options) { GF_OPTION_RECONF("expiry-time", priv->expiry_time, options, uint32, error_return); - else + GF_OPTION_RECONF("signer-threads", priv->signer_th_count, options, + uint32, error_return); + } else { GF_OPTION_INIT("expiry-time", priv->expiry_time, uint32, error_return); + GF_OPTION_INIT("signer-threads", priv->signer_th_count, uint32, + error_return); + } return 0; @@ -1861,6 +1877,8 @@ br_signer_init(xlator_t *this, br_private_t *priv) GF_OPTION_INIT("expiry-time", priv->expiry_time, uint32, error_return); GF_OPTION_INIT("brick-count", numbricks, int32, error_return); + GF_OPTION_INIT("signer-threads", priv->signer_th_count, uint32, + error_return); ret = br_rate_limit_signer(this, priv->child_count, numbricks); if (ret) @@ -2187,6 +2205,15 @@ struct volume_options options[] = { .description = "Pause/Resume scrub. Upon resume, scrubber " "continues from where it left off.", }, + { + .key = {"signer-threads"}, + .type = GF_OPTION_TYPE_INT, + .default_value = BR_WORKERS, + .op_version = {GD_OP_VERSION_8_0}, + .flags = OPT_FLAG_SETTABLE, + .description = "Number of signing process threads. As a best " + "practice, set this to the number of processor cores", + }, {.key = {NULL}}, }; diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.h b/xlators/features/bit-rot/src/bitd/bit-rot.h index a4d4fd74198..8ac7dcdac3d 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.h +++ b/xlators/features/bit-rot/src/bitd/bit-rot.h @@ -30,12 +30,6 @@ #include <openssl/sha.h> -/** - * TODO: make this configurable. As a best practice, set this to the - * number of processor cores. - */ -#define BR_WORKERS 4 - typedef enum scrub_throttle { BR_SCRUB_THROTTLE_VOID = -1, BR_SCRUB_THROTTLE_LAZY = 0, @@ -108,12 +102,12 @@ struct br_child { typedef struct br_child br_child_t; struct br_obj_n_workers { - struct list_head objects; /* queue of objects expired from the - timer wheel and ready to be picked - up for signing */ - pthread_t workers[BR_WORKERS]; /* Threads which pick up the objects - from the above queue and start - signing each object */ + struct list_head objects; /* queue of objects expired from the + timer wheel and ready to be picked + up for signing */ + pthread_t *workers; /* Threads which pick up the objects + from the above queue and start + signing each object */ }; struct br_scrubber { @@ -209,6 +203,8 @@ struct br_private { uint32_t expiry_time; /* objects "wait" time */ + uint32_t signer_th_count; /* Number of signing process threads */ + tbf_t *tbf; /* token bucket filter */ gf_boolean_t iamscrubber; /* function as a fs scrubber */ diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h b/xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h index 40bcda110e6..9d93caf069f 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h @@ -29,6 +29,7 @@ enum br_mem_types { gf_br_stub_mt_sigstub_t, gf_br_mt_br_child_event_t, gf_br_stub_mt_misc, + gf_br_mt_br_worker_t, gf_br_stub_mt_end, }; diff --git a/xlators/mgmt/glusterd/src/glusterd-bitrot.c b/xlators/mgmt/glusterd/src/glusterd-bitrot.c index 9959a59e40c..37429fe9214 100644 --- a/xlators/mgmt/glusterd/src/glusterd-bitrot.c +++ b/xlators/mgmt/glusterd/src/glusterd-bitrot.c @@ -34,6 +34,7 @@ const char *gd_bitrot_op_list[GF_BITROT_OPTION_TYPE_MAX] = { [GF_BITROT_OPTION_TYPE_SCRUB_FREQ] = "scrub-frequency", [GF_BITROT_OPTION_TYPE_SCRUB] = "scrub", [GF_BITROT_OPTION_TYPE_EXPIRY_TIME] = "expiry-time", + [GF_BITROT_OPTION_TYPE_SIGNER_THREADS] = "signer-threads", }; int @@ -354,6 +355,81 @@ out: return ret; } +static gf_boolean_t +is_bitd_configure_noop(xlator_t *this, glusterd_volinfo_t *volinfo) +{ + gf_boolean_t noop = _gf_true; + glusterd_brickinfo_t *brickinfo = NULL; + + if (!glusterd_is_bitrot_enabled(volinfo)) + goto out; + else if (volinfo->status != GLUSTERD_STATUS_STARTED) + goto out; + else { + cds_list_for_each_entry(brickinfo, &volinfo->bricks, brick_list) + { + if (!glusterd_is_local_brick(this, volinfo, brickinfo)) + continue; + noop = _gf_false; + return noop; + } + } +out: + return noop; +} + +static int +glusterd_bitrot_signer_threads(glusterd_volinfo_t *volinfo, dict_t *dict, + char *key, char **op_errstr) +{ + int32_t ret = -1; + uint32_t signer_th_count = 0; + uint32_t existing_th_count = 0; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + char dkey[32] = { + 0, + }; + + this = THIS; + GF_ASSERT(this); + + priv = this->private; + GF_VALIDATE_OR_GOTO(this->name, priv, out); + + ret = dict_get_uint32(dict, "signer-threads", &signer_th_count); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_GET_FAILED, + "Unable to get bitrot signer thread count."); + goto out; + } + + ret = dict_get_uint32(volinfo->dict, key, &existing_th_count); + if (ret == 0 && signer_th_count == existing_th_count) { + goto out; + } + + snprintf(dkey, sizeof(dkey), "%d", signer_th_count); + ret = dict_set_dynstr_with_alloc(volinfo->dict, key, dkey); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_DICT_SET_FAILED, + "Failed to set option %s", key); + goto out; + } + + if (!is_bitd_configure_noop(this, volinfo)) { + ret = priv->bitd_svc.manager(&(priv->bitd_svc), NULL, + PROC_START_NO_WAIT); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BITDSVC_RECONF_FAIL, + "Failed to reconfigure bitrot services"); + goto out; + } + } +out: + return ret; +} + static int glusterd_bitrot_enable(glusterd_volinfo_t *volinfo, char **op_errstr) { @@ -594,6 +670,15 @@ glusterd_op_bitrot(dict_t *dict, char **op_errstr, dict_t *rsp_dict) volinfo, dict, "features.expiry-time", op_errstr); if (ret) goto out; + break; + + case GF_BITROT_OPTION_TYPE_SIGNER_THREADS: + ret = glusterd_bitrot_signer_threads( + volinfo, dict, "features.signer-threads", op_errstr); + if (ret) + goto out; + break; + case GF_BITROT_CMD_SCRUB_STATUS: case GF_BITROT_CMD_SCRUB_ONDEMAND: break; diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index d9e5e865fbd..aea25b1d206 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -4308,6 +4308,12 @@ bitrot_option_handler(volgen_graph_t *graph, struct volopt_map_entry *vme, return -1; } + if (!strcmp(vme->option, "signer-threads")) { + ret = xlator_set_fixed_option(xl, "signer-threads", vme->value); + if (ret) + return -1; + } + return ret; } diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index cec5b1a78d3..63de3ef685c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -2651,6 +2651,15 @@ struct volopt_map_entry glusterd_volopt_map[] = { .op_version = GD_OP_VERSION_3_7_0, .type = NO_DOC, }, + { + .key = "features.signer-threads", + .voltype = "features/bit-rot", + .value = BR_WORKERS, + .option = "signer-threads", + .op_version = GD_OP_VERSION_8_0, + .type = NO_DOC, + }, + /* Upcall translator options */ /* Upcall translator options */ { .key = "features.cache-invalidation", |