diff options
| -rw-r--r-- | glusterfsd/src/glusterfsd-mgmt.c | 24 | ||||
| -rw-r--r-- | xlators/features/changelog/src/Makefile.am | 2 | ||||
| -rw-r--r-- | xlators/features/changelog/src/changelog-barrier.c | 70 | ||||
| -rw-r--r-- | xlators/features/changelog/src/changelog-helpers.c | 17 | ||||
| -rw-r--r-- | xlators/features/changelog/src/changelog-helpers.h | 17 | ||||
| -rw-r--r-- | xlators/features/changelog/src/changelog.c | 240 | 
6 files changed, 334 insertions, 36 deletions
diff --git a/glusterfsd/src/glusterfsd-mgmt.c b/glusterfsd/src/glusterfsd-mgmt.c index b1f00691c8c..0febaf20cbd 100644 --- a/glusterfsd/src/glusterfsd-mgmt.c +++ b/glusterfsd/src/glusterfsd-mgmt.c @@ -1219,6 +1219,8 @@ glusterfs_handle_barrier (rpcsvc_request_t *req)          xlator_t                *old_THIS   = NULL;          dict_t                  *dict       = NULL;          char                    name[1024]  = {0,}; +        gf_boolean_t            barrier     = _gf_true; +        gf_boolean_t            barrier_err = _gf_false;          GF_ASSERT (req); @@ -1269,7 +1271,14 @@ glusterfs_handle_barrier (rpcsvc_request_t *req)                  brick_rsp.op_ret = ret;                  brick_rsp.op_errstr = gf_strdup ("Failed to reconfigure "                                                   "barrier."); -                goto submit_reply; +                /* This is to invoke changelog-barrier disable if barrier +                 * disable fails and don't invoke if barrier enable fails. +                 */ +                barrier = dict_get_str_boolean (dict, "barrier", _gf_true); +                if (barrier) +                        goto submit_reply; +                else +                        barrier_err = _gf_true;          }          /* Reset THIS so that we have it correct in case of an error below @@ -1277,7 +1286,6 @@ glusterfs_handle_barrier (rpcsvc_request_t *req)          THIS = old_THIS;          /* Send barrier request to changelog as well */ -        /* Commenting out the below code till the changelog changes are merged          memset (name, 0, sizeof (name));          snprintf (name, sizeof (name), "%s-changelog", brick_req.name); @@ -1290,16 +1298,16 @@ glusterfs_handle_barrier (rpcsvc_request_t *req)          }          THIS = xlator; -        ret = xlator->reconfigure (xlator, dict); - - +        ret = xlator->notify (xlator, GF_EVENT_TRANSLATOR_OP, dict);          if (ret) {                  brick_rsp.op_ret = ret; -                brick_rsp.op_errstr = gf_strdup ("Failed to reconfigure " -                                                 "changelog."); +                brick_rsp.op_errstr = gf_strdup ("changelog notify failed");                  goto submit_reply;          } -        */ + +        if (barrier_err) +                ret = -1; +  submit_reply:          THIS = old_THIS; diff --git a/xlators/features/changelog/src/Makefile.am b/xlators/features/changelog/src/Makefile.am index c5d5e100e41..8e748f9dcde 100644 --- a/xlators/features/changelog/src/Makefile.am +++ b/xlators/features/changelog/src/Makefile.am @@ -8,7 +8,7 @@ noinst_HEADERS = changelog-helpers.h changelog-mem-types.h changelog-rt.h \  changelog_la_LDFLAGS = -module -avoid-version  changelog_la_SOURCES = changelog.c changelog-rt.c changelog-helpers.c \ -	changelog-encoders.c changelog-notifier.c +	changelog-encoders.c changelog-notifier.c changelog-barrier.c  changelog_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la  AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src -fPIC -D_FILE_OFFSET_BITS=64 \ diff --git a/xlators/features/changelog/src/changelog-barrier.c b/xlators/features/changelog/src/changelog-barrier.c new file mode 100644 index 00000000000..c20eed85b1c --- /dev/null +++ b/xlators/features/changelog/src/changelog-barrier.c @@ -0,0 +1,70 @@ +/* +     Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com> +     This file is part of GlusterFS. + +     This file is licensed to you under your choice of the GNU Lesser +     General Public License, version 3 or any later version (LGPLv3 or +     later), or the GNU General Public License, version 2 (GPLv2), in all +     cases as published by the Free Software Foundation. +*/ + +#include "changelog-helpers.h" +#include "call-stub.h" + +/* Enqueue a stub*/ +void +__chlog_barrier_enqueue (xlator_t *this, call_stub_t *stub) +{ +        changelog_priv_t *priv    = NULL; + +        priv = this->private; +        GF_ASSERT (priv); + +        list_add_tail (&stub->list, &priv->queue); +        priv->queue_size++; + +        return; +} + +/* Dequeue a stub */ +call_stub_t * +__chlog_barrier_dequeue (xlator_t *this, struct list_head *queue) +{ +        call_stub_t      *stub            = NULL; +        changelog_priv_t *priv            = NULL; + +        priv = this->private; +        GF_ASSERT (priv); + +        if (list_empty (queue)) +                goto out; + +        stub = list_entry (queue->next, call_stub_t, list); +        list_del_init (&stub->list); + +out: +        return stub; +} + +/* Dequeue all the stubs and call corresponding resume functions */ +void +chlog_barrier_dequeue_all (xlator_t *this, struct list_head *queue) +{ +        call_stub_t            *stub    = NULL; + +        while ((stub = __chlog_barrier_dequeue (this, queue))) +                call_resume (stub); + +        return; +} + +/* Disable changelog barrier enable flag */ +void +__chlog_barrier_disable (xlator_t *this, struct list_head *queue) +{ +        changelog_priv_t  *priv   = this->private; + +        list_splice_init (&priv->queue, queue); +        priv->queue_size = 0; +        priv->barrier_enabled = _gf_false; +} diff --git a/xlators/features/changelog/src/changelog-helpers.c b/xlators/features/changelog/src/changelog-helpers.c index c3661b9b76c..2d412e7b60d 100644 --- a/xlators/features/changelog/src/changelog-helpers.c +++ b/xlators/features/changelog/src/changelog-helpers.c @@ -988,9 +988,9 @@ changelog_barrier_notify (changelog_priv_t *priv, char *buf)  }  /* Clean up flags set on barrier notification */ -/*TODO: Add changelog barrier stop code with changelog barrier patch*/  inline void -changelog_barrier_cleanup (xlator_t *this, changelog_priv_t *priv) +changelog_barrier_cleanup (xlator_t *this, changelog_priv_t *priv, +                                                struct list_head *queue)  {          int ret = 0; @@ -1005,6 +1005,19 @@ changelog_barrier_cleanup (xlator_t *this, changelog_priv_t *priv)          }          ret = pthread_mutex_unlock (&priv->bn.bnotify_mutex);          CHANGELOG_PTHREAD_ERROR_HANDLE_0 (ret, out); + +        /* Disable changelog barrier and dequeue fops */ +        LOCK (&priv->lock); +        { +                if (priv->barrier_enabled == _gf_true) +                        __chlog_barrier_disable (this, queue); +                else +                        ret = -1; +        } +        UNLOCK (&priv->lock); +        if (ret == 0) +                chlog_barrier_dequeue_all(this, queue); +   out:          return;  } diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h index 54577592c90..8e591e2f935 100644 --- a/xlators/features/changelog/src/changelog-helpers.h +++ b/xlators/features/changelog/src/changelog-helpers.h @@ -17,6 +17,7 @@  #include "iobuf.h"  #include "changelog-misc.h" +#include "call-stub.h"  /**   * the changelog entry @@ -186,7 +187,7 @@ typedef struct drain_mgmt {           gf_boolean_t           drain_wait_white;  }drain_mgmt_t; -/* Internal and External barrier on/off indicating flags */ +/* External barrier as a result of snap on/off indicating flag*/  typedef struct barrier_flags {          gf_lock_t lock;          gf_boolean_t barrier_ext; @@ -265,6 +266,11 @@ struct changelog_priv {          /* barrier on/off indicating flags */          barrier_flags_t bflags; + +        /* changelog barrier on/off indicating flag */ +        gf_boolean_t      barrier_enabled; +        struct list_head  queue; +        uint32_t          queue_size;  };  struct changelog_local { @@ -401,12 +407,19 @@ changelog_dec_fop_cnt (xlator_t *this, changelog_priv_t *priv,  inline int  changelog_barrier_notify (changelog_priv_t *priv, char* buf);  inline void -changelog_barrier_cleanup (xlator_t *this, changelog_priv_t *priv); +changelog_barrier_cleanup (xlator_t *this, changelog_priv_t *priv, +                                                struct list_head *queue);  void  changelog_drain_white_fops (xlator_t *this, changelog_priv_t *priv);  void  changelog_drain_black_fops (xlator_t *this, changelog_priv_t *priv); +/* Changelog barrier routines */ +void __chlog_barrier_enqueue (xlator_t *this, call_stub_t *stub); +void __chlog_barrier_disable (xlator_t *this, struct list_head *queue); +void chlog_barrier_dequeue_all (xlator_t *this, struct list_head *queue); +call_stub_t *__chlog_barrier_dequeue (xlator_t *this, struct list_head *queue); +  /* macros */  #define CHANGELOG_STACK_UNWIND(fop, frame, params ...) do {             \ diff --git a/xlators/features/changelog/src/changelog.c b/xlators/features/changelog/src/changelog.c index 0a491c5ac07..1253a1a6829 100644 --- a/xlators/features/changelog/src/changelog.c +++ b/xlators/features/changelog/src/changelog.c @@ -69,12 +69,33 @@ changelog_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  }  int32_t +changelog_rmdir_resume (call_frame_t *frame, xlator_t *this, +                        loc_t *loc, int xflags, dict_t *xdata) +{ +        changelog_priv_t *priv     = NULL; + +        priv = this->private; + +        gf_log (this->name, GF_LOG_DEBUG, "Dequeue rmdir"); +        changelog_color_fop_and_inc_cnt (this, priv, frame->local); +        STACK_WIND (frame, changelog_rmdir_cbk, +                    FIRST_CHILD (this), FIRST_CHILD (this)->fops->rmdir, +                    loc, xflags, xdata); +        return 0; +} + +int32_t  changelog_rmdir (call_frame_t *frame, xlator_t *this,                   loc_t *loc, int xflags, dict_t *xdata)  { -        size_t            xtra_len = 0; -        changelog_priv_t *priv     = NULL; -        changelog_opt_t  *co       = NULL; +        size_t                  xtra_len                = 0; +        changelog_priv_t       *priv                    = NULL; +        changelog_opt_t        *co                      = NULL; +        call_stub_t            *stub                    = NULL; +        struct list_head        queue                   = {0, }; +        gf_boolean_t            barrier_enabled         = _gf_false; + +        INIT_LIST_HEAD (&queue);          priv = this->private;          CHANGELOG_NOT_ACTIVE_THEN_GOTO (frame, priv, wind); @@ -94,11 +115,49 @@ changelog_rmdir (call_frame_t *frame, xlator_t *this,          changelog_set_usable_record_and_length (frame->local, xtra_len, 2); +/* changelog barrier */ +        /* Color assignment and increment of fop_cnt for rmdir/unlink/rename +         * should be made with in priv lock if changelog barrier is not enabled. +         * Because if counter is not incremented yet, draining wakes up and +         * publishes the changelog but later these fops might hit the disk and +         * present in snapped volume but where as the intention is these fops +         * should not be present in snapped volume. +         */ +        LOCK (&priv->lock); +        { +                if ((barrier_enabled = priv->barrier_enabled)) { +                        stub = fop_rmdir_stub (frame, changelog_rmdir_resume, +                                                loc, xflags, xdata); +                        if (!stub) +                               __chlog_barrier_disable (this, &queue); +                        else +                               __chlog_barrier_enqueue (this, stub); +                } else { +                        ((changelog_local_t *)frame->local)->color +                                                          = priv->current_color; +                        changelog_inc_fop_cnt (this, priv, frame->local); +                } +        } +        UNLOCK (&priv->lock); + +        if (barrier_enabled && stub) { +                gf_log (this->name, GF_LOG_DEBUG, "Enqueue rmdir"); +                goto out; +        } +        if (barrier_enabled && !stub) { +                gf_log (this->name, GF_LOG_ERROR, +                        "Failed to barrier FOPs, disabling changelog barrier " +                        "FOP: rmdir, ERROR: %s", strerror (ENOMEM)); +                chlog_barrier_dequeue_all (this, &queue); +        } + +/* changelog barrier */ +   wind: -        changelog_color_fop_and_inc_cnt (this, priv, frame->local);          STACK_WIND (frame, changelog_rmdir_cbk,                      FIRST_CHILD (this), FIRST_CHILD (this)->fops->rmdir,                      loc, xflags, xdata); + out:          return 0;  } @@ -127,12 +186,33 @@ changelog_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  }  int32_t +changelog_unlink_resume (call_frame_t *frame, xlator_t *this, +                         loc_t *loc, int xflags, dict_t *xdata) +{ +        changelog_priv_t *priv     = NULL; + +        priv = this->private; + +        gf_log (this->name, GF_LOG_DEBUG, "Dequeue unlink"); +        changelog_color_fop_and_inc_cnt (this, priv, frame->local); +        STACK_WIND (frame, changelog_unlink_cbk, +                    FIRST_CHILD (this), FIRST_CHILD (this)->fops->unlink, +                    loc, xflags, xdata); +        return 0; +} + +int32_t  changelog_unlink (call_frame_t *frame, xlator_t *this,                    loc_t *loc, int xflags, dict_t *xdata)  { -        size_t            xtra_len = 0; -        changelog_priv_t *priv     = NULL; -        changelog_opt_t  *co       = NULL; +        size_t                  xtra_len                = 0; +        changelog_priv_t       *priv                    = NULL; +        changelog_opt_t        *co                      = NULL; +        call_stub_t            *stub                    = NULL; +        struct list_head        queue                   = {0, }; +        gf_boolean_t            barrier_enabled         = _gf_false; + +        INIT_LIST_HEAD (&queue);          priv = this->private;          CHANGELOG_NOT_ACTIVE_THEN_GOTO (frame, priv, wind); @@ -152,11 +232,42 @@ changelog_unlink (call_frame_t *frame, xlator_t *this,          changelog_set_usable_record_and_length (frame->local, xtra_len, 2); +/* changelog barrier */ +        LOCK (&priv->lock); +        { +                if ((barrier_enabled = priv->barrier_enabled)) { +                        stub = fop_unlink_stub (frame, changelog_unlink_resume, +                                                loc, xflags, xdata); +                        if (!stub) +                               __chlog_barrier_disable (this, &queue); +                        else +                               __chlog_barrier_enqueue (this, stub); +                } else { +                        ((changelog_local_t *)frame->local)->color +                                                          = priv->current_color; +                        changelog_inc_fop_cnt (this, priv, frame->local); +                } +        } +        UNLOCK (&priv->lock); + +        if (barrier_enabled && stub) { +                gf_log (this->name, GF_LOG_DEBUG, "Enqueue unlink"); +                goto out; +        } +        if (barrier_enabled && !stub) { +                gf_log (this->name, GF_LOG_ERROR, +                        "Failed to barrier FOPs, disabling changelog barrier " +                        "FOP: unlink, ERROR: %s", strerror (ENOMEM)); +                chlog_barrier_dequeue_all (this, &queue); +        } + +/* changelog barrier */ +   wind: -        changelog_color_fop_and_inc_cnt (this, priv, frame->local);          STACK_WIND (frame, changelog_unlink_cbk,                      FIRST_CHILD (this), FIRST_CHILD (this)->fops->unlink,                      loc, xflags, xdata); + out:          return 0;  } @@ -190,12 +301,33 @@ changelog_rename_cbk (call_frame_t *frame,  int32_t +changelog_rename_resume (call_frame_t *frame, xlator_t *this, +                         loc_t *oldloc, loc_t *newloc, dict_t *xdata) +{ +        changelog_priv_t *priv     = NULL; + +        priv = this->private; + +        gf_log (this->name, GF_LOG_DEBUG, "Dequeue rename"); +        changelog_color_fop_and_inc_cnt (this, priv, frame->local); +        STACK_WIND (frame, changelog_rename_cbk, +                    FIRST_CHILD (this), FIRST_CHILD (this)->fops->rename, +                    oldloc, newloc, xdata); +        return 0; +} + +int32_t  changelog_rename (call_frame_t *frame, xlator_t *this,                    loc_t *oldloc, loc_t *newloc, dict_t *xdata)  { -        size_t            xtra_len  = 0; -        changelog_priv_t *priv      = NULL; -        changelog_opt_t  *co        = NULL; +        size_t                  xtra_len                = 0; +        changelog_priv_t       *priv                    = NULL; +        changelog_opt_t        *co                      = NULL; +        call_stub_t            *stub                    = NULL; +        struct list_head        queue                   = {0, }; +        gf_boolean_t            barrier_enabled         = _gf_false; + +        INIT_LIST_HEAD (&queue);          priv = this->private;          CHANGELOG_NOT_ACTIVE_THEN_GOTO (frame, priv, wind); @@ -219,12 +351,41 @@ changelog_rename (call_frame_t *frame, xlator_t *this,                                entry_fn, entry_free_fn, xtra_len, wind);          changelog_set_usable_record_and_length (frame->local, xtra_len, 3); +/* changelog barrier */ +        LOCK (&priv->lock); +        { +                if ((barrier_enabled = priv->barrier_enabled)) { +                        stub = fop_rename_stub (frame, changelog_rename_resume, +                                                oldloc, newloc, xdata); +                        if (!stub) +                               __chlog_barrier_disable (this, &queue); +                        else +                               __chlog_barrier_enqueue (this, stub); +                } else { +                        ((changelog_local_t *)frame->local)->color +                                                          = priv->current_color; +                        changelog_inc_fop_cnt (this, priv, frame->local); +                } +        } +        UNLOCK (&priv->lock); + +        if (barrier_enabled && stub) { +                gf_log (this->name, GF_LOG_DEBUG, "Enqueue rename"); +                goto out; +        } +        if (barrier_enabled && !stub) { +                gf_log (this->name, GF_LOG_ERROR, +                        "Failed to barrier FOPs, disabling changelog barrier " +                        "FOP: rename, ERROR: %s", strerror (ENOMEM)); +                chlog_barrier_dequeue_all (this, &queue); +        } +/* changelog barrier */   wind: -        changelog_color_fop_and_inc_cnt (this, priv, frame->local);          STACK_WIND (frame, changelog_rename_cbk,                      FIRST_CHILD (this), FIRST_CHILD (this)->fops->rename,                      oldloc, newloc, xdata); + out:          return 0;  } @@ -1265,12 +1426,15 @@ changelog_spawn_notifier (xlator_t *this, changelog_priv_t *priv)  int  notify (xlator_t *this, int event, void *data, ...)  { -        changelog_priv_t       *priv           = NULL; -        dict_t                 *dict           = NULL; -        char                    buf[1]         = {1}; -        int                     barrier        = DICT_DEFAULT; -        gf_boolean_t            bclean_req     = _gf_false; -        int                     ret            = 0; +        changelog_priv_t       *priv            = NULL; +        dict_t                 *dict            = NULL; +        char                    buf[1]          = {1}; +        int                     barrier         = DICT_DEFAULT; +        gf_boolean_t            bclean_req      = _gf_false; +        int                     ret             = 0; +        struct list_head        queue           = {0, }; + +        INIT_LIST_HEAD (&queue);          priv = this->private;          if (!priv) @@ -1311,14 +1475,33 @@ notify (xlator_t *this, int event, void *data, ...)                                  goto out;                          } -                        /*TODO: STOP CHANGELOG BARRIER */ +                        /* Stop changelog barrier and dequeue all fops */ +                        LOCK (&priv->lock); +                        { +                                if (priv->barrier_enabled == _gf_true) +                                        __chlog_barrier_disable (this, &queue); +                                else +                                        ret = -1; +                        } +                        UNLOCK (&priv->lock); +                        /* If ret = -1, then changelog barrier is already +                         * disabled because of error or timeout. +                         */ +                        if (ret == 0) { +                                chlog_barrier_dequeue_all(this, &queue); +                                gf_log(this->name, GF_LOG_DEBUG, +                                       "Disabled changelog barrier"); +                        } else { +                                gf_log (this->name, GF_LOG_ERROR, +                                        "Changelog barrier already disabled"); +                        } +                          LOCK (&priv->bflags.lock);                          {                                  priv->bflags.barrier_ext = _gf_false;                          }                          UNLOCK (&priv->bflags.lock); -                        ret = 0;                          goto out;                  case BARRIER_ON: @@ -1353,13 +1536,20 @@ notify (xlator_t *this, int event, void *data, ...)                          CHANGELOG_PTHREAD_ERROR_HANDLE_1 (ret, out,                                                                      bclean_req); -                        /*TODO: START CHANGELOG BARRIER */ +                        /* Start changelog barrier */ +                        LOCK (&priv->lock); +                        { +                                priv->barrier_enabled = _gf_true; +                        } +                        UNLOCK (&priv->lock); +                        gf_log(this->name, GF_LOG_DEBUG, +                                           "Enabled changelog barrier");                          ret = changelog_barrier_notify(priv, buf);                          if (ret) {                                  gf_log (this->name, GF_LOG_ERROR,                                          "Explicit roll over: write failed"); -                                changelog_barrier_cleanup (this, priv); +                                changelog_barrier_cleanup (this, priv, &queue);                                  ret = -1;                                  goto out;                          } @@ -1406,7 +1596,7 @@ notify (xlator_t *this, int event, void *data, ...)   out:          if (bclean_req) -                changelog_barrier_cleanup (this, priv); +                changelog_barrier_cleanup (this, priv, &queue);          return ret;  } @@ -1787,6 +1977,10 @@ init (xlator_t *this)          cond_lock_init = _gf_true;          priv->bflags.barrier_ext = _gf_false; +        /* Changelog barrier init */ +        INIT_LIST_HEAD (&priv->queue); +        priv->barrier_enabled = _gf_false; +          ret = changelog_init (this, priv);          if (ret)                  goto out;  | 
