cb8e9e
From 7c8df30e18538917e361faff2ed032024d5ba16f Mon Sep 17 00:00:00 2001
cb8e9e
From: Gaurav Kumar Garg <ggarg@redhat.com>
cb8e9e
Date: Fri, 5 Jun 2015 13:58:28 +0530
cb8e9e
Subject: [PATCH 117/129] features/bitrot: tuanble object signing waiting time value for bitrot
cb8e9e
cb8e9e
 Currently bitrot using 120 second waiting time for object to be signed
cb8e9e
 after all fop's released. This signing waiting time value should be tunable.
cb8e9e
cb8e9e
 Command for changing the signing waiting time will be
cb8e9e
 #gluster volume bitrot <VOLNAME> signing-time <waiting time value in second>
cb8e9e
cb8e9e
BUG: 1227900
cb8e9e
Change-Id: I6f63cc77c996bfc576a05801be39a2028e5db866
cb8e9e
Signed-off-by: Gaurav Kumar Garg <ggarg@redhat.com>
cb8e9e
upstream patch url: http://review.gluster.org/#/c/11105/
cb8e9e
Reviewed-on: https://code.engineering.redhat.com/gerrit/50741
cb8e9e
Reviewed-by: Venky Shankar <vshankar@redhat.com>
cb8e9e
Tested-by: Venky Shankar <vshankar@redhat.com>
cb8e9e
---
cb8e9e
 cli/src/cli-cmd-parser.c                        |   33 ++++++++++++++-
cb8e9e
 rpc/xdr/src/cli1-xdr.x                          |    1 +
cb8e9e
 tests/bugs/bitrot/bug-1228680.t                 |   31 ++++++++++++++
cb8e9e
 xlators/features/bit-rot/src/bitd/bit-rot.c     |   37 ++++++++++++++---
cb8e9e
 xlators/features/bit-rot/src/bitd/bit-rot.h     |    2 +-
cb8e9e
 xlators/mgmt/glusterd/src/glusterd-bitrot.c     |   49 +++++++++++++++++++++++
cb8e9e
 xlators/mgmt/glusterd/src/glusterd-volgen.c     |   33 +++++++++++++++
cb8e9e
 xlators/mgmt/glusterd/src/glusterd-volume-set.c |    7 +++
cb8e9e
 8 files changed, 182 insertions(+), 11 deletions(-)
cb8e9e
 create mode 100644 tests/bugs/bitrot/bug-1228680.t
cb8e9e
cb8e9e
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
cb8e9e
index 2ddbe88..51da792 100644
cb8e9e
--- a/cli/src/cli-cmd-parser.c
cb8e9e
+++ b/cli/src/cli-cmd-parser.c
cb8e9e
@@ -5018,8 +5018,8 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options)
cb8e9e
         char               *volname               = NULL;
cb8e9e
         char               *opwords[]             = {"enable", "disable",
cb8e9e
                                                      "scrub-throttle",
cb8e9e
-                                                     "scrub-frequency",
cb8e9e
-                                                     "scrub", NULL};
cb8e9e
+                                                     "scrub-frequency", "scrub",
cb8e9e
+                                                     "signing-time", NULL};
cb8e9e
         char               *scrub_throt_values[]  = {"lazy", "normal",
cb8e9e
                                                      "aggressive", NULL};
cb8e9e
         char               *scrub_freq_values[]   = {"hourly",
cb8e9e
@@ -5030,6 +5030,7 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options)
cb8e9e
                                                       NULL};
cb8e9e
         dict_t             *dict                  = NULL;
cb8e9e
         gf_bitrot_type     type                   = GF_BITROT_OPTION_TYPE_NONE;
cb8e9e
+        uint32_t           expiry_time            = 0;
cb8e9e
 
cb8e9e
         GF_ASSERT (words);
cb8e9e
         GF_ASSERT (options);
cb8e9e
@@ -5039,7 +5040,7 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options)
cb8e9e
                 goto out;
cb8e9e
 
cb8e9e
         if (wordcount < 4 || wordcount > 5) {
cb8e9e
-                gf_log ("", GF_LOG_ERROR, "Invalid syntax");
cb8e9e
+                gf_log ("cli", GF_LOG_ERROR, "Invalid syntax");
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
@@ -5167,6 +5168,32 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options)
cb8e9e
                                 goto set_type;
cb8e9e
                         }
cb8e9e
                 }
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        if (!strcmp (words[3], "signing-time")) {
cb8e9e
+                if (!words[4]) {
cb8e9e
+                        cli_err ("Missing signing-time value for bitrot "
cb8e9e
+                                 "option");
cb8e9e
+                        ret = -1;
cb8e9e
+                        goto out;
cb8e9e
+                } else {
cb8e9e
+                        type = GF_BITROT_OPTION_TYPE_EXPIRY_TIME;
cb8e9e
+
cb8e9e
+                        expiry_time = strtol (words[4], NULL, 0);
cb8e9e
+                        if (expiry_time < 1) {
cb8e9e
+                                cli_err ("Expiry time  value should not be less"
cb8e9e
+                                         " than 1");
cb8e9e
+                                ret = -1;
cb8e9e
+                                goto out;
cb8e9e
+                        }
cb8e9e
+
cb8e9e
+                        ret = dict_set_int32 (dict, "expiry-time", expiry_time);
cb8e9e
+                        if (ret) {
cb8e9e
+                                cli_out ("Failed to set dict for bitrot");
cb8e9e
+                                goto out;
cb8e9e
+                        }
cb8e9e
+                        goto set_type;
cb8e9e
+                }
cb8e9e
         } else {
cb8e9e
                 cli_err ("Invalid option %s for bitrot. Please enter valid "
cb8e9e
                          "bitrot option", words[3]);
cb8e9e
diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x
cb8e9e
index 0d5d3cc..34f324f 100644
cb8e9e
--- a/rpc/xdr/src/cli1-xdr.x
cb8e9e
+++ b/rpc/xdr/src/cli1-xdr.x
cb8e9e
@@ -40,6 +40,7 @@ enum gf_bitrot_type {
cb8e9e
         GF_BITROT_OPTION_TYPE_SCRUB_THROTTLE,
cb8e9e
         GF_BITROT_OPTION_TYPE_SCRUB_FREQ,
cb8e9e
         GF_BITROT_OPTION_TYPE_SCRUB,
cb8e9e
+        GF_BITROT_OPTION_TYPE_EXPIRY_TIME,
cb8e9e
         GF_BITROT_OPTION_TYPE_MAX
cb8e9e
 };
cb8e9e
 
cb8e9e
diff --git a/tests/bugs/bitrot/bug-1228680.t b/tests/bugs/bitrot/bug-1228680.t
cb8e9e
new file mode 100644
cb8e9e
index 0000000..c77beed
cb8e9e
--- /dev/null
cb8e9e
+++ b/tests/bugs/bitrot/bug-1228680.t
cb8e9e
@@ -0,0 +1,31 @@
cb8e9e
+#!/bin/bash
cb8e9e
+
cb8e9e
+## Test case for bitrot
cb8e9e
+## Tunable object signing waiting time value for bitrot.
cb8e9e
+
cb8e9e
+
cb8e9e
+. $(dirname $0)/../../include.rc
cb8e9e
+. $(dirname $0)/../../volume.rc
cb8e9e
+. $(dirname $0)/../../cluster.rc
cb8e9e
+
cb8e9e
+cleanup;
cb8e9e
+
cb8e9e
+
cb8e9e
+## Start glusterd
cb8e9e
+TEST glusterd;
cb8e9e
+TEST pidof glusterd;
cb8e9e
+
cb8e9e
+## Lets create and start the volume
cb8e9e
+TEST $CLI volume create $V0 $H0:$B0/${V0}0 $H0:$B0/${V0}1
cb8e9e
+TEST $CLI volume start $V0
cb8e9e
+
cb8e9e
+## Enable bitrot on volume $V0
cb8e9e
+TEST $CLI volume bitrot $V0 enable
cb8e9e
+
cb8e9e
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count
cb8e9e
+
cb8e9e
+## Set object expiry time value 20 second.
cb8e9e
+TEST $CLI volume bitrot $V0 signing-time 20
cb8e9e
+
cb8e9e
+
cb8e9e
+cleanup;
cb8e9e
diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.c b/xlators/features/bit-rot/src/bitd/bit-rot.c
cb8e9e
index 8149083..a4821ba 100644
cb8e9e
--- a/xlators/features/bit-rot/src/bitd/bit-rot.c
cb8e9e
+++ b/xlators/features/bit-rot/src/bitd/bit-rot.c
cb8e9e
@@ -753,8 +753,11 @@ br_initialize_timer (xlator_t *this, br_object_t *object, br_child_t *child,
cb8e9e
                 goto out;
cb8e9e
         INIT_LIST_HEAD (&timer->entry);
cb8e9e
 
cb8e9e
+        timer->expires  = (priv->expiry_time >> 1);
cb8e9e
+        if (!timer->expires)
cb8e9e
+                timer->expires = 1;
cb8e9e
+
cb8e9e
         timer->data     = object;
cb8e9e
-        timer->expires  = priv->expiry_time;
cb8e9e
         timer->function = br_add_object_to_queue;
cb8e9e
         gf_tw_add_timer (priv->timer_wheel, timer);
cb8e9e
 
cb8e9e
@@ -1491,12 +1494,28 @@ br_rate_limit_signer (xlator_t *this, int child_count, int numbricks)
cb8e9e
 }
cb8e9e
 
cb8e9e
 static int32_t
cb8e9e
+br_signer_handle_options (xlator_t *this, br_private_t *priv, dict_t *options)
cb8e9e
+{
cb8e9e
+        if (options)
cb8e9e
+                GF_OPTION_RECONF ("expiry-time", priv->expiry_time,
cb8e9e
+                                  options, uint32, error_return);
cb8e9e
+        else
cb8e9e
+                GF_OPTION_INIT ("expiry-time", priv->expiry_time,
cb8e9e
+                                uint32, error_return);
cb8e9e
+
cb8e9e
+        return 0;
cb8e9e
+
cb8e9e
+error_return:
cb8e9e
+        return -1;
cb8e9e
+}
cb8e9e
+
cb8e9e
+static int32_t
cb8e9e
 br_signer_init (xlator_t *this, br_private_t *priv)
cb8e9e
 {
cb8e9e
         int32_t ret = 0;
cb8e9e
         int numbricks = 0;
cb8e9e
 
cb8e9e
-        GF_OPTION_INIT ("expiry-time", priv->expiry_time, int32, error_return);
cb8e9e
+        GF_OPTION_INIT ("expiry-time", priv->expiry_time, uint32, error_return);
cb8e9e
         GF_OPTION_INIT ("brick-count", numbricks, int32, error_return);
cb8e9e
 
cb8e9e
         ret = br_rate_limit_signer (this, priv->child_count, numbricks);
cb8e9e
@@ -1581,6 +1600,8 @@ init (xlator_t *this)
cb8e9e
 
cb8e9e
         if (!priv->iamscrubber) {
cb8e9e
                 ret = br_signer_init (this, priv);
cb8e9e
+                if (!ret)
cb8e9e
+                        ret = br_signer_handle_options (this, priv, NULL);
cb8e9e
         } else {
cb8e9e
                 ret = br_scrubber_init (this, priv);
cb8e9e
                 if (!ret)
cb8e9e
@@ -1651,8 +1672,12 @@ reconfigure (xlator_t *this, dict_t *options)
cb8e9e
 
cb8e9e
         priv = this->private;
cb8e9e
 
cb8e9e
-        if (!priv->iamscrubber)
cb8e9e
+        if (!priv->iamscrubber) {
cb8e9e
+                ret = br_signer_handle_options (this, priv, options);
cb8e9e
+                if (ret)
cb8e9e
+                        goto err;
cb8e9e
                 return 0;
cb8e9e
+        }
cb8e9e
 
cb8e9e
         ret = br_scrubber_handle_options (this, priv, options);
cb8e9e
         if (ret)
cb8e9e
@@ -1700,10 +1725,8 @@ struct xlator_cbks cbks;
cb8e9e
 struct volume_options options[] = {
cb8e9e
         { .key = {"expiry-time"},
cb8e9e
           .type = GF_OPTION_TYPE_INT,
cb8e9e
-          /* Let the default timer be half the value of the wait time for
cb8e9e
-           * sining (which is 120 as of now) */
cb8e9e
-          .default_value = "60",
cb8e9e
-          .description = "default time duration for which an object waits "
cb8e9e
+          .default_value = "120",
cb8e9e
+          .description = "Waiting time for an object on which it waits "
cb8e9e
                          "before it is signed",
cb8e9e
         },
cb8e9e
         { .key = {"brick-count"},
cb8e9e
diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.h b/xlators/features/bit-rot/src/bitd/bit-rot.h
cb8e9e
index 40e02eb..562f17e 100644
cb8e9e
--- a/xlators/features/bit-rot/src/bitd/bit-rot.h
cb8e9e
+++ b/xlators/features/bit-rot/src/bitd/bit-rot.h
cb8e9e
@@ -162,7 +162,7 @@ struct br_private {
cb8e9e
                                              and ready to be picked up for
cb8e9e
                                              signing and the workers which sign
cb8e9e
                                              the objects */
cb8e9e
-        int32_t expiry_time;              /* objects "wait" time */
cb8e9e
+        uint32_t expiry_time;              /* objects "wait" time */
cb8e9e
 
cb8e9e
         br_tbf_t *tbf;                    /* token bucket filter */
cb8e9e
 
cb8e9e
diff --git a/xlators/mgmt/glusterd/src/glusterd-bitrot.c b/xlators/mgmt/glusterd/src/glusterd-bitrot.c
cb8e9e
index 08976cf..1563102 100644
cb8e9e
--- a/xlators/mgmt/glusterd/src/glusterd-bitrot.c
cb8e9e
+++ b/xlators/mgmt/glusterd/src/glusterd-bitrot.c
cb8e9e
@@ -37,6 +37,7 @@ const char *gd_bitrot_op_list[GF_BITROT_OPTION_TYPE_MAX] = {
cb8e9e
         [GF_BITROT_OPTION_TYPE_SCRUB_THROTTLE]  = "scrub-throttle",
cb8e9e
         [GF_BITROT_OPTION_TYPE_SCRUB_FREQ]      = "scrub-frequency",
cb8e9e
         [GF_BITROT_OPTION_TYPE_SCRUB]           = "scrub",
cb8e9e
+        [GF_BITROT_OPTION_TYPE_EXPIRY_TIME]     = "expiry-time",
cb8e9e
 };
cb8e9e
 
cb8e9e
 int
cb8e9e
@@ -248,6 +249,46 @@ out:
cb8e9e
 }
cb8e9e
 
cb8e9e
 static int
cb8e9e
+glusterd_bitrot_expiry_time (glusterd_volinfo_t *volinfo, dict_t *dict,
cb8e9e
+                             char *key, char **op_errstr)
cb8e9e
+{
cb8e9e
+        int32_t        ret                  = -1;
cb8e9e
+        uint32_t       expiry_time          = 0;
cb8e9e
+        xlator_t       *this                = NULL;
cb8e9e
+        char           dkey[1024]           = {0,};
cb8e9e
+        char           *key_value           = NULL;
cb8e9e
+
cb8e9e
+        this = THIS;
cb8e9e
+        GF_ASSERT (this);
cb8e9e
+
cb8e9e
+        ret = dict_get_uint32 (dict, "expiry-time", &expiry_time);
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log (this->name, GF_LOG_ERROR, "Unable to get bitrot expiry"
cb8e9e
+                        " timer value.");
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        snprintf (dkey, sizeof (dkey), "%d", expiry_time);
cb8e9e
+        key_value = gf_strdup (dkey);
cb8e9e
+
cb8e9e
+        ret = dict_set_dynstr (volinfo->dict, key, key_value);
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log (this->name, GF_LOG_ERROR, "Failed to set option %s",
cb8e9e
+                        key);
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        ret = glusterd_bitdsvc_reconfigure ();
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log (this->name, GF_LOG_ERROR, "Failed to reconfigure bitrot"
cb8e9e
+                         "services");
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+out:
cb8e9e
+        return ret;
cb8e9e
+}
cb8e9e
+
cb8e9e
+static int
cb8e9e
 glusterd_bitrot_enable (glusterd_volinfo_t *volinfo, char **op_errstr)
cb8e9e
 {
cb8e9e
         int32_t         ret             = -1;
cb8e9e
@@ -476,6 +517,14 @@ glusterd_op_bitrot (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
cb8e9e
                         goto out;
cb8e9e
                 break;
cb8e9e
 
cb8e9e
+        case GF_BITROT_OPTION_TYPE_EXPIRY_TIME:
cb8e9e
+                ret = glusterd_bitrot_expiry_time (volinfo, dict,
cb8e9e
+                                                   "features.expiry-time",
cb8e9e
+                                                   op_errstr);
cb8e9e
+                if (ret)
cb8e9e
+                        goto out;
cb8e9e
+                break;
cb8e9e
+
cb8e9e
         default:
cb8e9e
                 gf_asprintf (op_errstr, "Bitrot command failed. Invalid "
cb8e9e
                              "opcode");
cb8e9e
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
cb8e9e
index 9c09c78..a79e129 100644
cb8e9e
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c
cb8e9e
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c
cb8e9e
@@ -3743,6 +3743,33 @@ gd_get_matching_option (char **options, char *option)
cb8e9e
 }
cb8e9e
 
cb8e9e
 static int
cb8e9e
+bitrot_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme,
cb8e9e
+                       void *param)
cb8e9e
+{
cb8e9e
+        xlator_t           *xl                 = NULL;
cb8e9e
+        char               *bitrot_option      = NULL;
cb8e9e
+        int                 ret                = 0;
cb8e9e
+        glusterd_volinfo_t *volinfo            = NULL;
cb8e9e
+
cb8e9e
+        volinfo = param;
cb8e9e
+
cb8e9e
+        xl = first_of (graph);
cb8e9e
+
cb8e9e
+        if (!strcmp (vme->option, "expiry-time")) {
cb8e9e
+                ret = gf_asprintf (&bitrot_option, "expiry-time");
cb8e9e
+                if (ret != -1) {
cb8e9e
+                        ret = xlator_set_option (xl, bitrot_option, vme->value);
cb8e9e
+                        GF_FREE (bitrot_option);
cb8e9e
+                }
cb8e9e
+
cb8e9e
+                if (ret)
cb8e9e
+                        return -1;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        return ret;
cb8e9e
+}
cb8e9e
+
cb8e9e
+static int
cb8e9e
 scrubber_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme,
cb8e9e
                        void *param)
cb8e9e
 {
cb8e9e
@@ -4981,6 +5008,12 @@ build_bitd_volume_graph (volgen_graph_t *graph,
cb8e9e
                 goto out;
cb8e9e
         }
cb8e9e
 
cb8e9e
+        ret = volgen_graph_set_options_generic (&cgraph, set_dict,
cb8e9e
+                                                volinfo,
cb8e9e
+                                                bitrot_option_handler);
cb8e9e
+        if (ret)
cb8e9e
+                goto out;
cb8e9e
+
cb8e9e
         ret = volgen_graph_merge_sub (graph, &cgraph, clusters);
cb8e9e
         if (ret)
cb8e9e
                 goto out;
cb8e9e
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
cb8e9e
index 624e577..415bc01 100644
cb8e9e
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
cb8e9e
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
cb8e9e
@@ -1866,6 +1866,13 @@ struct volopt_map_entry glusterd_volopt_map[] = {
cb8e9e
           .flags      = OPT_FLAG_FORCE,
cb8e9e
           .type       = NO_DOC,
cb8e9e
         },
cb8e9e
+        { .key        = "features.expiry-time",
cb8e9e
+          .voltype    = "features/bitrot",
cb8e9e
+          .value      = "120",
cb8e9e
+          .option     = "expiry-time",
cb8e9e
+          .op_version = GD_OP_VERSION_3_7_0,
cb8e9e
+          .type       = NO_DOC,
cb8e9e
+        },
cb8e9e
         /* Upcall translator options */
cb8e9e
         { .key         = "features.cache-invalidation",
cb8e9e
           .voltype     = "features/upcall",
cb8e9e
-- 
cb8e9e
1.7.1
cb8e9e