From 453cb4bf0b70c876eb468def34054095cfd66359 Mon Sep 17 00:00:00 2001 From: Vijay Bellur Date: Fri, 6 Aug 2010 05:25:16 +0000 Subject: v2[PATCH BUG:1286] glusterd: Regain volume state upon re-start Signed-off-by: Vijay Bellur Signed-off-by: Anand V. Avati BUG: 1286 () URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1286 --- xlators/mgmt/glusterd/src/Makefile.am | 4 +- xlators/mgmt/glusterd/src/glusterd-ha.c | 171 ----- xlators/mgmt/glusterd/src/glusterd-ha.h | 46 -- xlators/mgmt/glusterd/src/glusterd-mem-types.h | 2 + xlators/mgmt/glusterd/src/glusterd-op-sm.c | 14 +- xlators/mgmt/glusterd/src/glusterd-store.c | 961 +++++++++++++++++++++++++ xlators/mgmt/glusterd/src/glusterd-store.h | 90 +++ xlators/mgmt/glusterd/src/glusterd-utils.c | 1 + xlators/mgmt/glusterd/src/glusterd.c | 29 +- xlators/mgmt/glusterd/src/glusterd.h | 40 +- 10 files changed, 1112 insertions(+), 246 deletions(-) delete mode 100644 xlators/mgmt/glusterd/src/glusterd-ha.c delete mode 100644 xlators/mgmt/glusterd/src/glusterd-ha.h create mode 100644 xlators/mgmt/glusterd/src/glusterd-store.c create mode 100644 xlators/mgmt/glusterd/src/glusterd-store.h (limited to 'xlators/mgmt/glusterd/src') diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am index 83f67b92e..adc7ee30b 100644 --- a/xlators/mgmt/glusterd/src/Makefile.am +++ b/xlators/mgmt/glusterd/src/Makefile.am @@ -2,12 +2,12 @@ xlator_LTLIBRARIES = glusterd.la xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/mgmt glusterd_la_LDFLAGS = -module -avoidversion glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c glusterd-op-sm.c \ - glusterd-utils.c glusterd3_1-mops.c glusterd-ha.c glusterd-handshake.c + glusterd-utils.c glusterd3_1-mops.c glusterd-store.c glusterd-handshake.c glusterd_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la\ $(top_builddir)/rpc/xdr/src/libgfxdr.la\ $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la -noinst_HEADERS = glusterd.h glusterd-utils.h glusterd-op-sm.h glusterd-sm.h glusterd-ha.h glusterd-mem-types.h +noinst_HEADERS = glusterd.h glusterd-utils.h glusterd-op-sm.h glusterd-sm.h glusterd-store.h glusterd-mem-types.h AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\ -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS)\ diff --git a/xlators/mgmt/glusterd/src/glusterd-ha.c b/xlators/mgmt/glusterd/src/glusterd-ha.c deleted file mode 100644 index ebf6ce066..000000000 --- a/xlators/mgmt/glusterd/src/glusterd-ha.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - Copyright (c) 2007-2010 Gluster, Inc. - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - . -*/ -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif -#include - - -#include "globals.h" -#include "glusterfs.h" -#include "compat.h" -#include "dict.h" -#include "protocol-common.h" -#include "xlator.h" -#include "logging.h" -#include "timer.h" -#include "defaults.h" -#include "compat.h" -#include "compat-errno.h" -#include "statedump.h" -#include "glusterd-mem-types.h" -#include "glusterd.h" -#include "glusterd-sm.h" -#include "glusterd-op-sm.h" -#include "glusterd-utils.h" -#include "glusterd-ha.h" - -#include "glusterd1.h" -#include "cli1.h" -#include "rpc-clnt.h" - -#include -#include -#include - -int32_t -glusterd_ha_create_volume (glusterd_volinfo_t *volinfo) -{ - char pathname[PATH_MAX] = {0,}; - int32_t ret = -1; - char filepath[PATH_MAX] = {0,}; - char buf[4096] = {0,}; - int fd = -1; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (volinfo); - priv = THIS->private; - - GF_ASSERT (priv); - - snprintf (pathname, 1024, "%s/vols/%s", priv->workdir, - volinfo->volname); - - ret = mkdir (pathname, 0x777); - - if (-1 == ret) { - gf_log ("", GF_LOG_ERROR, "mkdir() failed on path %s," - "errno: %d", pathname, errno); - goto out; - } - - snprintf (filepath, 1024, "%s/info", pathname); - - fd = open (filepath, O_RDWR | O_CREAT | O_APPEND, 0644); - - if (-1 == fd) { - gf_log ("", GF_LOG_ERROR, "open() failed on path %s," - "errno: %d", filepath, errno); - ret = -1; - goto out; - } - - snprintf (buf, 4096, "type=%d\n", volinfo->type); - ret = write (fd, buf, strlen (buf)); - snprintf (buf, 4096, "count=%d\n", volinfo->brick_count); - ret = write (fd, buf, strlen (buf)); - close (fd); - - ret = 0; - -out: - if (ret) { - glusterd_ha_delete_volume (volinfo); - } - - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - - -int32_t -glusterd_ha_delete_volume (glusterd_volinfo_t *volinfo) -{ - char pathname[PATH_MAX] = {0,}; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - DIR *dir = NULL; - struct dirent *entry = NULL; - char path[PATH_MAX] = {0,}; - - GF_ASSERT (volinfo); - priv = THIS->private; - - GF_ASSERT (priv); - snprintf (pathname, 1024, "%s/vols/%s", priv->workdir, - volinfo->volname); - - dir = opendir (pathname); - if (!dir) - goto out; - - entry = readdir (dir); - while (entry != NULL) { - if (!strcmp (entry->d_name, ".") || - !strcmp (entry->d_name, "..")) { - entry = readdir (dir); - continue; - } - snprintf (path, PATH_MAX, "%s/%s", pathname, entry->d_name); - if (DT_DIR == entry->d_type) - ret = rmdir (path); - else - ret = unlink (path); - - gf_log ("", GF_LOG_NORMAL, "%s %s", - ret?"Failed to remove":"Removed", - entry->d_name); - if (ret) - gf_log ("", GF_LOG_NORMAL, "errno:%d", errno); - entry = readdir (dir); - memset (path, 0, sizeof(path)); - } - - ret = closedir (dir); - if (ret) { - gf_log ("", GF_LOG_NORMAL, "Failed to close dir, errno:%d", - errno); - } - - ret = rmdir (pathname); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Failed to rmdir: %s, errno: %d", - pathname, errno); - } - - -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - - diff --git a/xlators/mgmt/glusterd/src/glusterd-ha.h b/xlators/mgmt/glusterd/src/glusterd-ha.h deleted file mode 100644 index b31142a67..000000000 --- a/xlators/mgmt/glusterd/src/glusterd-ha.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (c) 2006-2010 Gluster, Inc. - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - . -*/ - -#ifndef _GLUSTERD_HA_H_ -#define _GLUSTERD_HA_H_ - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include -#include "uuid.h" - -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" -#include "call-stub.h" -#include "fd.h" -#include "byte-order.h" -#include "glusterd.h" -#include "rpcsvc.h" - -int32_t -glusterd_ha_create_volume (glusterd_volinfo_t *volinfo); - -int32_t -glusterd_ha_delete_volume (glusterd_volinfo_t *volinfo); - -#endif diff --git a/xlators/mgmt/glusterd/src/glusterd-mem-types.h b/xlators/mgmt/glusterd/src/glusterd-mem-types.h index 2cbdf22ab..8df94163d 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mem-types.h +++ b/xlators/mgmt/glusterd/src/glusterd-mem-types.h @@ -52,6 +52,8 @@ enum gf_gld_mem_types_ { gf_gld_mt_glusterd_brickinfo_t, gf_gld_mt_peer_hostname_t, gf_gld_mt_ifreq, + gf_gld_mt_store_handle_t, + gf_gld_mt_store_iter_t, gf_gld_mt_end }; #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 55533c118..31e2a9e50 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -43,7 +43,7 @@ #include "glusterd-sm.h" #include "glusterd-op-sm.h" #include "glusterd-utils.h" -#include "glusterd-ha.h" +#include "glusterd-store.h" #include "cli1.h" static struct list_head gd_op_sm_queue; @@ -690,7 +690,7 @@ glusterd_op_create_volume (gd1_mgmt_stage_op_req *req) } list_add_tail (&volinfo->vol_list, &priv->volumes); - ret = glusterd_ha_create_volume (volinfo); + ret = glusterd_store_create_volume (volinfo); if (ret) goto out; @@ -816,11 +816,11 @@ glusterd_op_add_brick (gd1_mgmt_stage_op_req *req) goto out; } -/* ret = glusterd_ha_update_volume (volinfo); + ret = glusterd_store_update_volume (volinfo); if (ret) goto out; -*/ + out: @@ -938,11 +938,11 @@ glusterd_op_remove_brick (gd1_mgmt_stage_op_req *req) goto out; } -/* ret = glusterd_ha_update_volume (volinfo); + ret = glusterd_store_update_volume (volinfo); if (ret) goto out; -*/ + out: @@ -973,7 +973,7 @@ glusterd_op_delete_volume (gd1_mgmt_stage_op_req *req) if (ret) goto out; - ret = glusterd_ha_delete_volume (volinfo); + ret = glusterd_store_delete_volume (volinfo); if (ret) goto out; diff --git a/xlators/mgmt/glusterd/src/glusterd-store.c b/xlators/mgmt/glusterd/src/glusterd-store.c new file mode 100644 index 000000000..8d66fe6fe --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-store.c @@ -0,0 +1,961 @@ +/* + Copyright (c) 2007-2010 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif +#include + + +#include "globals.h" +#include "glusterfs.h" +#include "compat.h" +#include "dict.h" +#include "protocol-common.h" +#include "xlator.h" +#include "logging.h" +#include "timer.h" +#include "defaults.h" +#include "compat.h" +#include "compat-errno.h" +#include "statedump.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 "glusterd1.h" +#include "cli1.h" +#include "rpc-clnt.h" + +#include +#include +#include + +static int32_t +glusterd_store_create_volume_dir (char *volname) +{ + int32_t ret = -1; + char path[PATH_MAX] = {0,}; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (volname); + priv = THIS->private; + + GF_ASSERT (priv); + + snprintf (path, 1024, "%s/vols/%s", priv->workdir, + volname); + + ret = mkdir (path, 0x777); + + if (-1 == ret) { + gf_log ("", GF_LOG_ERROR, "mkdir() failed on path %s," + "errno: %d", path, errno); + goto out; + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +int32_t +glusterd_store_create_brick (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo) +{ + int32_t ret = -1; + glusterd_conf_t *priv = NULL; + char path[PATH_MAX] = {0,}; + char brickpath[PATH_MAX] = {0,}; + struct stat stbuf = {0,}; + int fd = -1; + char buf[4096] = {0,}; + char *tmppath = NULL; + char *ptr = NULL; + + GF_ASSERT (volinfo); + GF_ASSERT (brickinfo); + + priv = THIS->private; + + GF_ASSERT (priv); + + GLUSTERD_GET_BRICK_DIR (path, volinfo, priv); + + ret = stat (path, &stbuf); + + if (ret == -1 && ENOENT == errno) { + ret = mkdir (path, 0x777); + if (ret) + goto out; + } + + tmppath = gf_strdup (brickinfo->path); + + ptr = strchr (tmppath, '/'); + + while (ptr) { + *ptr = '-'; + ptr = strchr (tmppath, '/'); + } + + snprintf (brickpath, sizeof (brickpath), "%s/%s:%s", + path, brickinfo->hostname, tmppath); + + GF_FREE (tmppath); + + fd = open (brickpath, O_RDWR | O_CREAT | O_APPEND, 0666); + + if (fd < 0) { + gf_log ("", GF_LOG_ERROR, "Open failed on %s", + brickpath); + ret = -1; + goto out; + } + + + snprintf (buf, sizeof(buf), "hostname=%s\n", brickinfo->hostname); + write (fd, buf, strlen(buf)); + snprintf (buf, sizeof(buf), "path=%s\n", brickinfo->path); + write (fd, buf, strlen(buf)); + + ret = 0; + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +int32_t +glusterd_store_delete_brick (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo) +{ + int32_t ret = -1; + glusterd_conf_t *priv = NULL; + char path[PATH_MAX] = {0,}; + char brickpath[PATH_MAX] = {0,}; + char *ptr = NULL; + char *tmppath = NULL; + + GF_ASSERT (volinfo); + GF_ASSERT (brickinfo); + + priv = THIS->private; + + GF_ASSERT (priv); + + GLUSTERD_GET_BRICK_DIR (path, volinfo, priv); + + tmppath = gf_strdup (brickinfo->path); + + ptr = strchr (tmppath, '/'); + + while (ptr) { + *ptr = '-'; + ptr = strchr (tmppath, '/'); + } + + snprintf (brickpath, sizeof (brickpath), "%s/%s:%s", + path, brickinfo->hostname, tmppath); + + GF_FREE (tmppath); + + ret = unlink (brickpath); + + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "Unlink failed on %s", + brickpath); + ret = -1; + goto out; + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +int32_t +glusterd_store_remove_bricks (glusterd_volinfo_t *volinfo) +{ + int32_t ret = -1; + glusterd_brickinfo_t *tmp = NULL; + glusterd_conf_t *priv = NULL; + char brickdir [PATH_MAX] = {0,}; + DIR *dir = NULL; + struct dirent *entry = NULL; + char path[PATH_MAX] = {0,}; + + GF_ASSERT (volinfo); + + list_for_each_entry (tmp, &volinfo->bricks, brick_list) { + ret = glusterd_store_delete_brick (volinfo, tmp); + if (ret) + goto out; + } + + priv = THIS->private; + GF_ASSERT (priv); + + GLUSTERD_GET_BRICK_DIR (brickdir, volinfo, priv); + + dir = opendir (brickdir); + + glusterd_for_each_entry (entry, dir); + + while (entry) { + snprintf (path, sizeof (path), "%s/%s", + brickdir, entry->d_name); + ret = unlink (path); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to unlink %s", + path); + } + glusterd_for_each_entry (entry, dir); + } + + closedir (dir); + + ret = rmdir (brickdir); + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +int32_t +glusterd_store_create_volume (glusterd_volinfo_t *volinfo) +{ + int32_t ret = -1; + char filepath[PATH_MAX] = {0,}; + char buf[4096] = {0,}; + glusterd_conf_t *priv = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + + GF_ASSERT (volinfo); + priv = THIS->private; + + GF_ASSERT (priv); + + ret = glusterd_store_create_volume_dir (volinfo->volname); + + if (ret) + goto out; + + snprintf (filepath, 1024, "%s/%s/%s/%s", priv->workdir, + GLUSTERD_VOLUME_DIR_PREFIX, volinfo->volname, + GLUSTERD_VOLUME_INFO_FILE); + + ret = glusterd_store_handle_new (filepath, &volinfo->shandle); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to create store" + " handle for path: %s", filepath); + goto out; + } + + snprintf (buf, sizeof (buf), "%d", volinfo->type); + ret = glusterd_store_save_value (volinfo->shandle, + GLUSTERD_STORE_KEY_VOL_TYPE, buf); + if (ret) + goto out; + + snprintf (buf, sizeof (buf), "%d", volinfo->brick_count); + ret = glusterd_store_save_value (volinfo->shandle, + GLUSTERD_STORE_KEY_VOL_COUNT, buf); + if (ret) + goto out; + + snprintf (buf, sizeof (buf), "%d", volinfo->status); + ret = glusterd_store_save_value (volinfo->shandle, + GLUSTERD_STORE_KEY_VOL_STATUS, buf); + if (ret) + goto out; + + snprintf (buf, sizeof (buf), "%d", volinfo->status); + ret = glusterd_store_save_value (volinfo->shandle, + GLUSTERD_STORE_KEY_VOL_PORT, buf); + if (ret) + goto out; + + snprintf (buf, sizeof (buf), "%d", volinfo->sub_count); + ret = glusterd_store_save_value (volinfo->shandle, + GLUSTERD_STORE_KEY_VOL_SUB_COUNT, buf); + if (ret) + goto out; + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + ret = glusterd_store_create_brick (volinfo, brickinfo); + if (ret) + goto out; + } + + ret = 0; + +out: + if (ret) { + glusterd_store_delete_volume (volinfo); + } + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + + +int32_t +glusterd_store_delete_volume (glusterd_volinfo_t *volinfo) +{ + char pathname[PATH_MAX] = {0,}; + int32_t ret = -1; + glusterd_conf_t *priv = NULL; + DIR *dir = NULL; + struct dirent *entry = NULL; + char path[PATH_MAX] = {0,}; + + GF_ASSERT (volinfo); + priv = THIS->private; + + GF_ASSERT (priv); + snprintf (pathname, 1024, "%s/vols/%s", priv->workdir, + volinfo->volname); + + dir = opendir (pathname); + if (!dir) + goto out; + ret = glusterd_store_remove_bricks (volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Remove bricks failed"); + } + + glusterd_for_each_entry (entry, dir); + while (entry) { + + snprintf (path, PATH_MAX, "%s/%s", pathname, entry->d_name); + if (DT_DIR == entry->d_type) + ret = rmdir (path); + else + ret = unlink (path); + + gf_log ("", GF_LOG_NORMAL, "%s %s", + ret?"Failed to remove":"Removed", + entry->d_name); + if (ret) + gf_log ("", GF_LOG_NORMAL, "errno:%d", errno); + memset (path, 0, sizeof(path)); + glusterd_for_each_entry (entry, dir); + } + + ret = closedir (dir); + if (ret) { + gf_log ("", GF_LOG_NORMAL, "Failed to close dir, errno:%d", + errno); + } + + ret = rmdir (pathname); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Failed to rmdir: %s, errno: %d", + pathname, errno); + } + + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + + + +int32_t +glusterd_store_retrieve_value (glusterd_store_handle_t *handle, + char *key, char **value) +{ + int32_t ret = -1; + char scan_str[4096] = {0,}; + char *iter_key = NULL; + char *iter_val = NULL; + char *str = NULL; + + GF_ASSERT (handle); + GF_ASSERT (handle->fd > 0); + + if (!handle->read) + handle->read = fdopen (handle->fd, "r"); + + if (!handle->read) { + gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %d", + handle->path, errno); + goto out; + } + + ret = fscanf (handle->read, "%s", scan_str); + + while (ret != EOF) { + str = gf_strdup (scan_str); + if (!str) + goto out; + iter_key = strtok (str, "="); + gf_log ("", GF_LOG_DEBUG, "key %s read", iter_key); + + if (!strcmp (key, iter_key)) { + gf_log ("", GF_LOG_DEBUG, "key %s found", key); + iter_val = strtok (NULL, "="); + ret = 0; + *value = gf_strdup (iter_val); + goto out; + } + + ret = fscanf (handle->read, "%s", scan_str); + } + + if (EOF == ret) + ret = -1; +out: + + return ret; +} + +int32_t +glusterd_store_save_value (glusterd_store_handle_t *handle, + char *key, char *value) +{ + int32_t ret = -1; + char buf[4096] = {0,}; + + GF_ASSERT (handle); + GF_ASSERT (handle->fd > 0); + GF_ASSERT (key); + GF_ASSERT (value); + + if (!handle->write) + handle->write = fdopen (handle->fd, "a+"); + + if (!handle->write) { + gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %d", + handle->path, errno); + goto out; + } + + snprintf (buf, sizeof (buf), "%s=%s\n", key, value); + ret = write (handle->fd, buf, strlen (buf)); + //ret = fprintf (handle->write, "%s=%s\n", key, value); + + if (ret < 0) { + gf_log ("", GF_LOG_CRITICAL, "Unable to store key: %s," + "value: %s, error: %s", key, value, + strerror (errno)); + ret = -1; + goto out; + } + + ret = 0; + +out: + + gf_log ("", GF_LOG_DEBUG, "returning: %d", ret); + return ret; +} + +int32_t +glusterd_store_handle_new (char *path, glusterd_store_handle_t **handle) +{ + int32_t ret = -1; + glusterd_store_handle_t *shandle = NULL; + + shandle = GF_CALLOC (1, sizeof (*shandle), gf_gld_mt_store_handle_t); + if (!shandle) + goto out; + + shandle->path = gf_strdup (path); + + if (!shandle->path) + goto out; + + shandle->fd = open (path, O_RDWR | O_CREAT | O_APPEND, 0644); + if (!shandle->fd) + goto out; + + *handle = shandle; + + ret = 0; + +out: + if (ret == -1) { + if (shandle) { + if (shandle->path) + GF_FREE (shandle->path); + GF_FREE (shandle); + } + } + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int32_t +glusterd_store_uuid () +{ + char str[GLUSTERD_UUID_LEN] = {0,}; + glusterd_conf_t *priv = NULL; + char path[PATH_MAX] = {0,}; + int32_t ret = -1; + glusterd_store_handle_t *handle = NULL; + + priv = THIS->private; + + uuid_unparse (priv->uuid, str); + + snprintf (path, PATH_MAX, "%s/%s", priv->workdir, + GLUSTERD_INFO_FILE); + + if (!priv->handle) { + ret = glusterd_store_handle_new (path, &handle); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get store" + " handle!"); + goto out; + } + + priv->handle = handle; + } + + ret = glusterd_store_save_value (priv->handle, GLUSTERD_STORE_UUID_KEY, + str); + + if (ret) { + gf_log ("", GF_LOG_CRITICAL, "Storing uuid failed" + "ret = %d", ret); + goto out; + } + + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + + +int32_t +glusterd_retrieve_uuid () +{ + char *uuid_str = NULL; + int32_t ret = -1; + glusterd_store_handle_t *handle = NULL; + glusterd_conf_t *priv = NULL; + char path[PATH_MAX] = {0,}; + + priv = THIS->private; + + + if (!priv->handle) { + snprintf (path, PATH_MAX, "%s/%s", priv->workdir, + GLUSTERD_INFO_FILE); + ret = glusterd_store_handle_new (path, &handle); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get store " + "handle!"); + goto out; + } + + priv->handle = handle; + } + + ret = glusterd_store_retrieve_value (priv->handle, + GLUSTERD_STORE_UUID_KEY, + &uuid_str); + + if (ret) { + gf_log ("", GF_LOG_CRITICAL, "Retrieving uuid failed" + " ret = %d", ret); + goto out; + } + + uuid_parse (uuid_str, priv->uuid); + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int32_t +glusterd_store_iter_new (glusterd_store_handle_t *shandle, + glusterd_store_iter_t **iter) +{ + int32_t ret = -1; + glusterd_store_iter_t *tmp_iter = NULL; + int fd = -1; + + GF_ASSERT (shandle); + GF_ASSERT (shandle->fd > 0); + GF_ASSERT (iter); + + tmp_iter = GF_CALLOC (1, sizeof (*tmp_iter), + gf_gld_mt_store_iter_t); + + if (!tmp_iter) { + gf_log ("", GF_LOG_ERROR, "Out of Memory"); + goto out; + } + + fd = open (shandle->path, O_RDWR); + + if (fd < 0) { + gf_log ("", GF_LOG_ERROR, "Unable to open %s", + shandle->path); + goto out; + } + + tmp_iter->fd = fd; + + tmp_iter->file = fdopen (shandle->fd, "r"); + + if (!tmp_iter->file) { + gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %d", + shandle->path, errno); + goto out; + } + + *iter = tmp_iter; + ret = 0; + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +int32_t +glusterd_store_iter_get_next (glusterd_store_iter_t *iter, + char **key, char **value) +{ + int32_t ret = -1; + char scan_str[4096] = {0,}; + char *str = NULL; + char *iter_key = NULL; + char *iter_val = NULL; + + GF_ASSERT (iter); + GF_ASSERT (iter->file); + + ret = fscanf (iter->file, "%s", scan_str); + + if (ret <= 0) { + ret = -1; + goto out; + } + + str = gf_strdup (scan_str); + if (!str) + goto out; + + iter_key = strtok (str, "="); + gf_log ("", GF_LOG_DEBUG, "key %s read", iter_key); + + + iter_val = strtok (NULL, "="); + gf_log ("", GF_LOG_DEBUG, "value %s read", iter_val); + + *value = gf_strdup (iter_val); + *key = gf_strdup (iter_key); + + ret = 0; + +out: + if (str) + GF_FREE (str); + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +int32_t +glusterd_store_iter_destroy (glusterd_store_iter_t *iter) +{ + int32_t ret = -1; + + GF_ASSERT (iter); + GF_ASSERT (iter->fd > 0); + + ret = fclose (iter->file); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to close fd: %d, ret: %d, " + "errno: %d" ,iter->fd, ret, errno); + } + + GF_FREE (iter); + + return ret; +} + +int32_t +glusterd_store_retrieve_bricks (glusterd_volinfo_t *volinfo) +{ + + int32_t ret = -1; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_store_iter_t *iter = NULL; + char *key = NULL; + char *value = NULL; + char brickdir[PATH_MAX] = {0,}; + char path[PATH_MAX] = {0,}; + glusterd_conf_t *priv = NULL; + DIR *dir = NULL; + struct dirent *entry = NULL; + + GF_ASSERT (volinfo); + GF_ASSERT (volinfo->volname); + + priv = THIS->private; + + GLUSTERD_GET_BRICK_DIR (brickdir, volinfo, priv); + + dir = opendir (brickdir); + + glusterd_for_each_entry (entry, dir); + + while (entry) { + ret = glusterd_brickinfo_new (&brickinfo); + + if (ret) + goto out; + + snprintf (path, sizeof (path), "%s/%s", brickdir, + entry->d_name); + + ret = glusterd_store_handle_new (path, &brickinfo->shandle); + + if (ret) + goto out; + + ret = glusterd_store_iter_new (brickinfo->shandle, &iter); + + if (ret) + goto out; + + ret = glusterd_store_iter_get_next (iter, &key, &value); + + while (!ret) { + if (!strncmp (key, GLUSTERD_STORE_KEY_BRICK_HOSTNAME, + strlen (GLUSTERD_STORE_KEY_BRICK_HOSTNAME))) { + strncpy (brickinfo->hostname, value, 1024); + } else if (!strncmp (key, GLUSTERD_STORE_KEY_BRICK_PATH, + strlen (GLUSTERD_STORE_KEY_BRICK_PATH))) { + strncpy (brickinfo->path, value, + sizeof (brickinfo->path)); + }else { + gf_log ("", GF_LOG_ERROR, "Unknown key: %s", + key); + } + + GF_FREE (key); + GF_FREE (value); + + ret = glusterd_store_iter_get_next (iter, &key, &value); + } + + ret = glusterd_store_iter_destroy (iter); + + if (ret) + goto out; + + list_add_tail (&brickinfo->brick_list, &volinfo->bricks); + glusterd_for_each_entry (entry, dir); + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + + +int32_t +glusterd_store_retrieve_volume (char *volname) +{ + int32_t ret = -1; + glusterd_volinfo_t *volinfo = NULL; + glusterd_store_iter_t *iter = NULL; + char *key = NULL; + char *value = NULL; + char volpath[PATH_MAX] = {0,}; + glusterd_conf_t *priv = NULL; + char path[PATH_MAX] = {0,}; + + ret = glusterd_volinfo_new (&volinfo); + + if (ret) + goto out; + + strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME); + + priv = THIS->private; + + GLUSTERD_GET_VOLUME_DIR(volpath, volinfo, priv); + snprintf (path, sizeof (path), "%s/%s", volpath, + GLUSTERD_VOLUME_INFO_FILE); + + ret = glusterd_store_handle_new (path, &volinfo->shandle); + + if (ret) + goto out; + + ret = glusterd_store_iter_new (volinfo->shandle, &iter); + + if (ret) + goto out; + + ret = glusterd_store_iter_get_next (iter, &key, &value); + + while (!ret) { + if (!strncmp (key, GLUSTERD_STORE_KEY_VOL_TYPE, + strlen (GLUSTERD_STORE_KEY_VOL_TYPE))) { + volinfo->type = atoi (value); + } else if (!strncmp (key, GLUSTERD_STORE_KEY_VOL_COUNT, + strlen (GLUSTERD_STORE_KEY_VOL_COUNT))) { + volinfo->brick_count = atoi (value); + } else if (!strncmp (key, GLUSTERD_STORE_KEY_VOL_STATUS, + strlen (GLUSTERD_STORE_KEY_VOL_STATUS))) { + volinfo->status = atoi (value); + } else if (!strncmp (key, GLUSTERD_STORE_KEY_VOL_PORT, + strlen (GLUSTERD_STORE_KEY_VOL_PORT))) { + volinfo->port = atoi (value); + } else { + gf_log ("", GF_LOG_ERROR, "Unknown key: %s", + key); + } + + GF_FREE (key); + GF_FREE (value); + + ret = glusterd_store_iter_get_next (iter, &key, &value); + } + + ret = glusterd_store_iter_destroy (iter); + + if (ret) + goto out; + + ret = glusterd_store_retrieve_bricks (volinfo); + + list_add_tail (&volinfo->vol_list, &priv->volumes); + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + + +int32_t +glusterd_store_retrieve_volumes (xlator_t *this) +{ + int32_t ret = 0; + char path[PATH_MAX] = {0,}; + glusterd_conf_t *priv = NULL; + DIR *dir = NULL; + struct dirent *entry = NULL; + + GF_ASSERT (this); + priv = this->private; + + GF_ASSERT (priv); + + snprintf (path, PATH_MAX, "%s/%s", priv->workdir, + GLUSTERD_VOLUME_DIR_PREFIX); + + dir = opendir (path); + + if (!dir) { + gf_log ("", GF_LOG_ERROR, "Unable to open dir %s", path); + ret = -1; + goto out; + } + + glusterd_for_each_entry (entry, dir); + + while (entry) { + ret = glusterd_store_retrieve_volume (entry->d_name); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to restore " + "volume: %s", entry->d_name); + goto out; + } + glusterd_for_each_entry (entry, dir); + } + +out: + if (dir) + closedir (dir); + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + +int32_t +glusterd_store_update_volume (glusterd_volinfo_t *volinfo) +{ + int32_t ret = -1; + + ret = glusterd_store_delete_volume (volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to delete " + "volume: %s", volinfo->volname); + goto out; + } + + ret = glusterd_store_create_volume (volinfo); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to create " + "volume: %s", volinfo->volname); + goto out; + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + return ret; +} + + +int32_t +glusterd_restore () +{ + int ret = -1; + xlator_t *this = NULL; + + this = THIS; + + ret = glusterd_store_retrieve_volumes (this); + + if (ret) + goto out; + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-store.h b/xlators/mgmt/glusterd/src/glusterd-store.h new file mode 100644 index 000000000..c3be21502 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-store.h @@ -0,0 +1,90 @@ +/* + Copyright (c) 2006-2010 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +#ifndef _GLUSTERD_HA_H_ +#define _GLUSTERD_HA_H_ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include +#include "uuid.h" + +#include "glusterfs.h" +#include "xlator.h" +#include "logging.h" +#include "call-stub.h" +#include "fd.h" +#include "byte-order.h" +#include "glusterd.h" +#include "rpcsvc.h" + + +#define GLUSTERD_STORE_UUID_KEY "UUID" + +#define GLUSTERD_STORE_KEY_VOL_TYPE "type" +#define GLUSTERD_STORE_KEY_VOL_COUNT "count" +#define GLUSTERD_STORE_KEY_VOL_STATUS "status" +#define GLUSTERD_STORE_KEY_VOL_PORT "port" +#define GLUSTERD_STORE_KEY_VOL_SUB_COUNT "sub_count" +#define GLUSTERD_STORE_KEY_VOL_BRICK "brick" + +#define GLUSTERD_STORE_KEY_BRICK_HOSTNAME "hostname" +#define GLUSTERD_STORE_KEY_BRICK_PATH "path" + +#define glusterd_for_each_entry(entry, dir) \ + do {\ + entry = readdir (dir);\ + while (entry && (!strcmp (entry->d_name, ".") ||\ + !strcmp (entry->d_name, ".."))) {\ + entry = readdir (dir);\ + }\ + } while (0); \ + +int32_t +glusterd_store_create_volume (glusterd_volinfo_t *volinfo); + +int32_t +glusterd_store_delete_volume (glusterd_volinfo_t *volinfo); + +int32_t +glusterd_store_uuid (); + +int32_t +glusterd_store_handle_new (char *path, glusterd_store_handle_t **handle); + +int32_t +glusterd_store_save_value (glusterd_store_handle_t *handle, + char *key, char *value); + +int32_t +glusterd_store_retrieve_value (glusterd_store_handle_t *handle, + char *key, char **value); + +int32_t +glusterd_store_update_volume (glusterd_volinfo_t *volinfo); + +int32_t +glusterd_retrieve_uuid (); + +int32_t +glusterd_restore (); +#endif diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 338ebc277..6b32bd3a0 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -878,6 +878,7 @@ glusterd_is_cli_op_req (int32_t op) case GD_MGMT_CLI_DELETE_VOLUME: case GD_MGMT_CLI_DEFRAG_VOLUME: case GD_MGMT_CLI_ADD_BRICK: + case GD_MGMT_CLI_REMOVE_BRICK: return _gf_true; break; } diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index cfd07433b..5b75c93fa 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -42,6 +42,7 @@ #include "statedump.h" #include "glusterd-sm.h" #include "glusterd-op-sm.h" +#include "glusterd-store.h" static uuid_t glusterd_uuid; @@ -50,17 +51,6 @@ extern struct rpcsvc_program gluster_handshake_prog; extern struct rpc_clnt_program glusterd3_1_mgmt_prog; extern glusterd_op_info_t opinfo; -static int -glusterd_retrieve_uuid () -{ - return -1; -} - -static int -glusterd_store_uuid () -{ - return 0; -} static int glusterd_opinfo_init () @@ -75,22 +65,28 @@ glusterd_opinfo_init () static int glusterd_uuid_init () { - int ret = -1; - char str[50]; + int ret = -1; + char str[50] = {0,}; + glusterd_conf_t *priv = NULL; + priv = THIS->private; ret = glusterd_retrieve_uuid (); if (!ret) { + uuid_unparse (priv->uuid, str); + uuid_copy (glusterd_uuid, priv->uuid); gf_log ("glusterd", GF_LOG_NORMAL, - "retrieved UUID: %s", glusterd_uuid); + "retrieved UUID: %s", str); return 0; } + uuid_generate (glusterd_uuid); uuid_unparse (glusterd_uuid, str); gf_log ("glusterd", GF_LOG_NORMAL, "generated UUID: %s",str); + uuid_copy (priv->uuid, glusterd_uuid); ret = glusterd_store_uuid (); @@ -282,6 +278,10 @@ init (xlator_t *this) ret = glusterd_uuid_init (); + if (ret < 0) + goto out; + + ret = glusterd_restore (); if (ret < 0) goto out; @@ -289,7 +289,6 @@ init (xlator_t *this) glusterd_op_sm_init (); glusterd_opinfo_init (); - memcpy(conf->uuid, glusterd_uuid, sizeof (uuid_t)); ret = 0; out: diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 6446f2fc1..9f0986bb6 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -40,7 +40,23 @@ #include "glusterd-sm.h" #include "glusterd1-xdr.h" +#define GLUSTERD_MAX_VOLUME_NAME 1000 +struct glusterd_store_handle_ { + char *path; + int fd; + FILE *read; + FILE *write; +}; + +typedef struct glusterd_store_handle_ glusterd_store_handle_t; + +struct glusterd_store_iter_ { + int fd; + FILE *file; +}; + +typedef struct glusterd_store_iter_ glusterd_store_iter_t; typedef struct { struct _volfile_ctx *volfile; @@ -55,6 +71,7 @@ typedef struct { rpc_clnt_prog_t *mgmt; struct list_head volumes; struct list_head hostnames; + glusterd_store_handle_t *handle; } glusterd_conf_t; struct glusterd_brickinfo { @@ -62,19 +79,21 @@ struct glusterd_brickinfo { char path[PATH_MAX]; struct list_head brick_list; uuid_t uuid; + glusterd_store_handle_t *shandle; }; typedef struct glusterd_brickinfo glusterd_brickinfo_t; struct glusterd_volinfo_ { - char volname[1024]; - int type; - int brick_count; + char volname[GLUSTERD_MAX_VOLUME_NAME]; + int type; + int brick_count; struct list_head vol_list; struct list_head bricks; glusterd_volume_status status; - int sub_count; - int port; + int sub_count; + int port; + glusterd_store_handle_t *shandle; }; typedef struct glusterd_volinfo_ glusterd_volinfo_t; @@ -85,6 +104,12 @@ enum glusterd_op_ret { #define GLUSTERD_DEFAULT_WORKDIR "/etc/glusterd" #define GLUSTERD_DEFAULT_PORT 6969 +#define GLUSTERD_INFO_FILE "glusterd.info" +#define GLUSTERD_VOLUME_DIR_PREFIX "vols" +#define GLUSTERD_VOLUME_INFO_FILE "info" +#define GLUSTERD_BRICK_INFO_DIR "bricks" + +#define GLUSTERD_UUID_LEN 50 typedef ssize_t (*gd_serialize_t) (struct iovec outmsg, void *args); @@ -92,6 +117,11 @@ typedef ssize_t (*gd_serialize_t) (struct iovec outmsg, void *args); snprintf (path, PATH_MAX, "%s/vols/%s", priv->workdir,\ volinfo->volname); +#define GLUSTERD_GET_BRICK_DIR(path, volinfo, priv) \ + snprintf (path, PATH_MAX, "%s/%s/%s/%s", priv->workdir,\ + GLUSTERD_VOLUME_DIR_PREFIX, volinfo->volname, \ + GLUSTERD_BRICK_INFO_DIR); + #define GLUSTERD_GET_BRICK_PIDFILE(pidfile, volpath, hostname, count) \ snprintf (pidfile, PATH_MAX, "%s/run/%s-%d.pid", volpath, hostname, count); -- cgit