cb8e9e
From 069d8f649618fc1230ce6382ddd12c6b082262c3 Mon Sep 17 00:00:00 2001
cb8e9e
From: Venky Shankar <vshankar@redhat.com>
cb8e9e
Date: Tue, 2 Jun 2015 21:23:48 +0530
cb8e9e
Subject: [PATCH 158/190] features/bitrot: cleanup, v1
cb8e9e
cb8e9e
    Backport of http://review.gluster.org/11147
cb8e9e
cb8e9e
This is a short series of patches (with other cleanups) aimed at
cb8e9e
cleaning up some of the incorrect assumptions taken in reconfigure()
cb8e9e
leading to crashes when subvolumes are not fully initialized (as
cb8e9e
reported here[1] on gluster-devel@). Furthermore, there is some
cb8e9e
amount of code cleanup to handle disconnection and cleanup up data
cb8e9e
structure (as part of subsequent patch).
cb8e9e
cb8e9e
[1] http://www.gluster.org/pipermail/gluster-devel/2015-June/045410.html
cb8e9e
cb8e9e
Change-Id: I68ac4bccfbac4bf02fcc31615bd7d2d191021132
cb8e9e
BUG: 1232307
cb8e9e
Signed-off-by: Venky Shankar <vshankar@redhat.com>
cb8e9e
Reviewed-on: https://code.engineering.redhat.com/gerrit/51743
cb8e9e
Tested-by: Raghavendra Bhat <raghavendra@redhat.com>
cb8e9e
Reviewed-by: Raghavendra Bhat <raghavendra@redhat.com>
cb8e9e
---
cb8e9e
 xlators/features/bit-rot/src/bitd/bit-rot.c        |  364 +++++++++++++-------
cb8e9e
 xlators/features/bit-rot/src/bitd/bit-rot.h        |   32 ++-
cb8e9e
 .../bit-rot/src/stub/bit-rot-stub-mem-types.h      |    1 +
cb8e9e
 3 files changed, 271 insertions(+), 126 deletions(-)
cb8e9e
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 c06a5c1..b855cd7 100644
cb8e9e
--- a/xlators/features/bit-rot/src/bitd/bit-rot.c
cb8e9e
+++ b/xlators/features/bit-rot/src/bitd/bit-rot.c
cb8e9e
@@ -30,6 +30,18 @@
cb8e9e
 
cb8e9e
 #define BR_HASH_CALC_READ_SIZE  (128 * 1024)
cb8e9e
 
cb8e9e
+typedef int32_t (br_child_handler)(xlator_t *, br_child_t *);
cb8e9e
+
cb8e9e
+struct br_child_event {
cb8e9e
+        xlator_t *this;
cb8e9e
+
cb8e9e
+        br_child_t *child;
cb8e9e
+
cb8e9e
+        br_child_handler *call;
cb8e9e
+
cb8e9e
+        struct list_head list;
cb8e9e
+};
cb8e9e
+
cb8e9e
 static int
cb8e9e
 br_find_child_index (xlator_t *this, xlator_t *child)
cb8e9e
 {
cb8e9e
@@ -54,26 +66,6 @@ out:
cb8e9e
         return index;
cb8e9e
 }
cb8e9e
 
cb8e9e
-static void
cb8e9e
-br_free_children (xlator_t *this)
cb8e9e
-{
cb8e9e
-        br_private_t *priv = NULL;
cb8e9e
-        int32_t       i    = 0;
cb8e9e
-        br_child_t   *child = NULL;
cb8e9e
-
cb8e9e
-        priv = this->private;
cb8e9e
-
cb8e9e
-        for (i = 0; i < priv->child_count; i++) {
cb8e9e
-                child = &priv->children[i];
cb8e9e
-                mem_pool_destroy (child->timer_pool);
cb8e9e
-                list_del_init (&priv->children[i].list);
cb8e9e
-        }
cb8e9e
-
cb8e9e
-        GF_FREE (priv->children);
cb8e9e
-
cb8e9e
-        priv->children = NULL;
cb8e9e
-}
cb8e9e
-
cb8e9e
 br_child_t *
cb8e9e
 br_get_child_from_brick_path (xlator_t *this, char *brick_path)
cb8e9e
 {
cb8e9e
@@ -1090,6 +1082,16 @@ br_oneshot_signer (void *arg)
cb8e9e
         return NULL;
cb8e9e
 }
cb8e9e
 
cb8e9e
+static void
cb8e9e
+br_set_child_state (br_child_t *child, br_child_state_t state)
cb8e9e
+{
cb8e9e
+        LOCK (&child->lock);
cb8e9e
+        {
cb8e9e
+                _br_set_child_state (child, state);
cb8e9e
+        }
cb8e9e
+        UNLOCK (&child->lock);
cb8e9e
+}
cb8e9e
+
cb8e9e
 /**
cb8e9e
  * At this point a thread is spawned to crawl the filesystem (in
cb8e9e
  * tortoise pace) to sign objects that were not signed in previous run(s).
cb8e9e
@@ -1177,7 +1179,12 @@ br_enact_scrubber (xlator_t *this, br_child_t *child)
cb8e9e
                 goto error_return;
cb8e9e
         }
cb8e9e
 
cb8e9e
-        ret = br_fsscan_schedule (this, child, fsscan, fsscrub);
cb8e9e
+        /* this needs to be serialized with reconfigure() */
cb8e9e
+        pthread_mutex_lock (&priv->lock);
cb8e9e
+        {
cb8e9e
+                ret = br_fsscan_schedule (this, child, fsscan, fsscrub);
cb8e9e
+        }
cb8e9e
+        pthread_mutex_unlock (&priv->lock);
cb8e9e
         if (ret)
cb8e9e
                 goto error_return;
cb8e9e
 
cb8e9e
@@ -1202,6 +1209,30 @@ br_enact_scrubber (xlator_t *this, br_child_t *child)
cb8e9e
         return -1;
cb8e9e
 }
cb8e9e
 
cb8e9e
+static int32_t
cb8e9e
+br_child_enaction (xlator_t *this, br_child_t *child, br_stub_init_t *stub)
cb8e9e
+{
cb8e9e
+        int32_t ret = -1;
cb8e9e
+        br_private_t *priv = this->private;
cb8e9e
+
cb8e9e
+        LOCK (&child->lock);
cb8e9e
+        {
cb8e9e
+                if (priv->iamscrubber)
cb8e9e
+                        ret = br_enact_scrubber (this, child);
cb8e9e
+                else
cb8e9e
+                        ret = br_enact_signer (this, child, stub);
cb8e9e
+
cb8e9e
+                if (!ret) {
cb8e9e
+                        _br_set_child_state (child, BR_CHILD_STATE_CONNECTED);
cb8e9e
+                        gf_log (this->name, GF_LOG_INFO,
cb8e9e
+                                "Connected to brick %s..", child->brick_path);
cb8e9e
+                }
cb8e9e
+        }
cb8e9e
+        UNLOCK (&child->lock);
cb8e9e
+
cb8e9e
+        return ret;
cb8e9e
+}
cb8e9e
+
cb8e9e
 /**
cb8e9e
  * This routine fetches various attributes associated with a child which
cb8e9e
  * is basically a subvolume. Attributes include brick path and the stub
cb8e9e
@@ -1209,7 +1240,7 @@ br_enact_scrubber (xlator_t *this, br_child_t *child)
cb8e9e
  * by getxattr() on a virtual key. Depending on the configuration, the
cb8e9e
  * process either acts as a signer or a scrubber.
cb8e9e
  */
cb8e9e
-static inline int32_t
cb8e9e
+int32_t
cb8e9e
 br_brick_connect (xlator_t *this, br_child_t *child)
cb8e9e
 {
cb8e9e
         int32_t         ret      = -1;
cb8e9e
@@ -1218,14 +1249,13 @@ br_brick_connect (xlator_t *this, br_child_t *child)
cb8e9e
         struct iatt     parent   = {0, };
cb8e9e
         br_stub_init_t *stub     = NULL;
cb8e9e
         dict_t         *xattr    = NULL;
cb8e9e
-        br_private_t   *priv     = NULL;
cb8e9e
         int             op_errno = 0;
cb8e9e
 
cb8e9e
         GF_VALIDATE_OR_GOTO ("bit-rot", this, out);
cb8e9e
         GF_VALIDATE_OR_GOTO (this->name, child, out);
cb8e9e
         GF_VALIDATE_OR_GOTO (this->name, this->private, out);
cb8e9e
 
cb8e9e
-        priv = this->private;
cb8e9e
+        br_set_child_state (child, BR_CHILD_STATE_INITIALIZING);
cb8e9e
 
cb8e9e
         loc.inode = inode_ref (child->table->root);
cb8e9e
         gf_uuid_copy (loc.gfid, loc.inode->gfid);
cb8e9e
@@ -1262,20 +1292,15 @@ br_brick_connect (xlator_t *this, br_child_t *child)
cb8e9e
         child->tv.tv_sec = ntohl (stub->timebuf[0]);
cb8e9e
         child->tv.tv_usec = ntohl (stub->timebuf[1]);
cb8e9e
 
cb8e9e
-        if (priv->iamscrubber)
cb8e9e
-                ret = br_enact_scrubber (this, child);
cb8e9e
-        else
cb8e9e
-                ret = br_enact_signer (this, child, stub);
cb8e9e
-
cb8e9e
-        if (!ret)
cb8e9e
-                gf_msg (this->name, GF_LOG_INFO, 0, BRB_MSG_CONNECTED_TO_BRICK,
cb8e9e
-                        "Connected to brick %s..", child->brick_path);
cb8e9e
+        ret = br_child_enaction (this, child, stub);
cb8e9e
 
cb8e9e
  free_dict:
cb8e9e
         dict_unref (xattr);
cb8e9e
  wipeloc:
cb8e9e
         loc_wipe (&loc;;
cb8e9e
  out:
cb8e9e
+        if (ret)
cb8e9e
+                br_set_child_state (child, BR_CHILD_STATE_CONNFAILED);
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
@@ -1290,7 +1315,8 @@ br_handle_events (void *arg)
cb8e9e
         int32_t       ret   = 0;
cb8e9e
         xlator_t     *this  = NULL;
cb8e9e
         br_private_t *priv  = NULL;
cb8e9e
-        br_child_t   *child = NULL;
cb8e9e
+        br_child_t *child = NULL;
cb8e9e
+        struct br_child_event *childev = NULL;
cb8e9e
 
cb8e9e
         this = arg;
cb8e9e
         priv = this->private;
cb8e9e
@@ -1309,17 +1335,20 @@ br_handle_events (void *arg)
cb8e9e
                         while (list_empty (&priv->bricks))
cb8e9e
                                 pthread_cond_wait (&priv->cond, &priv->lock);
cb8e9e
 
cb8e9e
-                        child = list_first_entry
cb8e9e
-                                          (&priv->bricks, br_child_t, list);
cb8e9e
-                        list_del_init (&child->list);
cb8e9e
+                        childev = list_first_entry
cb8e9e
+                                   (&priv->bricks, struct br_child_event, list);
cb8e9e
+                        list_del_init (&childev->list);
cb8e9e
                 }
cb8e9e
                 pthread_mutex_unlock (&priv->lock);
cb8e9e
 
cb8e9e
-                ret = br_brick_connect (this, child);
cb8e9e
+                child = childev->child;
cb8e9e
+                ret = childev->call (this, child);
cb8e9e
                 if (ret)
cb8e9e
                         gf_msg (this->name, GF_LOG_ERROR, 0,
cb8e9e
-                                BRB_MSG_SUBVOL_CONNECT_FAILED, "failed to "
cb8e9e
-                                "connect to subvolume %s", child->xl->name);
cb8e9e
+                                BRB_MSG_SUBVOL_CONNECT_FAILED,
cb8e9e
+                                "callback handler for subvolume [%s] failed",
cb8e9e
+                                child->xl->name);
cb8e9e
+                GF_FREE (childev);
cb8e9e
         }
cb8e9e
 
cb8e9e
         return NULL;
cb8e9e
@@ -1344,6 +1373,29 @@ mem_acct_init (xlator_t *this)
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
+static void
cb8e9e
+_br_qchild_event (xlator_t *this, br_child_t *child, br_child_handler *call)
cb8e9e
+{
cb8e9e
+        br_private_t *priv = NULL;
cb8e9e
+        struct br_child_event *childev = NULL;
cb8e9e
+
cb8e9e
+        priv = this->private;
cb8e9e
+
cb8e9e
+        childev = GF_CALLOC (1, sizeof (*childev), gf_br_mt_br_child_event_t);
cb8e9e
+        if (!childev) {
cb8e9e
+                gf_log (this->name, GF_LOG_ERROR, "Event unhandled for "
cb8e9e
+                        "child.. [Brick: %s]", child->xl->name);
cb8e9e
+                return;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        INIT_LIST_HEAD (&childev->list);
cb8e9e
+        childev->this  = this;
cb8e9e
+        childev->child = child;
cb8e9e
+        childev->call  = call;
cb8e9e
+
cb8e9e
+        list_add_tail (&childev->list, &priv->bricks);
cb8e9e
+}
cb8e9e
+
cb8e9e
 int
cb8e9e
 notify (xlator_t *this, int32_t event, void *data, ...)
cb8e9e
 {
cb8e9e
@@ -1373,14 +1425,14 @@ notify (xlator_t *this, int32_t event, void *data, ...)
cb8e9e
                         child = &priv->children[idx];
cb8e9e
                         if (child->child_up == 1)
cb8e9e
                                 goto unblock;
cb8e9e
+                        priv->up_children++;
cb8e9e
 
cb8e9e
                         child->child_up = 1;
cb8e9e
                         child->xl = subvol;
cb8e9e
-                        child->table = inode_table_new (4096, subvol);
cb8e9e
+                        if (!child->table)
cb8e9e
+                                child->table = inode_table_new (4096, subvol);
cb8e9e
 
cb8e9e
-                        priv->up_children++;
cb8e9e
-
cb8e9e
-                        list_add_tail (&child->list, &priv->bricks);
cb8e9e
+                        _br_qchild_event (this, child, br_brick_connect);
cb8e9e
                         pthread_cond_signal (&priv->cond);
cb8e9e
                 }
cb8e9e
         unblock:
cb8e9e
@@ -1410,6 +1462,7 @@ notify (xlator_t *this, int32_t event, void *data, ...)
cb8e9e
                 if (priv->up_children == 0)
cb8e9e
                         default_notify (this, event, data);
cb8e9e
                 break;
cb8e9e
+
cb8e9e
         default:
cb8e9e
                 default_notify (this, event, data);
cb8e9e
         }
cb8e9e
@@ -1563,59 +1616,94 @@ br_signer_init (xlator_t *this, br_private_t *priv)
cb8e9e
 
cb8e9e
 }
cb8e9e
 
cb8e9e
-int32_t
cb8e9e
-init (xlator_t *this)
cb8e9e
+static void
cb8e9e
+br_free_children (xlator_t *this, br_private_t *priv, int count)
cb8e9e
 {
cb8e9e
-        int            i    = 0;
cb8e9e
-        int32_t        ret  = -1;
cb8e9e
-        br_private_t  *priv = NULL;
cb8e9e
-        xlator_list_t *trav = NULL;
cb8e9e
+        br_child_t *child = NULL;
cb8e9e
 
cb8e9e
-        if (!this->children) {
cb8e9e
-                gf_msg (this->name, GF_LOG_ERROR, 0, BRB_MSG_NO_CHILD,
cb8e9e
-                        "FATAL: no children");
cb8e9e
-                goto out;
cb8e9e
+        for (--count; count >= 0; count--) {
cb8e9e
+                child = &priv->children[count];
cb8e9e
+                mem_pool_destroy (child->timer_pool);
cb8e9e
+                LOCK_DESTROY (&child->lock);
cb8e9e
         }
cb8e9e
 
cb8e9e
-        priv = GF_CALLOC (1, sizeof (*priv), gf_br_mt_br_private_t);
cb8e9e
-        if (!priv) {
cb8e9e
-                gf_msg (this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_NO_MEMORY,
cb8e9e
-                        "failed to allocate memory (->priv)");
cb8e9e
-                goto out;
cb8e9e
-        }
cb8e9e
+        GF_FREE (priv->children);
cb8e9e
+        priv->children = NULL;
cb8e9e
+}
cb8e9e
 
cb8e9e
-        GF_OPTION_INIT ("scrubber", priv->iamscrubber, bool, out);
cb8e9e
+static int
cb8e9e
+br_init_children (xlator_t *this, br_private_t *priv)
cb8e9e
+{
cb8e9e
+        int i = 0;
cb8e9e
+        br_child_t *child = NULL;
cb8e9e
+        xlator_list_t *trav = NULL;
cb8e9e
 
cb8e9e
         priv->child_count = xlator_subvolume_count (this);
cb8e9e
         priv->children = GF_CALLOC (priv->child_count, sizeof (*priv->children),
cb8e9e
                                     gf_br_mt_br_child_t);
cb8e9e
         if (!priv->children)
cb8e9e
-                goto free_priv;
cb8e9e
+                goto err;
cb8e9e
 
cb8e9e
         trav = this->children;
cb8e9e
         while (trav) {
cb8e9e
-                priv->children[i].this = this;
cb8e9e
-                priv->children[i].xl = trav->xlator;
cb8e9e
-
cb8e9e
-                priv->children[i].timer_pool =
cb8e9e
-                                  mem_pool_new (struct gf_tw_timer_list,  4096);
cb8e9e
-                if (!priv->children[i].timer_pool) {
cb8e9e
-                        gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
cb8e9e
-                                BRB_MSG_NO_MEMORY, "failed to allocate mem-pool"
cb8e9e
-                                " for timer");
cb8e9e
+                child = &priv->children[i];
cb8e9e
+
cb8e9e
+                LOCK_INIT (&child->lock);
cb8e9e
+                br_set_child_state (child, BR_CHILD_STATE_DISCONNECTED);
cb8e9e
+
cb8e9e
+                child->this = this;
cb8e9e
+                child->xl = trav->xlator;
cb8e9e
+
cb8e9e
+                child->timer_pool = mem_pool_new
cb8e9e
+                                    (struct gf_tw_timer_list,  4096);
cb8e9e
+                if (!child->timer_pool) {
cb8e9e
+                        gf_log (this->name, GF_LOG_ERROR,
cb8e9e
+                                "failed to allocate mem-pool for timer");
cb8e9e
                         errno = ENOMEM;
cb8e9e
-                        goto free_children;
cb8e9e
+                        goto freechild;
cb8e9e
                 }
cb8e9e
 
cb8e9e
+                INIT_LIST_HEAD (&child->list);
cb8e9e
+
cb8e9e
                 i++;
cb8e9e
                 trav = trav->next;
cb8e9e
         }
cb8e9e
 
cb8e9e
+        return 0;
cb8e9e
+
cb8e9e
+ freechild:
cb8e9e
+        br_free_children (this, priv, i);
cb8e9e
+ err:
cb8e9e
+        return -1;
cb8e9e
+}
cb8e9e
+
cb8e9e
+int32_t
cb8e9e
+init (xlator_t *this)
cb8e9e
+{
cb8e9e
+        int32_t       ret  = -1;
cb8e9e
+	br_private_t *priv = NULL;
cb8e9e
+
cb8e9e
+	if (!this->children) {
cb8e9e
+		gf_log (this->name, GF_LOG_ERROR, "FATAL: no children");
cb8e9e
+		goto out;
cb8e9e
+	}
cb8e9e
+
cb8e9e
+        priv = GF_CALLOC (1, sizeof (*priv), gf_br_mt_br_private_t);
cb8e9e
+        if (!priv) {
cb8e9e
+                gf_log (this->name, GF_LOG_ERROR,
cb8e9e
+                        "failed to allocate memory (->priv)");
cb8e9e
+                goto out;
cb8e9e
+        }
cb8e9e
+
cb8e9e
+        GF_OPTION_INIT ("scrubber", priv->iamscrubber, bool, out);
cb8e9e
+
cb8e9e
+        ret = br_init_children (this, priv);
cb8e9e
+        if (ret)
cb8e9e
+                goto free_priv;
cb8e9e
+
cb8e9e
         pthread_mutex_init (&priv->lock, NULL);
cb8e9e
         pthread_cond_init (&priv->cond, NULL);
cb8e9e
 
cb8e9e
-        for (i = 0; i < priv->child_count; i++)
cb8e9e
-                INIT_LIST_HEAD (&priv->children[i].list);
cb8e9e
         INIT_LIST_HEAD (&priv->bricks);
cb8e9e
         INIT_LIST_HEAD (&priv->signing);
cb8e9e
 
cb8e9e
@@ -1624,7 +1712,7 @@ init (xlator_t *this)
cb8e9e
                 gf_msg (this->name, GF_LOG_ERROR, 0,
cb8e9e
                         BRB_MSG_TIMER_WHEEL_UNAVAILABLE,
cb8e9e
                         "global timer wheel unavailable");
cb8e9e
-                goto cleanup_mutex;
cb8e9e
+                goto cleanup;
cb8e9e
         }
cb8e9e
 
cb8e9e
 	this->private = priv;
cb8e9e
@@ -1640,7 +1728,7 @@ init (xlator_t *this)
cb8e9e
         }
cb8e9e
 
cb8e9e
         if (ret)
cb8e9e
-                goto cleanup_mutex;
cb8e9e
+                goto cleanup;
cb8e9e
 
cb8e9e
         ret = gf_thread_create (&priv->thread, NULL, br_handle_events, this);
cb8e9e
         if (ret != 0) {
cb8e9e
@@ -1656,16 +1744,12 @@ init (xlator_t *this)
cb8e9e
                 return 0;
cb8e9e
         }
cb8e9e
 
cb8e9e
- cleanup_mutex:
cb8e9e
+ cleanup:
cb8e9e
         (void) pthread_cond_destroy (&priv->cond);
cb8e9e
         (void) pthread_mutex_destroy (&priv->lock);
cb8e9e
- free_children:
cb8e9e
-        for (i = 0; i < priv->child_count; i++) {
cb8e9e
-                if (priv->children[i].timer_pool)
cb8e9e
-                        mem_pool_destroy (priv->children[i].timer_pool);
cb8e9e
-        }
cb8e9e
 
cb8e9e
-        GF_FREE (priv->children);
cb8e9e
+        br_free_children (this, priv, priv->child_count);
cb8e9e
+
cb8e9e
  free_priv:
cb8e9e
         GF_FREE (priv);
cb8e9e
  out:
cb8e9e
@@ -1683,7 +1767,7 @@ fini (xlator_t *this)
cb8e9e
 
cb8e9e
         if (!priv->iamscrubber)
cb8e9e
                 br_fini_signer (this, priv);
cb8e9e
-        br_free_children (this);
cb8e9e
+        br_free_children (this, priv, priv->child_count);
cb8e9e
 
cb8e9e
         this->private = NULL;
cb8e9e
 	GF_FREE (priv);
cb8e9e
@@ -1691,64 +1775,96 @@ fini (xlator_t *this)
cb8e9e
 	return;
cb8e9e
 }
cb8e9e
 
cb8e9e
-int
cb8e9e
-reconfigure (xlator_t *this, dict_t *options)
cb8e9e
+static void
cb8e9e
+br_reconfigure_child (xlator_t *this,
cb8e9e
+                      br_child_t *child, struct br_scrubber *fsscrub)
cb8e9e
 {
cb8e9e
-        int i = 0;
cb8e9e
-        int32_t ret = -1;
cb8e9e
-        br_child_t *child = NULL;
cb8e9e
-        br_private_t *priv = NULL;
cb8e9e
-        struct br_scanfs *fsscan = NULL;
cb8e9e
+        int32_t ret = 0;
cb8e9e
+        struct br_scanfs *fsscan = &child->fsscan;
cb8e9e
+
cb8e9e
+        ret = br_fsscan_reschedule (this, child, fsscan, fsscrub, _gf_true);
cb8e9e
+        if (ret) {
cb8e9e
+                gf_log (this->name, GF_LOG_ERROR,
cb8e9e
+                        "Could not reschedule scrubber for brick: %s. "
cb8e9e
+                        "Scubbing will continue according to old frequency.",
cb8e9e
+                        child->brick_path);
cb8e9e
+        }
cb8e9e
+}
cb8e9e
+
cb8e9e
+static int
cb8e9e
+br_reconfigure_scrubber (xlator_t *this, dict_t *options)
cb8e9e
+{
cb8e9e
+        int                 i       = 0;
cb8e9e
+        int32_t             ret     = -1;
cb8e9e
+        br_child_t         *child   = NULL;
cb8e9e
+        br_private_t       *priv    = NULL;
cb8e9e
         struct br_scrubber *fsscrub = NULL;
cb8e9e
 
cb8e9e
         priv = this->private;
cb8e9e
+        fsscrub = &priv->fsscrub;
cb8e9e
 
cb8e9e
-        if (!priv->iamscrubber) {
cb8e9e
-                ret = br_signer_handle_options (this, priv, options);
cb8e9e
-                if (ret)
cb8e9e
-                        goto err;
cb8e9e
-                return 0;
cb8e9e
+        pthread_mutex_lock (&priv->lock);
cb8e9e
+        {
cb8e9e
+                ret = br_scrubber_handle_options (this, priv, options);
cb8e9e
         }
cb8e9e
+        pthread_mutex_unlock (&priv->lock);
cb8e9e
 
cb8e9e
-        ret = br_scrubber_handle_options (this, priv, options);
cb8e9e
         if (ret)
cb8e9e
                 goto err;
cb8e9e
 
cb8e9e
-        fsscrub = &priv->fsscrub;
cb8e9e
-
cb8e9e
         /* reschedule all _up_ subvolume(s) */
cb8e9e
-        pthread_mutex_lock (&priv->lock);
cb8e9e
-        {
cb8e9e
-                for (; i < priv->child_count; i++) {
cb8e9e
-                        child = &priv->children[i];
cb8e9e
-                        if (!child->child_up) {
cb8e9e
-                                gf_msg (this->name, GF_LOG_INFO, 0,
cb8e9e
-                                        BRB_MSG_BRICK_INFO, "Brick %s is "
cb8e9e
-                                        "offline, skipping rescheduling (scrub"
cb8e9e
-                                        " would auto- schedule when brick is "
cb8e9e
-                                        "back online).", child->brick_path);
cb8e9e
-                                continue;
cb8e9e
-                        }
cb8e9e
+        for (; i < priv->child_count; i++) {
cb8e9e
+                child = &priv->children[i];
cb8e9e
 
cb8e9e
-                        fsscan = &child->fsscan;
cb8e9e
-                        ret = br_fsscan_reschedule (this, child,
cb8e9e
-                                                    fsscan, fsscrub, _gf_true);
cb8e9e
-                        if (ret) {
cb8e9e
-                                gf_msg (this->name, GF_LOG_ERROR, 0,
cb8e9e
-                                        BRB_MSG_RESCHEDULE_SCRUBBER_FAILED,
cb8e9e
-                                        "Could not reschedule scrubber for "
cb8e9e
-                                        "brick: %s. Scubbing will continue "
cb8e9e
-                                        "according to old frequency.",
cb8e9e
-                                        child->brick_path);
cb8e9e
+                LOCK (&child->lock);
cb8e9e
+                {
cb8e9e
+                        if (_br_child_failed_conn (child)) {
cb8e9e
+                                gf_log (this->name, GF_LOG_INFO,
cb8e9e
+                                        "Scrubber for brick [%s] failed "
cb8e9e
+                                        "initialization, rescheduling is "
cb8e9e
+                                        "skipped", child->brick_path);
cb8e9e
+                                goto unblock;
cb8e9e
                         }
cb8e9e
+
cb8e9e
+                        if (_br_is_child_connected (child))
cb8e9e
+                                br_reconfigure_child (this, child, fsscrub);
cb8e9e
+
cb8e9e
+                        /**
cb8e9e
+                         * for the rest.. either the child is in initialization
cb8e9e
+                         * phase or is disconnected. either way, updated values
cb8e9e
+                         * would be reflected on successful connection.
cb8e9e
+                         */
cb8e9e
                 }
cb8e9e
+        unblock:
cb8e9e
+                UNLOCK (&child->lock);
cb8e9e
         }
cb8e9e
-        pthread_mutex_unlock (&priv->lock);
cb8e9e
-
cb8e9e
-        return 0;
cb8e9e
 
cb8e9e
  err:
cb8e9e
-        return -1;
cb8e9e
+        return ret;
cb8e9e
+}
cb8e9e
+
cb8e9e
+static int
cb8e9e
+br_reconfigure_signer (xlator_t *this, dict_t *options)
cb8e9e
+{
cb8e9e
+        br_private_t *priv = this->private;
cb8e9e
+
cb8e9e
+        return br_signer_handle_options (this, priv, options);
cb8e9e
+}
cb8e9e
+
cb8e9e
+int
cb8e9e
+reconfigure (xlator_t *this, dict_t *options)
cb8e9e
+{
cb8e9e
+        int ret = 0;
cb8e9e
+        br_private_t *priv = NULL;
cb8e9e
+
cb8e9e
+        priv = this->private;
cb8e9e
+
cb8e9e
+        if (priv->iamscrubber)
cb8e9e
+                ret = br_reconfigure_scrubber (this, options);
cb8e9e
+        else
cb8e9e
+                ret = br_reconfigure_signer (this, options);
cb8e9e
+
cb8e9e
+        return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
 struct xlator_fops fops;
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 562f17e..b8d9e3b 100644
cb8e9e
--- a/xlators/features/bit-rot/src/bitd/bit-rot.h
cb8e9e
+++ b/xlators/features/bit-rot/src/bitd/bit-rot.h
cb8e9e
@@ -76,7 +76,18 @@ struct br_scanfs {
cb8e9e
         struct gf_tw_timer_list *timer;
cb8e9e
 };
cb8e9e
 
cb8e9e
+/* just need three states to track child status */
cb8e9e
+typedef enum br_child_state {
cb8e9e
+        BR_CHILD_STATE_CONNECTED = 1,
cb8e9e
+        BR_CHILD_STATE_INITIALIZING,
cb8e9e
+        BR_CHILD_STATE_CONNFAILED,
cb8e9e
+        BR_CHILD_STATE_DISCONNECTED,
cb8e9e
+} br_child_state_t;
cb8e9e
+
cb8e9e
 struct br_child {
cb8e9e
+        gf_lock_t lock;
cb8e9e
+        br_child_state_t c_state;
cb8e9e
+
cb8e9e
         char child_up;                /* Indicates whether this child is
cb8e9e
                                          up or not */
cb8e9e
         xlator_t *xl;                 /* client xlator corresponding to
cb8e9e
@@ -140,8 +151,8 @@ typedef struct br_obj_n_workers br_obj_n_workers_t;
cb8e9e
 struct br_private {
cb8e9e
         pthread_mutex_t lock;
cb8e9e
 
cb8e9e
-        struct list_head bricks;          /* list of bricks from which CHILD_UP
cb8e9e
-                                             has been received */
cb8e9e
+        struct list_head bricks;          /* list of bricks from which enents
cb8e9e
+                                             have been received */
cb8e9e
 
cb8e9e
         struct list_head signing;
cb8e9e
 
cb8e9e
@@ -207,5 +218,22 @@ br_prepare_loc (xlator_t *, br_child_t *, loc_t *, gf_dirent_t *, loc_t *);
cb8e9e
 gf_boolean_t
cb8e9e
 bitd_is_bad_file (xlator_t *, br_child_t *, loc_t *, fd_t *);
cb8e9e
 
cb8e9e
+static inline void
cb8e9e
+_br_set_child_state (br_child_t *child, br_child_state_t state)
cb8e9e
+{
cb8e9e
+        child->c_state = state;
cb8e9e
+}
cb8e9e
+
cb8e9e
+static inline int
cb8e9e
+_br_is_child_connected (br_child_t *child)
cb8e9e
+{
cb8e9e
+        return (child->c_state == BR_CHILD_STATE_CONNECTED);
cb8e9e
+}
cb8e9e
+
cb8e9e
+static inline int
cb8e9e
+_br_child_failed_conn (br_child_t *child)
cb8e9e
+{
cb8e9e
+        return (child->c_state == BR_CHILD_STATE_CONNFAILED);
cb8e9e
+}
cb8e9e
 
cb8e9e
 #endif /* __BIT_ROT_H__ */
cb8e9e
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
cb8e9e
index fbb69ce..f70fafb 100644
cb8e9e
--- a/xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h
cb8e9e
+++ b/xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h
cb8e9e
@@ -31,6 +31,7 @@ enum br_mem_types {
cb8e9e
         gf_br_stub_mt_br_stub_fd_t,
cb8e9e
         gf_br_stub_mt_br_scanner_freq_t,
cb8e9e
         gf_br_stub_mt_sigstub_t,
cb8e9e
+        gf_br_mt_br_child_event_t,
cb8e9e
         gf_br_stub_mt_end,
cb8e9e
 };
cb8e9e
 
cb8e9e
-- 
cb8e9e
1.7.1
cb8e9e