diff options
-rw-r--r-- | cli/src/cli-cmd-parser.c | 34 | ||||
-rw-r--r-- | libglusterfs/src/common-utils.h | 3 | ||||
-rw-r--r-- | rpc/xdr/src/cli1-xdr.x | 1 | ||||
-rw-r--r-- | tests/bugs/bitrot/bug-1228680.t | 48 | ||||
-rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot.c | 37 | ||||
-rw-r--r-- | xlators/features/bit-rot/src/bitd/bit-rot.h | 2 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-bitrot.c | 47 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 33 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-set.c | 7 |
9 files changed, 201 insertions, 11 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index f3dd58528b6..2f7885b80eb 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -4994,8 +4994,8 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options) char *volname = NULL; char *opwords[] = {"enable", "disable", "scrub-throttle", - "scrub-frequency", - "scrub", NULL}; + "scrub-frequency", "scrub", + "signing-time", NULL}; char *scrub_throt_values[] = {"lazy", "normal", "aggressive", NULL}; char *scrub_freq_values[] = {"hourly", @@ -5006,6 +5006,7 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options) NULL}; dict_t *dict = NULL; gf_bitrot_type type = GF_BITROT_OPTION_TYPE_NONE; + int32_t expiry_time = 0; GF_ASSERT (words); GF_ASSERT (options); @@ -5015,7 +5016,7 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options) goto out; if (wordcount < 4 || wordcount > 5) { - gf_log ("", GF_LOG_ERROR, "Invalid syntax"); + gf_log ("cli", GF_LOG_ERROR, "Invalid syntax"); goto out; } @@ -5143,6 +5144,33 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options) goto set_type; } } + } + + if (!strcmp (words[3], "signing-time")) { + if (!words[4]) { + cli_err ("Missing signing-time value for bitrot " + "option"); + ret = -1; + goto out; + } else { + type = GF_BITROT_OPTION_TYPE_EXPIRY_TIME; + + expiry_time = strtol (words[4], NULL, 0); + if (expiry_time < 1) { + cli_err ("Expiry time value should not be less" + " than 1"); + ret = -1; + goto out; + } + + ret = dict_set_uint32 (dict, "expiry-time", + (unsigned int) expiry_time); + 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 " "bitrot option", words[3]); diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 6691259f518..06ce0ff4d71 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -90,6 +90,9 @@ void trap (void); /* Default timeout for both barrier and changelog translator */ #define BARRIER_TIMEOUT "120" +/* Default value of signing waiting time to sign a file for bitrot */ +#define SIGNING_TIMEOUT "120" + enum _gf_boolean { _gf_false = 0, diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index 0d5d3cc360c..34f324f1099 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -40,6 +40,7 @@ enum gf_bitrot_type { GF_BITROT_OPTION_TYPE_SCRUB_THROTTLE, GF_BITROT_OPTION_TYPE_SCRUB_FREQ, GF_BITROT_OPTION_TYPE_SCRUB, + GF_BITROT_OPTION_TYPE_EXPIRY_TIME, GF_BITROT_OPTION_TYPE_MAX }; diff --git a/tests/bugs/bitrot/bug-1228680.t b/tests/bugs/bitrot/bug-1228680.t new file mode 100644 index 00000000000..23db9d5e208 --- /dev/null +++ b/tests/bugs/bitrot/bug-1228680.t @@ -0,0 +1,48 @@ +#!/bin/bash + +## Test case for bitrot +## Tunable object signing waiting time value for bitrot. + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../cluster.rc + +SLEEP_TIME=3 + +cleanup; +## Start glusterd +TEST glusterd; +TEST pidof glusterd; + +## Lets create and start the volume +TEST $CLI volume create $V0 $H0:$B0/${V0}0 $H0:$B0/${V0}1 +TEST $CLI volume start $V0 + +## Enable bitrot on volume $V0 +TEST $CLI volume bitrot $V0 enable + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count + +# wait a bit for oneshot crawler to finish +sleep $SLEEP_TIME + +## negative test +TEST ! $CLI volume bitrot $V0 signing-time -100 + +## Set object expiry time value 5 second. +TEST $CLI volume bitrot $V0 signing-time $SLEEP_TIME + +## Mount the volume +TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0; + +# create and check object signature +fname="$M0/filezero" +echo "ZZZ" > $fname + +# wait till the object is signed +sleep `expr $SLEEP_TIME \* 2` + +backpath=$(get_backend_paths $fname) +TEST getfattr -m . -n trusted.bit-rot.signature $backpath + +cleanup; diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.c b/xlators/features/bit-rot/src/bitd/bit-rot.c index a645085fd58..651c42fcb82 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.c +++ b/xlators/features/bit-rot/src/bitd/bit-rot.c @@ -748,8 +748,11 @@ br_initialize_timer (xlator_t *this, br_object_t *object, br_child_t *child, goto out; INIT_LIST_HEAD (&timer->entry); + timer->expires = (priv->expiry_time >> 1); + if (!timer->expires) + timer->expires = 1; + timer->data = object; - timer->expires = priv->expiry_time; timer->function = br_add_object_to_queue; gf_tw_add_timer (priv->timer_wheel, timer); @@ -1486,12 +1489,28 @@ 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) + GF_OPTION_RECONF ("expiry-time", priv->expiry_time, + options, uint32, error_return); + else + GF_OPTION_INIT ("expiry-time", priv->expiry_time, + uint32, error_return); + + return 0; + +error_return: + return -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 ("expiry-time", priv->expiry_time, uint32, error_return); GF_OPTION_INIT ("brick-count", numbricks, int32, error_return); ret = br_rate_limit_signer (this, priv->child_count, numbricks); @@ -1576,6 +1595,8 @@ init (xlator_t *this) if (!priv->iamscrubber) { ret = br_signer_init (this, priv); + if (!ret) + ret = br_signer_handle_options (this, priv, NULL); } else { ret = br_scrubber_init (this, priv); if (!ret) @@ -1646,8 +1667,12 @@ reconfigure (xlator_t *this, dict_t *options) priv = this->private; - if (!priv->iamscrubber) + if (!priv->iamscrubber) { + ret = br_signer_handle_options (this, priv, options); + if (ret) + goto err; return 0; + } ret = br_scrubber_handle_options (this, priv, options); if (ret) @@ -1695,10 +1720,8 @@ struct xlator_cbks cbks; struct volume_options options[] = { { .key = {"expiry-time"}, .type = GF_OPTION_TYPE_INT, - /* Let the default timer be half the value of the wait time for - * sining (which is 120 as of now) */ - .default_value = "60", - .description = "default time duration for which an object waits " + .default_value = SIGNING_TIMEOUT, + .description = "Waiting time for an object on which it waits " "before it is signed", }, { .key = {"brick-count"}, diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.h b/xlators/features/bit-rot/src/bitd/bit-rot.h index e702f3ac72d..7be4398d00d 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.h +++ b/xlators/features/bit-rot/src/bitd/bit-rot.h @@ -157,7 +157,7 @@ struct br_private { and ready to be picked up for signing and the workers which sign the objects */ - int32_t expiry_time; /* objects "wait" time */ + uint32_t expiry_time; /* objects "wait" time */ br_tbf_t *tbf; /* token bucket filter */ diff --git a/xlators/mgmt/glusterd/src/glusterd-bitrot.c b/xlators/mgmt/glusterd/src/glusterd-bitrot.c index da1b54ac1df..c32aa1e3ff3 100644 --- a/xlators/mgmt/glusterd/src/glusterd-bitrot.c +++ b/xlators/mgmt/glusterd/src/glusterd-bitrot.c @@ -32,6 +32,7 @@ const char *gd_bitrot_op_list[GF_BITROT_OPTION_TYPE_MAX] = { [GF_BITROT_OPTION_TYPE_SCRUB_THROTTLE] = "scrub-throttle", [GF_BITROT_OPTION_TYPE_SCRUB_FREQ] = "scrub-frequency", [GF_BITROT_OPTION_TYPE_SCRUB] = "scrub", + [GF_BITROT_OPTION_TYPE_EXPIRY_TIME] = "expiry-time", }; int @@ -243,6 +244,44 @@ out: } static int +glusterd_bitrot_expiry_time (glusterd_volinfo_t *volinfo, dict_t *dict, + char *key, char **op_errstr) +{ + int32_t ret = -1; + uint32_t expiry_time = 0; + xlator_t *this = NULL; + char dkey[1024] = {0,}; + + this = THIS; + GF_ASSERT (this); + + ret = dict_get_uint32 (dict, "expiry-time", &expiry_time); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to get bitrot expiry" + " timer value."); + goto out; + } + + snprintf (dkey, sizeof (dkey), "%d", expiry_time); + + ret = dict_set_dynstr_with_alloc (volinfo->dict, key, dkey); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to set option %s", + key); + goto out; + } + + ret = glusterd_bitdsvc_reconfigure (); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to reconfigure bitrot" + "services"); + goto out; + } +out: + return ret; +} + +static int glusterd_bitrot_enable (glusterd_volinfo_t *volinfo, char **op_errstr) { int32_t ret = -1; @@ -471,6 +510,14 @@ glusterd_op_bitrot (dict_t *dict, char **op_errstr, dict_t *rsp_dict) goto out; break; + case GF_BITROT_OPTION_TYPE_EXPIRY_TIME: + ret = glusterd_bitrot_expiry_time (volinfo, dict, + "features.expiry-time", + op_errstr); + if (ret) + goto out; + break; + default: gf_asprintf (op_errstr, "Bitrot command failed. Invalid " "opcode"); diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 8fe1be16fad..e618e2c7a35 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -3738,6 +3738,33 @@ gd_get_matching_option (char **options, char *option) } static int +bitrot_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, + void *param) +{ + xlator_t *xl = NULL; + char *bitrot_option = NULL; + int ret = 0; + glusterd_volinfo_t *volinfo = NULL; + + volinfo = param; + + xl = first_of (graph); + + if (!strcmp (vme->option, "expiry-time")) { + ret = gf_asprintf (&bitrot_option, "expiry-time"); + if (ret != -1) { + ret = xlator_set_option (xl, bitrot_option, vme->value); + GF_FREE (bitrot_option); + } + + if (ret) + return -1; + } + + return ret; +} + +static int scrubber_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme, void *param) { @@ -4976,6 +5003,12 @@ build_bitd_volume_graph (volgen_graph_t *graph, goto out; } + ret = volgen_graph_set_options_generic (&cgraph, set_dict, + volinfo, + bitrot_option_handler); + if (ret) + goto out; + ret = volgen_graph_merge_sub (graph, &cgraph, clusters); if (ret) goto out; diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index 2ea2ae2eadc..3d3525297f5 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -1935,6 +1935,13 @@ struct volopt_map_entry glusterd_volopt_map[] = { .flags = OPT_FLAG_FORCE, .type = NO_DOC, }, + { .key = "features.expiry-time", + .voltype = "features/bitrot", + .value = SIGNING_TIMEOUT, + .option = "expiry-time", + .op_version = GD_OP_VERSION_3_7_0, + .type = NO_DOC, + }, /* Upcall translator options */ { .key = "features.cache-invalidation", .voltype = "features/upcall", |