summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/mgmt/glusterd/src/Makefile.am3
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot.c339
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c301
-rw-r--r--xlators/protocol/server/src/server-helpers.c307
-rw-r--r--xlators/protocol/server/src/server-helpers.h15
-rw-r--r--xlators/protocol/server/src/server.c120
-rw-r--r--xlators/protocol/server/src/server.h29
7 files changed, 806 insertions, 308 deletions
diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am
index a6f49ae01..6d87b9469 100644
--- a/xlators/mgmt/glusterd/src/Makefile.am
+++ b/xlators/mgmt/glusterd/src/Makefile.am
@@ -11,7 +11,8 @@ glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c \
glusterd-volgen.c glusterd-rebalance.c glusterd-quota.c \
glusterd-geo-rep.c glusterd-replace-brick.c glusterd-log-ops.c \
glusterd-volume-ops.c glusterd-brick-ops.c glusterd-mountbroker.c \
- glusterd-syncop.c glusterd-hooks.c glusterd-volume-set.c
+ glusterd-syncop.c glusterd-hooks.c glusterd-volume-set.c \
+ glusterd-snapshot.c
glusterd_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \
$(top_builddir)/rpc/xdr/src/libgfxdr.la \
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
new file mode 100644
index 000000000..528308831
--- /dev/null
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
@@ -0,0 +1,339 @@
+/*
+ Copyright (c) 2010-2012 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.
+*/
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/resource.h>
+#include <sys/statvfs.h>
+
+#include "globals.h"
+#include "compat.h"
+#include "protocol-common.h"
+#include "xlator.h"
+#include "logging.h"
+#include "timer.h"
+#include "glusterd-mem-types.h"
+#include "glusterd.h"
+#include "glusterd-sm.h"
+#include "glusterd-op-sm.h"
+#include "glusterd-utils.h"
+#include "glusterd-store.h"
+#include "run.h"
+#include "glusterd-volgen.h"
+
+#include "syscall.h"
+#include "cli1-xdr.h"
+#include "xdr-generic.h"
+
+glusterd_snap_t*
+glusterd_new_snap_object()
+{
+ glusterd_snap_t *snap = NULL;
+
+ snap = GF_CALLOC (1, sizeof (*snap), gf_gld_mt_snap_t);
+
+ if (snap) {
+ LOCK_INIT (&snap->lock);
+ INIT_LIST_HEAD (&snap->snap_list);
+ snap->snap_status = GD_SNAP_STATUS_INIT;
+ }
+
+ return snap;
+
+};
+
+glusterd_snap_cg_t*
+glusterd_new_snap_cg_object(int64_t volume_count)
+{
+ glusterd_snap_cg_t *cg = NULL;
+ glusterd_volinfo_t *volinfo = NULL;
+
+ if (volume_count < 0) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Volume count < 0");
+ return NULL;
+ }
+
+ cg = GF_CALLOC (1, (sizeof (*cg) +
+ (volume_count * sizeof (*volinfo))),
+ gf_gld_mt_snap_cg_t);
+
+ if (cg) {
+ LOCK_INIT (&cg->lock);
+ INIT_LIST_HEAD (&cg->cg_list);
+ cg->cg_status = GD_SNAP_STATUS_INIT;
+ cg->volume_count = volume_count;
+ }
+
+ return cg;
+}
+
+int32_t
+glusterd_add_snap (glusterd_volinfo_t *volinfo, glusterd_snap_t *snap)
+{
+ int ret = -1;
+ uint64_t count = -1;
+ glusterd_snap_t *entry = NULL;
+ glusterd_snap_t *last = NULL;
+ glusterd_snap_t *tmp = NULL;
+
+ GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
+ GF_VALIDATE_OR_GOTO ("glusterd", snap, out);
+
+ LOCK (&volinfo->lock);
+ {
+ list_for_each_entry_safe (entry, tmp, &volinfo->snaps,
+ snap_list) {
+ count++;
+ if (!strcmp (entry->snap_name, snap->snap_name) ||
+ !uuid_compare (entry->snap_id, snap->snap_id)) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Found "
+ "duplicate snap %s (%s)",
+ entry->snap_name,
+ uuid_utoa (entry->snap_id));
+ goto unlock;
+ }
+ last = entry;
+ }
+ list_add (&snap->snap_list, &last->snap_list);
+
+ gf_log (THIS->name, GF_LOG_DEBUG, "Snap %s added @ %"PRIu64,
+ snap->snap_name, count);
+ ret = 0;
+ }
+unlock:
+ UNLOCK (&volinfo->lock);
+out:
+ return ret;
+}
+
+glusterd_snap_t*
+glusterd_find_snap_by_name (glusterd_volinfo_t *volinfo, char *snap_name)
+{
+ uint64_t count = -1;
+ glusterd_snap_t *entry = NULL;
+ glusterd_snap_t *dup = NULL;
+ glusterd_snap_t *tmp = NULL;
+
+ GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
+ GF_VALIDATE_OR_GOTO ("glusterd", snap_name, out);
+
+ LOCK (&volinfo->lock);
+ {
+ list_for_each_entry_safe (entry, tmp, &volinfo->snaps,
+ snap_list) {
+ count++;
+ if (!strcmp (entry->snap_name, snap_name)) {
+ gf_log (THIS->name, GF_LOG_DEBUG, "Found "
+ "snap %s (%s)", entry->snap_name,
+ uuid_utoa (entry->snap_id));
+ dup = entry;
+ break;
+ }
+ }
+ }
+ UNLOCK (&volinfo->lock);
+out:
+ return dup;
+}
+
+glusterd_snap_t*
+glusterd_find_snap_by_id (glusterd_volinfo_t *volinfo, uuid_t snap_id)
+{
+ uint64_t count = -1;
+ glusterd_snap_t *entry = NULL;
+ glusterd_snap_t *dup = NULL;
+ glusterd_snap_t *tmp = NULL;
+
+ GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
+ if (uuid_is_null(snap_id))
+ goto out;
+
+ LOCK (&volinfo->lock);
+ {
+ list_for_each_entry_safe (entry, tmp, &volinfo->snaps,
+ snap_list) {
+ count++;
+ if (!uuid_compare (entry->snap_id, snap_id)) {
+ gf_log (THIS->name, GF_LOG_DEBUG, "Found "
+ "snap %s (%s)", entry->snap_name,
+ uuid_utoa (entry->snap_id));
+ dup = entry;
+ break;
+ }
+ }
+ }
+ UNLOCK (&volinfo->lock);
+out:
+ return dup;
+}
+
+glusterd_snap_t*
+glusterd_remove_snap_by_id (glusterd_volinfo_t *volinfo, uuid_t snap_id)
+{
+ glusterd_snap_t *entry = NULL;
+
+ GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
+ if (uuid_is_null(snap_id))
+ goto out;
+
+ entry = glusterd_find_snap_by_id (volinfo, snap_id);
+
+ if (entry) {
+ LOCK (&volinfo->lock);
+ {
+ entry->snap_status = GD_SNAP_STATUS_DECOMMISSION;
+ list_del_init (&entry->snap_list);
+ }
+ UNLOCK (&volinfo->lock);
+ }
+out:
+ return entry;
+}
+
+glusterd_snap_t*
+glusterd_remove_snap_by_name (glusterd_volinfo_t *volinfo, char *snap_name)
+{
+ glusterd_snap_t *entry = NULL;
+
+ GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
+ GF_VALIDATE_OR_GOTO ("glusterd", snap_name, out);
+
+ entry = glusterd_find_snap_by_name (volinfo, snap_name);
+
+ if (entry) {
+ LOCK (&volinfo->lock);
+ {
+ entry->snap_status = GD_SNAP_STATUS_DECOMMISSION;
+ list_del_init (&entry->snap_list);
+ }
+ UNLOCK (&volinfo->lock);
+ }
+out:
+ return entry;
+}
+
+// Big lock should already acquired before this is called
+int32_t
+glusterd_add_snap_cg (glusterd_conf_t *conf, glusterd_snap_cg_t *cg)
+{
+ int ret = -1;
+ uint64_t count = -1;
+ glusterd_snap_cg_t *entry = NULL;
+ glusterd_snap_cg_t *last = NULL;
+ glusterd_snap_cg_t *tmp = NULL;
+
+ GF_VALIDATE_OR_GOTO (THIS->name, conf, out);
+ GF_VALIDATE_OR_GOTO (THIS->name, cg, out);
+
+ list_for_each_entry_safe (entry, tmp, &conf->snap_cg, cg_list) {
+ count++;
+ if (!strcmp (entry->cg_name, cg->cg_name) ||
+ !uuid_compare (entry->cg_id, cg->cg_id)) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Found duplicate "
+ "CG %s(%s)", entry->cg_name,
+ uuid_utoa(entry->cg_id));
+ goto out;
+ }
+ last = entry;
+ }
+ list_add (&cg->cg_list, &last->cg_list);
+ gf_log (THIS->name, GF_LOG_DEBUG, "Added CG %s (%s) @ %"PRIu64,
+ cg->cg_name, uuid_utoa(cg->cg_id), count);
+ ret = 0;
+out:
+ return ret;
+
+}
+
+
+glusterd_snap_cg_t*
+glusterd_find_snap_cg_by_name (glusterd_conf_t *conf, char *cg_name)
+{
+ glusterd_snap_cg_t *entry = NULL;
+ glusterd_snap_cg_t *dup = NULL;
+ glusterd_snap_cg_t *tmp = NULL;
+
+ GF_VALIDATE_OR_GOTO (THIS->name, conf, out);
+ GF_VALIDATE_OR_GOTO (THIS->name, cg_name, out);
+
+ list_for_each_entry_safe (entry, tmp, &conf->snap_cg, cg_list) {
+ if (!strcmp (entry->cg_name, cg_name)) {
+ gf_log (THIS->name, GF_LOG_DEBUG, "Found CG %s(%s)",
+ entry->cg_name, uuid_utoa(entry->cg_id));
+ dup = entry;
+ break;
+ }
+ }
+out:
+ return dup;
+}
+
+glusterd_snap_cg_t*
+glusterd_find_snap_cg_by_id (glusterd_conf_t *conf, uuid_t cg_id)
+{
+ glusterd_snap_cg_t *entry = NULL;
+ glusterd_snap_cg_t *dup = NULL;
+ glusterd_snap_cg_t *tmp = NULL;
+
+ GF_VALIDATE_OR_GOTO (THIS->name, conf, out);
+ if (uuid_is_null (cg_id))
+ goto out;
+
+ list_for_each_entry_safe (entry, tmp, &conf->snap_cg, cg_list) {
+ if (!uuid_compare (entry->cg_id, cg_id)) {
+ gf_log (THIS->name, GF_LOG_DEBUG, "Found CG %s(%s)",
+ entry->cg_name, uuid_utoa(entry->cg_id));
+ dup = entry;
+ break;
+ }
+ }
+out:
+ return dup;
+}
+
+glusterd_snap_cg_t*
+glusterd_remove_snap_cg_by_name (glusterd_conf_t *conf, char *cg_name)
+{
+ glusterd_snap_cg_t *entry = NULL;
+
+ GF_VALIDATE_OR_GOTO (THIS->name, conf, out);
+ GF_VALIDATE_OR_GOTO (THIS->name, cg_name, out);
+
+ entry = glusterd_find_snap_cg_by_name(conf, cg_name);
+ if (entry) {
+ entry->cg_status = GD_SNAP_STATUS_DECOMMISSION;
+ list_del_init (&entry->cg_list);
+ }
+out:
+ return entry;
+}
+
+glusterd_snap_cg_t*
+glusterd_remove_snap_cg_by_id (glusterd_conf_t *conf, uuid_t cg_id)
+{
+ glusterd_snap_cg_t *entry = NULL;
+
+ GF_VALIDATE_OR_GOTO (THIS->name, conf, out);
+ if (uuid_is_null (cg_id))
+ goto out;
+
+ entry = glusterd_find_snap_cg_by_id (conf, cg_id);
+ if (entry) {
+ entry->cg_status = GD_SNAP_STATUS_DECOMMISSION;
+ list_del_init (&entry->cg_list);
+ }
+out:
+ return entry;
+}
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index f89e6f716..7ad6cc882 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -7738,304 +7738,3 @@ out:
gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
-
-glusterd_snap_t*
-glusterd_new_snap_object()
-{
- glusterd_snap_t *snap = NULL;
-
- snap = GF_CALLOC (1, sizeof (*snap), gf_gld_mt_snap_t);
-
- if (snap) {
- LOCK_INIT (&snap->lock);
- INIT_LIST_HEAD (&snap->snap_list);
- snap->snap_status = GD_SNAP_STATUS_INIT;
- }
-
- return snap;
-
-};
-
-glusterd_snap_cg_t*
-glusterd_new_snap_cg_object(int64_t volume_count)
-{
- glusterd_snap_cg_t *cg = NULL;
- glusterd_volinfo_t *volinfo = NULL;
-
- if (volume_count < 0) {
- gf_log (THIS->name, GF_LOG_ERROR, "Volume count < 0");
- return NULL;
- }
-
- cg = GF_CALLOC (1, (sizeof (*cg) +
- (volume_count * sizeof (*volinfo))),
- gf_gld_mt_snap_cg_t);
-
- if (cg) {
- LOCK_INIT (&cg->lock);
- INIT_LIST_HEAD (&cg->cg_list);
- cg->cg_status = GD_SNAP_STATUS_INIT;
- cg->volume_count = volume_count;
- }
-
- return cg;
-}
-
-int32_t
-glusterd_add_snap (glusterd_volinfo_t *volinfo, glusterd_snap_t *snap)
-{
- int ret = -1;
- uint64_t count = -1;
- glusterd_snap_t *entry = NULL;
- glusterd_snap_t *last = NULL;
- glusterd_snap_t *tmp = NULL;
-
- GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
- GF_VALIDATE_OR_GOTO ("glusterd", snap, out);
-
- LOCK (&volinfo->lock);
- {
- list_for_each_entry_safe (entry, tmp, &volinfo->snaps,
- snap_list) {
- count++;
- if (!strcmp (entry->snap_name, snap->snap_name) ||
- !uuid_compare (entry->snap_id, snap->snap_id)) {
- gf_log (THIS->name, GF_LOG_ERROR, "Found "
- "duplicate snap %s (%s)",
- entry->snap_name,
- uuid_utoa (entry->snap_id));
- goto unlock;
- }
- last = entry;
- }
- list_add (&snap->snap_list, &last->snap_list);
-
- gf_log (THIS->name, GF_LOG_DEBUG, "Snap %s added @ %"PRIu64,
- snap->snap_name, count);
- ret = 0;
- }
-unlock:
- UNLOCK (&volinfo->lock);
-out:
- return ret;
-}
-
-glusterd_snap_t*
-glusterd_find_snap_by_name (glusterd_volinfo_t *volinfo, char *snap_name)
-{
- uint64_t count = -1;
- glusterd_snap_t *entry = NULL;
- glusterd_snap_t *dup = NULL;
- glusterd_snap_t *tmp = NULL;
-
- GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
- GF_VALIDATE_OR_GOTO ("glusterd", snap_name, out);
-
- LOCK (&volinfo->lock);
- {
- list_for_each_entry_safe (entry, tmp, &volinfo->snaps,
- snap_list) {
- count++;
- if (!strcmp (entry->snap_name, snap_name)) {
- gf_log (THIS->name, GF_LOG_DEBUG, "Found "
- "snap %s (%s)", entry->snap_name,
- uuid_utoa (entry->snap_id));
- dup = entry;
- break;
- }
- }
- }
- UNLOCK (&volinfo->lock);
-out:
- return dup;
-}
-
-glusterd_snap_t*
-glusterd_find_snap_by_id (glusterd_volinfo_t *volinfo, uuid_t snap_id)
-{
- uint64_t count = -1;
- glusterd_snap_t *entry = NULL;
- glusterd_snap_t *dup = NULL;
- glusterd_snap_t *tmp = NULL;
-
- GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
- if (uuid_is_null(snap_id))
- goto out;
-
- LOCK (&volinfo->lock);
- {
- list_for_each_entry_safe (entry, tmp, &volinfo->snaps,
- snap_list) {
- count++;
- if (!uuid_compare (entry->snap_id, snap_id)) {
- gf_log (THIS->name, GF_LOG_DEBUG, "Found "
- "snap %s (%s)", entry->snap_name,
- uuid_utoa (entry->snap_id));
- dup = entry;
- break;
- }
- }
- }
- UNLOCK (&volinfo->lock);
-out:
- return dup;
-}
-
-glusterd_snap_t*
-glusterd_remove_snap_by_id (glusterd_volinfo_t *volinfo, uuid_t snap_id)
-{
- glusterd_snap_t *entry = NULL;
-
- GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
- if (uuid_is_null(snap_id))
- goto out;
-
- entry = glusterd_find_snap_by_id (volinfo, snap_id);
-
- if (entry) {
- LOCK (&volinfo->lock);
- {
- entry->snap_status = GD_SNAP_STATUS_DECOMMISSION;
- list_del_init (&entry->snap_list);
- }
- UNLOCK (&volinfo->lock);
- }
-out:
- return entry;
-}
-
-glusterd_snap_t*
-glusterd_remove_snap_by_name (glusterd_volinfo_t *volinfo, char *snap_name)
-{
- glusterd_snap_t *entry = NULL;
-
- GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
- GF_VALIDATE_OR_GOTO ("glusterd", snap_name, out);
-
- entry = glusterd_find_snap_by_name (volinfo, snap_name);
-
- if (entry) {
- LOCK (&volinfo->lock);
- {
- entry->snap_status = GD_SNAP_STATUS_DECOMMISSION;
- list_del_init (&entry->snap_list);
- }
- UNLOCK (&volinfo->lock);
- }
-out:
- return entry;
-}
-
-// Big lock should already acquired before this is called
-int32_t
-glusterd_add_snap_cg (glusterd_conf_t *conf, glusterd_snap_cg_t *cg)
-{
- int ret = -1;
- uint64_t count = -1;
- glusterd_snap_cg_t *entry = NULL;
- glusterd_snap_cg_t *last = NULL;
- glusterd_snap_cg_t *tmp = NULL;
-
- GF_VALIDATE_OR_GOTO (THIS->name, conf, out);
- GF_VALIDATE_OR_GOTO (THIS->name, cg, out);
-
- list_for_each_entry_safe (entry, tmp, &conf->snap_cg, cg_list) {
- count++;
- if (!strcmp (entry->cg_name, cg->cg_name) ||
- !uuid_compare (entry->cg_id, cg->cg_id)) {
- gf_log (THIS->name, GF_LOG_ERROR, "Found duplicate "
- "CG %s(%s)", entry->cg_name,
- uuid_utoa(entry->cg_id));
- goto out;
- }
- last = entry;
- }
- list_add (&cg->cg_list, &last->cg_list);
- gf_log (THIS->name, GF_LOG_DEBUG, "Added CG %s (%s) @ %"PRIu64,
- cg->cg_name, uuid_utoa(cg->cg_id), count);
- ret = 0;
-out:
- return ret;
-
-}
-
-
-glusterd_snap_cg_t*
-glusterd_find_snap_cg_by_name (glusterd_conf_t *conf, char *cg_name)
-{
- glusterd_snap_cg_t *entry = NULL;
- glusterd_snap_cg_t *dup = NULL;
- glusterd_snap_cg_t *tmp = NULL;
-
- GF_VALIDATE_OR_GOTO (THIS->name, conf, out);
- GF_VALIDATE_OR_GOTO (THIS->name, cg_name, out);
-
- list_for_each_entry_safe (entry, tmp, &conf->snap_cg, cg_list) {
- if (!strcmp (entry->cg_name, cg_name)) {
- gf_log (THIS->name, GF_LOG_DEBUG, "Found CG %s(%s)",
- entry->cg_name, uuid_utoa(entry->cg_id));
- dup = entry;
- break;
- }
- }
-out:
- return dup;
-}
-
-glusterd_snap_cg_t*
-glusterd_find_snap_cg_by_id (glusterd_conf_t *conf, uuid_t cg_id)
-{
- glusterd_snap_cg_t *entry = NULL;
- glusterd_snap_cg_t *dup = NULL;
- glusterd_snap_cg_t *tmp = NULL;
-
- GF_VALIDATE_OR_GOTO (THIS->name, conf, out);
- if (uuid_is_null (cg_id))
- goto out;
-
- list_for_each_entry_safe (entry, tmp, &conf->snap_cg, cg_list) {
- if (!uuid_compare (entry->cg_id, cg_id)) {
- gf_log (THIS->name, GF_LOG_DEBUG, "Found CG %s(%s)",
- entry->cg_name, uuid_utoa(entry->cg_id));
- dup = entry;
- break;
- }
- }
-out:
- return dup;
-}
-
-glusterd_snap_cg_t*
-glusterd_remove_snap_cg_by_name (glusterd_conf_t *conf, char *cg_name)
-{
- glusterd_snap_cg_t *entry = NULL;
-
- GF_VALIDATE_OR_GOTO (THIS->name, conf, out);
- GF_VALIDATE_OR_GOTO (THIS->name, cg_name, out);
-
- entry = glusterd_find_snap_cg_by_name(conf, cg_name);
- if (entry) {
- entry->cg_status = GD_SNAP_STATUS_DECOMMISSION;
- list_del_init (&entry->cg_list);
- }
-out:
- return entry;
-}
-
-glusterd_snap_cg_t*
-glusterd_remove_snap_cg_by_id (glusterd_conf_t *conf, uuid_t cg_id)
-{
- glusterd_snap_cg_t *entry = NULL;
-
- GF_VALIDATE_OR_GOTO (THIS->name, conf, out);
- if (uuid_is_null (cg_id))
- goto out;
-
- entry = glusterd_find_snap_cg_by_id (conf, cg_id);
- if (entry) {
- entry->cg_status = GD_SNAP_STATUS_DECOMMISSION;
- list_del_init (&entry->cg_list);
- }
-out:
- return entry;
-}
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c
index 14d074124..053670765 100644
--- a/xlators/protocol/server/src/server-helpers.c
+++ b/xlators/protocol/server/src/server-helpers.c
@@ -1076,3 +1076,310 @@ server_cancel_grace_timer (xlator_t *this, client_t *client)
}
return cancelled;
}
+
+int32_t
+gf_barrier_transmit (server_conf_t *conf, gf_barrier_payload_t *payload)
+{
+ gf_barrier_t *barrier = NULL;
+ int32_t ret = -1;
+ client_t *client = NULL;
+ gf_boolean_t lk_heal = _gf_false;
+ call_frame_t *frame = NULL;
+ server_state_t *state = NULL;
+
+ GF_VALIDATE_OR_GOTO ("barrier", conf, out);
+ GF_VALIDATE_OR_GOTO ("barrier", conf->barrier, out);
+ GF_VALIDATE_OR_GOTO ("barrier", payload, out);
+
+ barrier = conf->barrier;
+
+ frame = payload->frame;
+ if (frame) {
+ state = CALL_STATE (frame);
+ frame->local = NULL;
+ client = state->client;
+ }
+
+ if (client)
+ lk_heal = ((server_conf_t *) client->this->private)->lk_heal;
+
+ ret = rpcsvc_submit_generic (payload->req, payload->rsp, 1,
+ payload->payload, payload->payload_count,
+ payload->iobref);
+ iobuf_unref (payload->iob);
+ if (ret == -1) {
+ gf_log_callingfn ("", GF_LOG_ERROR, "Reply submission failed");
+ if (frame && client && !lk_heal) {
+ server_connection_cleanup (frame->this, client,
+ INTERNAL_LOCKS | POSIX_LOCKS);
+ } else {
+ /* TODO: Failure of open(dir), create, inodelk, entrylk
+ or lk fops send failure must be handled specially. */
+ }
+ goto ret;
+ }
+
+ ret = 0;
+ret:
+ if (state) {
+ free_state (state);
+ }
+
+ if (frame) {
+ gf_client_unref (client);
+ STACK_DESTROY (frame->root);
+ }
+
+ if (payload->free_iobref) {
+ iobref_unref (payload->iobref);
+ }
+out:
+ return ret;
+}
+gf_barrier_payload_t *
+gf_barrier_dequeue (gf_barrier_t *barrier)
+{
+ gf_barrier_payload_t *payload = NULL;
+
+ if (!barrier || list_empty (&barrier->queue))
+ return NULL;
+
+ LOCK (&barrier->lock);
+ {
+ payload = list_entry (barrier->queue.next,
+ gf_barrier_payload_t, list);
+ list_del_init (&payload->list);
+ barrier->cur_size--;
+ }
+ UNLOCK (&barrier->lock);
+
+ return payload;
+}
+
+
+void
+gf_barrier_dequeue_start (void *data)
+{
+ server_conf_t *conf = NULL;
+ gf_barrier_t *barrier = NULL;
+ gf_barrier_payload_t *payload = NULL;
+
+ conf = (server_conf_t *)data;
+ if (!conf || !conf->barrier)
+ return;
+ barrier = conf->barrier;
+
+
+ while (!list_empty (&barrier->queue)) {
+ payload = gf_barrier_dequeue (barrier);
+ if (payload) {
+ if (gf_barrier_transmit (conf, payload)) {
+ gf_log ("server", GF_LOG_WARNING,
+ "Failed to transmit");
+ }
+ GF_FREE (payload);
+ }
+ }
+ return;
+}
+
+void
+gf_barrier_timeout (void *data)
+{
+ server_conf_t *conf = NULL;
+ gf_barrier_t *barrier = NULL;
+ gf_boolean_t need_dequeue = _gf_false;
+
+ conf = (server_conf_t *)data;
+ if (!conf || !conf->barrier)
+ goto out;
+ barrier = conf->barrier;
+
+ LOCK (&barrier->lock);
+ {
+ need_dequeue = barrier->on;
+ barrier->on = _gf_false;
+ }
+ UNLOCK (&barrier->lock);
+
+ if (need_dequeue == _gf_true)
+ gf_barrier_dequeue_start (data);
+out:
+ return;
+}
+
+
+int32_t
+gf_barrier_start (xlator_t *this)
+{
+ server_conf_t *conf = NULL;
+ gf_barrier_t *barrier = NULL;
+ int32_t ret = -1;
+ struct timeval time = {0,};
+
+ conf = this->private;
+
+ GF_VALIDATE_OR_GOTO ("server", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, conf, out);
+ GF_VALIDATE_OR_GOTO (this->name, conf->barrier, out);
+
+ barrier = conf->barrier;
+
+ LOCK (&barrier->lock);
+ {
+ /* if barrier is on, reset timer */
+ if (barrier->on == _gf_true) {
+ ret = gf_timer_call_cancel (this->ctx, barrier->timer);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "unset timer, failing barrier start");
+ goto unlock;
+ }
+ }
+
+ barrier->on = _gf_true;
+ time.tv_sec = barrier->time_out;
+ time.tv_usec = 0;
+ barrier->timer = gf_timer_call_after (this->ctx, time,
+ gf_barrier_timeout,
+ (void *)conf);
+ if (!barrier->timer) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to set "
+ "timer, failing barrier start");
+ barrier->on = _gf_false;
+ }
+ }
+unlock:
+ UNLOCK (&barrier->lock);
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int32_t
+gf_barrier_stop (xlator_t *this)
+{
+ server_conf_t *conf = NULL;
+ gf_barrier_t *barrier = NULL;
+ int32_t ret = -1;
+ gf_boolean_t need_dequeue = _gf_false;
+
+ conf = this->private;
+
+ GF_VALIDATE_OR_GOTO ("server", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, conf, out);
+ GF_VALIDATE_OR_GOTO (this->name, conf->barrier, out);
+
+ barrier = conf->barrier;
+
+ LOCK (&barrier->lock);
+ {
+ need_dequeue = barrier->on;
+ barrier->on = _gf_false;
+ }
+ UNLOCK (&barrier->lock);
+
+ if (need_dequeue == _gf_true) {
+ gf_timer_call_cancel (this->ctx, barrier->timer);
+ gf_barrier_dequeue_start (conf);
+ }
+ ret = 0;
+out:
+ return ret;
+}
+
+int32_t
+gf_barrier_fops_configure (xlator_t *this, gf_barrier_t *barrier, char *str)
+{
+ int32_t ret = -1;
+ char *dup_str = NULL;
+ char *str_tok = NULL;
+ char *save_ptr = NULL;
+ uint64_t fops = 0;
+
+ /* by defaul fsync & flush needs to be barriered */
+
+ fops |= 1 << GFS3_OP_FSYNC;
+ fops |= 1 << GFS3_OP_FLUSH;
+
+ if (!str)
+ goto done;
+
+ dup_str = gf_strdup (str);
+ if (!dup_str)
+ goto done;
+
+ str_tok = strtok_r (dup_str, ",", &save_ptr);
+ if (!str_tok)
+ goto done;
+
+ fops = 0;
+ while (str_tok) {
+ if (!strcmp(str_tok, "writev")) {
+ fops |= ((uint64_t)1 << GFS3_OP_WRITE);
+ } else if (!strcmp(str_tok, "fsync")) {
+ fops |= ((uint64_t)1 << GFS3_OP_FSYNC);
+ } else if (!strcmp(str_tok, "read")) {
+ fops |= ((uint64_t)1 << GFS3_OP_READ);
+ } else if (!strcmp(str_tok, "rename")) {
+ fops |= ((uint64_t)1 << GFS3_OP_RENAME);
+ } else if (!strcmp(str_tok, "flush")) {
+ fops |= ((uint64_t)1 << GFS3_OP_FLUSH);
+ } else if (!strcmp(str_tok, "ftruncate")) {
+ fops |= ((uint64_t)1 << GFS3_OP_FTRUNCATE);
+ } else if (!strcmp(str_tok, "fallocate")) {
+ fops |= ((uint64_t)1 << GFS3_OP_FALLOCATE);
+ } else if (!strcmp(str_tok, "rmdir")) {
+ fops |= ((uint64_t)1 << GFS3_OP_RMDIR);
+ } else {
+ gf_log ("barrier", GF_LOG_ERROR,
+ "Invalid barrier fop %s", str_tok);
+ }
+
+ str_tok = strtok_r (NULL, ",", &save_ptr);
+ }
+done:
+ LOCK (&barrier->lock);
+ {
+ barrier->fops = fops;
+ }
+ ret = 0;
+
+ GF_FREE (dup_str);
+ return ret;
+}
+
+
+void
+gf_barrier_enqueue (gf_barrier_t *barrier, gf_barrier_payload_t *payload)
+{
+ list_add_tail (&payload->list, &barrier->queue);
+ barrier->cur_size++;
+}
+
+gf_barrier_payload_t *
+gf_barrier_payload (rpcsvc_request_t *req, struct iovec *rsp,
+ call_frame_t *frame, struct iovec *payload_orig,
+ int payloadcount, struct iobref *iobref,
+ struct iobuf *iob, gf_boolean_t free_iobref)
+{
+ gf_barrier_payload_t *payload = NULL;
+
+ payload = GF_CALLOC (1, sizeof (*payload),1);
+ if (!payload)
+ return NULL;
+
+ INIT_LIST_HEAD (&payload->list);
+
+ payload->req = req;
+ payload->rsp = rsp;
+ payload->frame = frame;
+ payload->payload = payload_orig;
+ payload->payload_count = payloadcount;
+ payload->iobref = iobref;
+ payload->iob = iob;
+ payload->free_iobref = free_iobref;
+
+ return payload;
+}
diff --git a/xlators/protocol/server/src/server-helpers.h b/xlators/protocol/server/src/server-helpers.h
index 987528fbd..bbbe0650d 100644
--- a/xlators/protocol/server/src/server-helpers.h
+++ b/xlators/protocol/server/src/server-helpers.h
@@ -31,6 +31,10 @@
#define IS_NOT_ROOT(pathlen) ((pathlen > 2)? 1 : 0)
+#define is_fop_barriered(fops, procnum) (fops & ((uint64_t)1 << procnum))
+
+#define barrier_add_to_queue(barrier) (barrier->on || barrier->cur_size)
+
void free_state (server_state_t *state);
void server_loc_wipe (loc_t *loc);
@@ -55,5 +59,14 @@ int serialize_rsp_dirent (gf_dirent_t *entries, gfs3_readdir_rsp *rsp);
int serialize_rsp_direntp (gf_dirent_t *entries, gfs3_readdirp_rsp *rsp);
int readdirp_rsp_cleanup (gfs3_readdirp_rsp *rsp);
int readdir_rsp_cleanup (gfs3_readdir_rsp *rsp);
-
+int32_t gf_barrier_start (xlator_t *this);
+int32_t gf_barrier_stop (xlator_t *this);
+int32_t gf_barrier_fops_configure (xlator_t *this, gf_barrier_t *barrier,
+ char *str);
+void gf_barrier_enqueue (gf_barrier_t *barrier, gf_barrier_payload_t *stub);
+gf_barrier_payload_t *
+gf_barrier_payload (rpcsvc_request_t *req, struct iovec *rsp,
+ call_frame_t *frame, struct iovec *payload,
+ int payloadcount, struct iobref *iobref,
+ struct iobuf *iob, gf_boolean_t free_iobref);
#endif /* !_SERVER_HELPERS_H */
diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c
index aa091e2e5..9a59634a9 100644
--- a/xlators/protocol/server/src/server.c
+++ b/xlators/protocol/server/src/server.c
@@ -124,8 +124,6 @@ ret:
return iob;
}
-
-
int
server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg,
struct iovec *payload, int payloadcount,
@@ -138,6 +136,9 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg,
char new_iobref = 0;
client_t *client = NULL;
gf_boolean_t lk_heal = _gf_false;
+ server_conf_t *conf = NULL;
+ gf_barrier_t *barrier = NULL;
+ gf_barrier_payload_t *stub = NULL;
GF_VALIDATE_OR_GOTO ("server", req, ret);
@@ -145,6 +146,7 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg,
state = CALL_STATE (frame);
frame->local = NULL;
client = state->client;
+ conf = (server_conf_t *) client->this->private;
}
if (client)
@@ -167,6 +169,30 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg,
iobref_add (iobref, iob);
+ if (conf)
+ barrier = conf->barrier;
+ if (barrier) {
+ /* todo: write's with fd flags set to O_SYNC and O_DIRECT */
+ LOCK (&barrier->lock);
+ {
+ if (is_fop_barriered (barrier->fops, req->procnum) &&
+ (barrier_add_to_queue (barrier))) {
+ stub = gf_barrier_payload (req, &rsp, frame,
+ payload,
+ payloadcount, iobref,
+ iob, new_iobref);
+ if (stub) {
+ gf_barrier_enqueue (barrier, stub);
+ goto ret;
+ } else {
+ gf_log ("", GF_LOG_ERROR, "Failed to "
+ " barrier fop %"PRIu64,
+ ((uint64_t)1 << req->procnum));
+ }
+ }
+ }
+ UNLOCK (&barrier->lock);
+ }
/* Then, submit the message for transmission. */
ret = rpcsvc_submit_generic (req, &rsp, 1, payload, payloadcount,
iobref);
@@ -208,7 +234,6 @@ ret:
if (new_iobref) {
iobref_unref (iobref);
}
-
return ret;
}
@@ -760,6 +785,8 @@ init (xlator_t *this)
server_conf_t *conf = NULL;
rpcsvc_listener_t *listener = NULL;
char *statedump_path = NULL;
+ gf_barrier_t *barrier = NULL;
+ char *str = NULL;
GF_VALIDATE_OR_GOTO ("init", this, out);
if (this->children == NULL) {
@@ -900,6 +927,35 @@ init (xlator_t *this)
}
}
#endif
+ /* barrier related */
+ barrier = GF_CALLOC (1, sizeof (*barrier),1);
+ if (!barrier) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "WARNING: Failed to allocate barrier");
+ ret = -1;
+ goto out;
+ }
+
+ LOCK_INIT (&barrier->lock);
+
+ GF_OPTION_INIT ("barrier-queue-length", barrier->max_size,
+ int64, out);
+ GF_OPTION_INIT ("barrier-timeout", barrier->time_out,
+ uint64, out);
+
+ ret = dict_get_str (this->options, "barrier-fops", &str);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "setting barrier fops to default value");
+ }
+ ret = gf_barrier_fops_configure (this, barrier, str);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "invalid barrier fops specified");
+ goto out;
+ }
+
+ conf->barrier = barrier;
this->private = conf;
ret = 0;
@@ -953,12 +1009,49 @@ int
notify (xlator_t *this, int32_t event, void *data, ...)
{
int ret = 0;
+ int32_t val = 0;
+ dict_t *dict = NULL;
+ dict_t *output = NULL;
+ va_list ap;
+
+ dict = data;
+ va_start (ap, data);
+ output = va_arg (ap, dict_t*);
+ va_end (ap);
+
switch (event) {
+ /* todo: GF_EVENT_BARRIER */
+ case 100:
+ ret = dict_get_int32 (dict, "barrier", &val);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Wrong BARRIER event");
+ goto out;
+ }
+ /* !val un-barrier, if val, barrier */
+ if (val) {
+ ret = gf_barrier_start (this);
+ if (ret)
+ gf_log (this->name, GF_LOG_ERROR,
+ "Barrier start failed");
+ } else {
+ ret = gf_barrier_stop (this);
+ if (ret)
+ gf_log (this->name, GF_LOG_ERROR,
+ "Barrier stop failed");
+ }
+ ret = dict_set_int32 (dict, "barrier-status", ret);
+ if (ret)
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to set barrier-status in dict");
+ break;
+
+ /* todo: call default_notify to make other xlators handle it.*/
default:
default_notify (this, event, data);
break;
}
-
+out:
return ret;
}
@@ -1062,6 +1155,23 @@ struct volume_options options[] = {
"hostnames to connect to the server. By default, all"
" connections are allowed."
},
-
+ {.key = {"barrier-timeout"},
+ .type = GF_OPTION_TYPE_INT,
+ .default_value = "60",
+ .min = 0,
+ .max = 360,
+ .description = "Barrier timeout in seconds",
+ },
+ {.key = {"barrier-queue-length"},
+ .type = GF_OPTION_TYPE_INT,
+ .default_value = "4096",
+ .min = 0,
+ .max = 16384,
+ .description = "Barrier queue length",
+ },
+ {.key = {"barrier-fops"},
+ .type = GF_OPTION_TYPE_STR,
+ .description = "Allow a comma seperated fop lists",
+ },
{ .key = {NULL} },
};
diff --git a/xlators/protocol/server/src/server.h b/xlators/protocol/server/src/server.h
index 6675d5b1a..0484ae988 100644
--- a/xlators/protocol/server/src/server.h
+++ b/xlators/protocol/server/src/server.h
@@ -26,6 +26,34 @@
#define GF_MAX_SOCKET_WINDOW_SIZE (1 * GF_UNIT_MB)
#define GF_MIN_SOCKET_WINDOW_SIZE (0)
+struct _gf_barrier_payload {
+ rpcsvc_request_t *req;
+ struct iovec *rsp;
+ call_frame_t *frame;
+ struct iovec *payload;
+ struct iobref *iobref;
+ struct iobuf *iob;
+ int payload_count;
+ gf_boolean_t free_iobref;
+ struct list_head list;
+};
+
+typedef struct _gf_barrier_payload gf_barrier_payload_t;
+
+struct _gf_barrier {
+ gf_lock_t lock;
+ gf_boolean_t on;
+ gf_boolean_t force;
+ size_t cur_size;
+ int64_t max_size;
+ uint64_t fops;
+ gf_timer_t *timer;
+ uint64_t time_out;
+ struct list_head queue;
+};
+
+typedef struct _gf_barrier gf_barrier_t;
+
typedef enum {
INTERNAL_LOCKS = 1,
POSIX_LOCKS = 2,
@@ -54,6 +82,7 @@ struct server_conf {
struct timeval grace_tv;
dict_t *auth_modules;
pthread_mutex_t mutex;
+ gf_barrier_t *barrier;
struct list_head xprt_list;
};
typedef struct server_conf server_conf_t;