summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajesh Joseph <rjoseph@redhat.com>2013-12-13 11:53:21 +0530
committerRajesh Joseph <rjoseph@redhat.com>2014-01-15 13:53:32 +0530
commit727a63c3a5f9cab5af6089826d81df2035e1c0b6 (patch)
tree25c37ce129a65ed5af8ec9b52272bd98916fa206
parent33c45ff71cb43eec7cdcee054a6a55b7c3aaa8fb (diff)
Snapshot: Gluster snapshot restore feature
Implemented gluster snapshot restore feature. The restore is done by replacing the origin volume with the snap volume. TODO: After the restore the snapshot volume should be deleted. As of now the deletion work is pending. Change-Id: Ib137fb6bb84a74030607ffa47f89cd705dc7e1ff Signed-off-by: Rajesh Joseph <rjoseph@redhat.com>
-rw-r--r--cli/src/cli-rpc-ops.c4
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot.c171
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-store.c150
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-store.h95
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c31
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.c514
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.h5
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.h18
8 files changed, 739 insertions, 249 deletions
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index 6ee039f..90fb8e4 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -8117,9 +8117,9 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov,
goto out;
}
- ret = dict_get_str (dict, "cg-name", &cg_name);
+ ret = dict_get_str (dict, "cgname", &cg_name);
if (ret) {
- ret = dict_get_str (dict, "snap-name", &snap_name);
+ ret = dict_get_str (dict, "snapname", &snap_name);
if (ret) {
gf_log (frame->this->name, GF_LOG_ERROR,
"Failed to get CG name or snap name");
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
index acc8bef..8419cfb 100644
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
@@ -48,139 +48,6 @@ char *
generate_snapname (char *volname, char *name, gf_boolean_t volume_from_cg);
-/* This function will do the actual snapshot restore on the brick.
- *
- * @param brickinfo brickinfo structure
- * @param snapname name of the snap which will be restored
- *
- * @return Negative value on Failure and 0 in success
- */
-int
-glusterd_snapshot_restore_brick_snap (glusterd_brickinfo_t *brickinfo,
- char *snapname)
-{
- int ret = -1;
- char *device = NULL;
- xlator_t *this = NULL;
- runner_t runner = {0,};
- glusterd_conf_t *conf = NULL;
- char msg[PATH_MAX] = {0,};
-
- this = THIS;
- GF_ASSERT (this);
- conf = this->private;
-
- GF_ASSERT (conf);
- GF_ASSERT (brickinfo);
- GF_ASSERT (snapname);
-
- /* Using the brickinfo get the actual device name */
- device = glusterd_get_brick_mount_details (brickinfo);
-
- runinit (&runner);
- snprintf (msg, sizeof (msg), "Restoring snapshot of the brick %s:%s "
- "to %s snap", brickinfo->hostname, brickinfo->path, snapname);
-
- /* Command for restoring the snapshot */
- runner_add_args (&runner, "/sbin/lvconvert", "--merge", device, NULL);
- runner_log (&runner, "", GF_LOG_DEBUG, msg);
-
- synclock_unlock (&conf->big_lock);
- /* Run the actual command */
- ret = runner_run (&runner);
- synclock_lock (&conf->big_lock);
-
- if (ret) {
- gf_log (this->name, GF_LOG_ERROR, "snapshot restore of the "
- "brick (%s:%s) of device %s failed",
- brickinfo->hostname, brickinfo->path, device);
- goto out;
- }
-
-out:
- return ret;
-}
-
-/* This function will restore the snapshot for the entire volume.
- *
- * @param snap snap object which needs to be restored
- * @param op_errstr In case of any failure error message will be returned
- * in this variable
- * @return Negative value on Failure and 0 in success
- */
-int
-glusterd_snapshot_restore_snap (glusterd_snap_t *snap, char **op_errstr)
-{
- int ret = -1;
- xlator_t *this = NULL;
- glusterd_volinfo_t *volinfo = NULL;
- glusterd_brickinfo_t *brickinfo = NULL;
-
- this = THIS;
-
- GF_ASSERT (this);
- GF_ASSERT (snap);
- GF_ASSERT (snap->snap_volume);
- GF_ASSERT (op_errstr);
-
- /* For restore always take volinfo stored in snap. Do not use
- * volinfo of the original volume*/
- volinfo = snap->snap_volume;
-
- list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
- /* This code is executed on each node of the volume. We need
- * to run the restore only on those bricks which are present
- * in this node. Therefore check if node belongs to this node
- * or not.
- */
- if (uuid_compare (brickinfo->uuid, MY_UUID)) {
- continue; /* Bricks not present in this node */
- }
-
- /* This case should never occur as volume is already stopped.
- * Just to avoid a case where the brick is explicitly started
- * by the user we have this check here.
- */
- if (glusterd_is_brick_started (brickinfo)) {
- ret = gf_asprintf (op_errstr, "Brick (%s: %s) is "
- "running therefore snapshot cannot "
- "be restored", brickinfo->hostname,
- brickinfo->path);
- if (ret < 0) {
- goto out;
- }
-
- gf_log (this->name, GF_LOG_ERROR, "%s", *op_errstr);
- ret = -1;
- goto out;
- }
-
- /* Do the actual snapshot restore */
- ret = glusterd_snapshot_restore_brick_snap (brickinfo,
- snap->snap_name);
- if (ret) {
- ret = gf_asprintf (op_errstr, "Snapshot restore failed"
- " for %s:%s", brickinfo->hostname,
- brickinfo->path);
- if (ret < 0) {
- goto out;
- }
-
- gf_log (this->name, GF_LOG_ERROR, "%s", *op_errstr);
- ret = -1;
- goto out;
- }
-
- }
-
- /* TODO: Move this code to postvalidate */
- snap->snap_restored = _gf_true;
- /* TODO: persist the change in store */
-
-out:
- return ret;
-}
-
/* This function will restore a snapshot for the entire
* volume or the entire CG (Consistency Group)
*
@@ -260,7 +127,7 @@ glusterd_snapshot_restore (dict_t *dict, char **op_errstr)
}
/* Restore the snap for the entire volume */
- ret = glusterd_snapshot_restore_snap (snap, op_errstr);
+ ret = gd_restore_snap_volume (volinfo, snap->snap_volume);
if (ret) {
/* No need to update op_errstr because it is assumed
* that the called function will do that in case of
@@ -289,10 +156,12 @@ out:
* @param dict dictionary containing snapshot restore request
* @param op_errstr In case of any failure error message will be returned
* in this variable
+ * @param rsp_dict response dictionary
* @return Negative value on Failure and 0 in success
*/
int
-glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr)
+glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr,
+ dict_t *rsp_dict)
{
int ret = -1;
int64_t i = 0;
@@ -300,6 +169,7 @@ glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr)
gf_boolean_t snap_restored = _gf_false;
char *volname = NULL;
char *snapname = NULL;
+ char *cgname = NULL;
glusterd_volinfo_t *volinfo = NULL;
glusterd_snap_t *snap = NULL;
xlator_t *this = NULL;
@@ -310,6 +180,30 @@ glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr)
GF_ASSERT (this);
GF_ASSERT (dict);
GF_ASSERT (op_errstr);
+ GF_ASSERT (rsp_dict);
+
+ ret = dict_get_str (dict, "cgname", &cgname);
+ if (ret) {
+ ret = dict_get_str (dict, "snapname", &snapname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get "
+ "neither snapname nor cgname");
+ goto out;
+ }
+ ret = dict_set_str (rsp_dict, "snapname", snapname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to set "
+ "snap name");
+ goto out;
+ }
+ } else {
+ ret = dict_set_str (rsp_dict, "cgname", cgname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to set "
+ "CG name");
+ goto out;
+ }
+ }
ret = dict_get_int64 (dict, "volcount", &volcount);
@@ -3234,7 +3128,7 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *snapname, dict_t *dict,
}
ret = generate_snap_client_volfiles (volinfo, snap_volume,
- GF_CLIENT_TRUSTED);
+ GF_CLIENT_TRUSTED, _gf_false);
if (ret) {
gf_log (this->name, GF_LOG_ERROR, "generating the trusted "
"client volfiles for the snap %s (volume: %s) failed",
@@ -3243,7 +3137,7 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *snapname, dict_t *dict,
}
ret = generate_snap_client_volfiles (volinfo, snap_volume,
- GF_CLIENT_OTHER);
+ GF_CLIENT_OTHER, _gf_false);
if (ret) {
gf_log (this->name, GF_LOG_ERROR, "generating the client "
"volfiles for the snap %s (volume: %s) failed",
@@ -4657,7 +4551,8 @@ glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr,
break;
case GF_SNAP_OPTION_TYPE_RESTORE:
- ret = glusterd_snapshot_restore_prevalidate (dict, op_errstr);
+ ret = glusterd_snapshot_restore_prevalidate (dict, op_errstr,
+ rsp_dict);
if (ret) {
gf_log (this->name, GF_LOG_WARNING, "Snapshot restore "
"validation failed");
diff --git a/xlators/mgmt/glusterd/src/glusterd-store.c b/xlators/mgmt/glusterd/src/glusterd-store.c
index d6e071b..41633eb 100644
--- a/xlators/mgmt/glusterd/src/glusterd-store.c
+++ b/xlators/mgmt/glusterd/src/glusterd-store.c
@@ -607,14 +607,13 @@ int _storeopts (dict_t *this, char *key, data_t *value, void *data)
int32_t
glusterd_volume_exclude_options_write (int fd, glusterd_volinfo_t *volinfo)
{
- char *str = NULL;
+ char *str = NULL;
+ char buf[PATH_MAX] = {0,};
+ int32_t ret = -1;
GF_ASSERT (fd > 0);
GF_ASSERT (volinfo);
- char buf[PATH_MAX] = {0,};
- int32_t ret = -1;
-
snprintf (buf, sizeof (buf), "%d", volinfo->type);
ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_VOL_TYPE, buf);
if (ret)
@@ -703,6 +702,14 @@ glusterd_volume_exclude_options_write (int fd, glusterd_volinfo_t *volinfo)
goto out;
}
+ snprintf (buf, sizeof (buf), "%d", volinfo->is_volume_restored);
+ ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_VOL_IS_RESTORED, buf);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Unable to write is_volume_restored");
+ goto out;
+ }
+
snprintf (buf, sizeof (buf), "%"PRIu64, volinfo->snap_max_hard_limit);
ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT,
buf);
@@ -1519,11 +1526,17 @@ glusterd_store_perform_snap_store (glusterd_volinfo_t *volinfo)
list_for_each_entry_safe (entry, tmp, &volinfo->snaps,
snap_list) {
ret = glusterd_store_snap_list_write (fd, entry, count);
- if (ret)
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Failed to "
+ "write snap list to store");
goto unlock;
+ }
ret = glusterd_store_snap_volume (volinfo, entry);
- if (ret)
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Failed to "
+ "store snap volume");
goto unlock;
+ }
count++;
}
snprintf (buf, sizeof(buf), "%"PRIu64, count);
@@ -2680,53 +2693,66 @@ out:
return ret;
}
-int32_t
-glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap)
-{
- int32_t ret = -1;
- glusterd_volinfo_t *volinfo = NULL;
- gf_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,};
- int exists = 0;
- gf_store_op_errno_t op_errno = GD_STORE_SUCCESS;
- glusterd_volinfo_t *parent_vol = NULL;
-
- GF_ASSERT (volname);
- ret = glusterd_volinfo_new (&volinfo);
- if (ret)
- goto out;
+int
+glusterd_store_update_volinfo (glusterd_volinfo_t *volinfo,
+ glusterd_snap_t *snap)
+{
+ int ret = -1;
+ int exists = 0;
+ uint64_t count = 0;
+ char *key = NULL;
+ char *value = NULL;
+ char volpath[PATH_MAX] = {0,};
+ char path[PATH_MAX] = {0,};
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ gf_store_iter_t *iter = NULL;
+ gf_store_op_errno_t op_errno = GD_STORE_SUCCESS;
+ glusterd_volinfo_t *parent_vol = NULL;
- priv = THIS->private;
+ this = THIS;
+ GF_ASSERT (this);
+ conf = THIS->private;
+ GF_ASSERT (volinfo);
if (snap) {
- ret = glusterd_volinfo_find (volname, &parent_vol);
- if (ret)
+ ret = glusterd_volinfo_find (volinfo->parent_volname,
+ &parent_vol);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG, "Failed to get parent"
+ " volume for %s snap volume", volinfo->volname);
goto out;
- strncpy (volinfo->volname, snap->snap_name, GLUSTERD_MAX_VOLUME_NAME);
- GLUSTERD_GET_SNAP_DIR (volpath, parent_vol, snap->snap_name, priv);
+ }
+
+ GLUSTERD_GET_SNAP_DIR (volpath, parent_vol, snap->snap_name,
+ conf);
} else {
- strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME);
- GLUSTERD_GET_VOLUME_DIR(volpath, volinfo, priv);
+ GLUSTERD_GET_VOLUME_DIR(volpath, volinfo, conf);
}
+
snprintf (path, sizeof (path), "%s/%s", volpath,
GLUSTERD_VOLUME_INFO_FILE);
ret = gf_store_handle_retrieve (path, &volinfo->shandle);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "snap handle is NULL");
goto out;
+ }
ret = gf_store_iter_new (volinfo->shandle, &iter);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get new store "
+ "iter");
goto out;
+ }
ret = gf_store_iter_get_next (iter, &key, &value, &op_errno);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get next store "
+ "iter");
goto out;
+ }
while (!ret) {
gf_log ("", GF_LOG_DEBUG, "key = %s value = %s", key, value);
@@ -2801,6 +2827,9 @@ glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap)
} else if (!strncmp (key, GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT,
strlen (GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT))) {
volinfo->snap_max_hard_limit = (uint64_t) atoll (value);
+ } else if (!strncmp (key, GLUSTERD_STORE_KEY_VOL_IS_RESTORED,
+ strlen (GLUSTERD_STORE_KEY_VOL_IS_RESTORED))) {
+ volinfo->is_volume_restored = atoi (value);
} else if (!strncmp (key, GLUSTERD_STORE_KEY_PARENT_VOLNAME,
strlen (GLUSTERD_STORE_KEY_PARENT_VOLNAME))) {
strncpy (volinfo->parent_volname, value, sizeof(volinfo->parent_volname) - 1);
@@ -2891,10 +2920,57 @@ glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap)
goto out;
ret = gf_store_iter_destroy (iter);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to destroy store "
+ "iter");
+ goto out;
+ }
+ ret = 0;
+out:
+ return ret;
+}
+
+int32_t
+glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap)
+{
+ int32_t ret = -1;
+ char volpath[PATH_MAX] = {0,};
+ glusterd_volinfo_t *volinfo = NULL;
+ glusterd_conf_t *priv = NULL;
+ glusterd_volinfo_t *parent_vol = NULL;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
+ GF_ASSERT (volname);
+
+ ret = glusterd_volinfo_new (&volinfo);
if (ret)
goto out;
+ priv = THIS->private;
+
+ if (snap) {
+ ret = glusterd_volinfo_find (volname, &parent_vol);
+ if (ret)
+ goto out;
+ strncpy (volinfo->volname, snap->snap_name, GLUSTERD_MAX_VOLUME_NAME);
+ GLUSTERD_GET_SNAP_DIR (volpath, parent_vol, snap->snap_name, priv);
+ } else {
+ strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME);
+ GLUSTERD_GET_VOLUME_DIR(volpath, volinfo, priv);
+ }
+
+ ret = glusterd_store_update_volinfo (volinfo, snap);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to update volinfo "
+ "for %s volume", volname);
+ goto out;
+ }
+
if (snap)
ret = glusterd_store_retrieve_bricks (parent_vol, volinfo);
else
@@ -2916,12 +2992,12 @@ glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap)
// as of now snap volume are also added to the list of volume
volinfo->is_snap_volume = _gf_true;
snap->snap_volume = volinfo;
- list_add_tail (&volinfo->vol_list, &priv->volumes);
+ list_add_tail (&volinfo->vol_list, &priv->volumes);
}
out:
- gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret);
+ gf_log ("", GF_LOG_TRACE, "Returning with %d", ret);
return ret;
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-store.h b/xlators/mgmt/glusterd/src/glusterd-store.h
index 02e723f..d9192e3 100644
--- a/xlators/mgmt/glusterd/src/glusterd-store.h
+++ b/xlators/mgmt/glusterd/src/glusterd-store.h
@@ -35,55 +35,55 @@ typedef enum glusterd_store_ver_ac_{
} glusterd_volinfo_ver_ac_t;
-#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_STRIPE_CNT "stripe_count"
-#define GLUSTERD_STORE_KEY_VOL_REPLICA_CNT "replica_count"
-#define GLUSTERD_STORE_KEY_VOL_BRICK "brick"
-#define GLUSTERD_STORE_KEY_VOL_VERSION "version"
-#define GLUSTERD_STORE_KEY_VOL_TRANSPORT "transport-type"
-#define GLUSTERD_STORE_KEY_VOL_ID "volume-id"
-#define GLUSTERD_STORE_KEY_RB_STATUS "rb_status"
-#define GLUSTERD_STORE_KEY_RB_SRC_BRICK "rb_src"
-#define GLUSTERD_STORE_KEY_RB_DST_BRICK "rb_dst"
-#define GLUSTERD_STORE_KEY_RB_DST_PORT "rb_port"
-#define GLUSTERD_STORE_KEY_VOL_DEFRAG "rebalance_status"
-#define GLUSTERD_STORE_KEY_DEFRAG_OP "rebalance_op"
-#define GLUSTERD_STORE_KEY_USERNAME "username"
-#define GLUSTERD_STORE_KEY_PASSWORD "password"
-#define GLUSTERD_STORE_KEY_PARENT_VOLNAME "parent_volname"
-#define GLUSTERD_STORE_KEY_VOL_OP_VERSION "op-version"
+#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_STRIPE_CNT "stripe_count"
+#define GLUSTERD_STORE_KEY_VOL_REPLICA_CNT "replica_count"
+#define GLUSTERD_STORE_KEY_VOL_BRICK "brick"
+#define GLUSTERD_STORE_KEY_VOL_VERSION "version"
+#define GLUSTERD_STORE_KEY_VOL_TRANSPORT "transport-type"
+#define GLUSTERD_STORE_KEY_VOL_ID "volume-id"
+#define GLUSTERD_STORE_KEY_VOL_IS_RESTORED "is-volume-restored"
+#define GLUSTERD_STORE_KEY_RB_STATUS "rb_status"
+#define GLUSTERD_STORE_KEY_RB_SRC_BRICK "rb_src"
+#define GLUSTERD_STORE_KEY_RB_DST_BRICK "rb_dst"
+#define GLUSTERD_STORE_KEY_RB_DST_PORT "rb_port"
+#define GLUSTERD_STORE_KEY_VOL_DEFRAG "rebalance_status"
+#define GLUSTERD_STORE_KEY_DEFRAG_OP "rebalance_op"
+#define GLUSTERD_STORE_KEY_USERNAME "username"
+#define GLUSTERD_STORE_KEY_PASSWORD "password"
+#define GLUSTERD_STORE_KEY_PARENT_VOLNAME "parent_volname"
+#define GLUSTERD_STORE_KEY_VOL_OP_VERSION "op-version"
#define GLUSTERD_STORE_KEY_VOL_CLIENT_OP_VERSION "client-op-version"
-#define GLUSTERD_STORE_KEY_SNAP_NAME "name"
-#define GLUSTERD_STORE_KEY_SNAP_ID "snap-id"
-#define GLUSTERD_STORE_KEY_SNAP_CG_ID "cg-id"
-#define GLUSTERD_STORE_KEY_SNAP_CG_NAME "cg-name"
-#define GLUSTERD_STORE_KEY_SNAP_DESC "desc"
-#define GLUSTERD_STORE_KEY_SNAP_TIMESTAMP "time-stamp"
-#define GLUSTERD_STORE_KEY_SNAP_STATUS "status"
-#define GLUSTERD_STORE_KEY_SNAP_COUNT "count"
-#define GLUSTERD_STORE_KEY_CG_VOL_COUNT "count"
-#define GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT "snap-max-hard-limit"
-#define GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT "snap-max-soft-limit"
-
-#define GLUSTERD_STORE_KEY_BRICK_HOSTNAME "hostname"
-#define GLUSTERD_STORE_KEY_BRICK_PATH "path"
-#define GLUSTERD_STORE_KEY_BRICK_PORT "listen-port"
-#define GLUSTERD_STORE_KEY_BRICK_RDMA_PORT "rdma.listen-port"
+#define GLUSTERD_STORE_KEY_SNAP_NAME "name"
+#define GLUSTERD_STORE_KEY_SNAP_ID "snap-id"
+#define GLUSTERD_STORE_KEY_SNAP_CG_ID "cg-id"
+#define GLUSTERD_STORE_KEY_SNAP_DESC "desc"
+#define GLUSTERD_STORE_KEY_SNAP_TIMESTAMP "time-stamp"
+#define GLUSTERD_STORE_KEY_SNAP_STATUS "status"
+#define GLUSTERD_STORE_KEY_SNAP_COUNT "count"
+#define GLUSTERD_STORE_KEY_CG_VOL_COUNT "count"
+#define GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT "snap-max-hard-limit"
+#define GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT "snap-max-soft-limit"
+
+#define GLUSTERD_STORE_KEY_BRICK_HOSTNAME "hostname"
+#define GLUSTERD_STORE_KEY_BRICK_PATH "path"
+#define GLUSTERD_STORE_KEY_BRICK_PORT "listen-port"
+#define GLUSTERD_STORE_KEY_BRICK_RDMA_PORT "rdma.listen-port"
#define GLUSTERD_STORE_KEY_BRICK_DECOMMISSIONED "decommissioned"
-#define GLUSTERD_STORE_KEY_BRICK_VGNAME "vg"
+#define GLUSTERD_STORE_KEY_BRICK_VGNAME "vg"
-#define GLUSTERD_STORE_KEY_PEER_UUID "uuid"
-#define GLUSTERD_STORE_KEY_PEER_HOSTNAME "hostname"
-#define GLUSTERD_STORE_KEY_PEER_STATE "state"
+#define GLUSTERD_STORE_KEY_PEER_UUID "uuid"
+#define GLUSTERD_STORE_KEY_PEER_HOSTNAME "hostname"
+#define GLUSTERD_STORE_KEY_PEER_STATE "state"
-#define GLUSTERD_STORE_KEY_VOL_CAPS "caps"
+#define GLUSTERD_STORE_KEY_VOL_CAPS "caps"
#define glusterd_for_each_entry(entry, dir) \
do {\
@@ -140,6 +140,13 @@ glusterd_store_global_info (xlator_t *this);
int32_t
glusterd_store_retrieve_options (xlator_t *this);
+int
+glusterd_store_update_volinfo (glusterd_volinfo_t *volinfo,
+ glusterd_snap_t *snap);
+int32_t
+glusterd_store_retrieve_bricks (glusterd_volinfo_t *volinfo,
+ glusterd_volinfo_t *snap_volinfo);
+
int32_t
glusterd_store_options (xlator_t *this, dict_t *opts);
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index 6cba5b4..dedfd89 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -1542,7 +1542,7 @@ glusterd_snap_volume_start_glusterfs (glusterd_volinfo_t *volinfo,
glusterd_set_socket_filepath (sock_filepath, socketpath, sizeof (socketpath));
- GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo,
+ GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo->volname,
snap_volinfo->volname,
brickinfo, priv);
if (glusterd_is_service_running (pidfile, NULL))
@@ -1760,10 +1760,10 @@ glusterd_volume_stop_glusterfs (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo,
gf_boolean_t del_brick)
{
- xlator_t *this = NULL;
- glusterd_conf_t *priv = NULL;
- char pidfile[PATH_MAX] = {0,};
- int ret = 0;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ char pidfile[PATH_MAX] = {0,};
+ int ret = 0;
GF_ASSERT (volinfo);
GF_ASSERT (brickinfo);
@@ -1816,7 +1816,7 @@ glusterd_snap_volume_stop_glusterfs (glusterd_volinfo_t *volinfo,
if (GLUSTERD_STATUS_STARTED == volinfo->status) {
(void) glusterd_brick_disconnect (brickinfo);
- GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo,
+ GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo->volname,
snap_volinfo->volname,
brickinfo, priv);
ret = glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_false);
@@ -2159,6 +2159,15 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
if (ret)
goto out;
+ snprintf (key, sizeof (key), "volume%d.is_volume_restored", count);
+ ret = dict_set_int32 (dict, key, volinfo->is_volume_restored);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Failed to set "
+ "is_volume_restored option for %s volume",
+ volinfo->volname);
+ goto out;
+ }
+
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "volume%d.brick_count", count);
ret = dict_set_int32 (dict, key, volinfo->brick_count);
@@ -5191,7 +5200,6 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo,
char key[1024] = {0};
char base_key[1024] = {0};
char pidfile[PATH_MAX] = {0};
- char exp_path[PATH_MAX] = {0};
xlator_t *this = NULL;
glusterd_conf_t *priv = NULL;
@@ -5226,11 +5234,10 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo,
if (volinfo->is_snap_volume == _gf_true) {
/* Fetching the snap pidfile using parent volname */
- GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path);
- snprintf (pidfile, sizeof(pidfile) - 1,
- "%s/vols/%s/snaps/%s/run/%s-%s.pid", priv->workdir,
- volinfo->parent_volname, volinfo->volname,
- brickinfo->hostname, exp_path);
+ GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile,
+ volinfo->parent_volname,
+ volinfo->volname,
+ brickinfo, priv);
} else
GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo, brickinfo, priv);
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
index 1bc0db6..3b8e764 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c
@@ -28,6 +28,8 @@
#include "logging.h"
#include "dict.h"
#include "graph-utils.h"
+#include "glusterd-store.h"
+#include "glusterd-hooks.h"
#include "trie.h"
#include "glusterd-mem-types.h"
#include "cli1-xdr.h"
@@ -3175,7 +3177,8 @@ glusterd_generate_brick_volfile (glusterd_volinfo_t *volinfo,
static int
glusterd_generate_snap_brick_volfile (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo,
- glusterd_volinfo_t *snap_volinfo)
+ glusterd_volinfo_t *snap_volinfo,
+ gf_boolean_t vol_restore)
{
volgen_graph_t graph = {0,};
char filename[PATH_MAX] = {0,};
@@ -3189,7 +3192,16 @@ glusterd_generate_snap_brick_volfile (glusterd_volinfo_t *volinfo,
GF_ASSERT (brickinfo);
GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, brick);
- GLUSTERD_GET_SNAP_DIR (path, volinfo, snap_volinfo->volname, priv);
+ /* If the brick volfile is generated as part of a restore
+ * operation then we should be generating the brick volfile
+ * in the origin volume folder instead of snap volume folder.
+ */
+ if (vol_restore) {
+ GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv);
+ } else {
+ GLUSTERD_GET_SNAP_DIR (path, volinfo,
+ snap_volinfo->volname, priv);
+ }
snprintf (filename, PATH_MAX, "%s/%s.%s.%s.vol",
path, snap_volinfo->volname,
@@ -3285,8 +3297,10 @@ generate_snap_brick_volfiles (glusterd_volinfo_t *volinfo,
"Found a brick - %s:%s", brickinfo->hostname,
brickinfo->path);
- ret = glusterd_generate_snap_brick_volfile (volinfo, brickinfo,
- snap_volinfo);
+ ret = glusterd_generate_snap_brick_volfile (volinfo,
+ brickinfo,
+ snap_volinfo,
+ _gf_false);
if (ret)
goto out;
}
@@ -3382,7 +3396,8 @@ out:
int
generate_snap_client_volfiles (glusterd_volinfo_t *actual_volinfo,
glusterd_volinfo_t *snap_volinfo,
- glusterd_client_type_t client_type)
+ glusterd_client_type_t client_type,
+ gf_boolean_t vol_restore)
{
char filepath[PATH_MAX] = {0,};
int ret = -1;
@@ -3416,6 +3431,18 @@ generate_snap_client_volfiles (glusterd_volinfo_t *actual_volinfo,
dict = dict_new ();
if (!dict)
goto out;
+
+ /* If the brick volfile is generated as part of a restore
+ * operation then we should be generating the brick volfile
+ * in the origin volume folder instead of snap volume folder.
+ */
+ if (vol_restore) {
+ GLUSTERD_GET_VOLUME_DIR (path, actual_volinfo, conf);
+ } else {
+ GLUSTERD_GET_SNAP_DIR (path, actual_volinfo,
+ snap_volinfo->volname, conf);
+ }
+
for (i = 0; types[i]; i++) {
memset (filepath, 0, sizeof (filepath));
ret = dict_set_str (dict, "client-transport-type", types[i]);
@@ -3427,8 +3454,6 @@ generate_snap_client_volfiles (glusterd_volinfo_t *actual_volinfo,
if (ret)
goto out;
- GLUSTERD_GET_SNAP_DIR (path, actual_volinfo,
- snap_volinfo->volname,conf);
if (client_type == GF_CLIENT_TRUSTED) {
if ((actual_volinfo->transport_type ==
GF_TRANSPORT_BOTH_TCP_RDMA) &&
@@ -4115,3 +4140,478 @@ gd_is_boolean_option (char *key)
return _gf_false;
}
+
+/* This is a utility function which will create backup of
+ * origin volume file and then replace the origin volume
+ * file with a sym-link to snap volume file.
+ *
+ * @param orig_vol volinfo of origin volume
+ * @param orig_file file belonging to origin volume
+ * @param snap_file corresponding file in snap volume
+ *
+ * @return 0 on success and negative value on failure.
+ */
+static int
+gd_backup_and_restore_snap_files (glusterd_volinfo_t *orig_vol,
+ const char *orig_file,
+ const char *snap_file)
+{
+ int ret = -1;
+ char tmppath[PATH_MAX] = {0,};
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ GF_ASSERT (orig_vol);
+ GF_ASSERT (orig_file);
+ GF_ASSERT (snap_file);
+
+ /* If the volume is already a restored volume then we
+ * need not create a backup of files belonging to origin
+ * volume.
+ * We can simply delete the sym-link created by previous
+ * restore.
+ */
+ if (orig_vol->is_volume_restored) {
+ ret = remove (orig_file);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "remove %s file", orig_file);
+ goto out;
+ }
+ } else {
+ snprintf (tmppath, sizeof (tmppath), "%s.origin",
+ orig_file);
+ /* TODO: These temp files need to be deleted once the restored
+ * operation is successful
+ */
+
+ /* Create backup of origin volume file */
+ ret = rename (orig_file, tmppath);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to rename "
+ "file from %s to %s", orig_file, tmppath);
+ goto out;
+ }
+ }
+
+ /* Create sym-link to snap file */
+ ret = symlink (snap_file, orig_file);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to create sym-link "
+ "to %s file", snap_file);
+ goto out;
+ }
+
+ ret = 0;
+out:
+
+ return ret;
+}
+
+/* This is a utility function which will create a backup copy
+ * of origin volume.
+ *
+ * @param origvol volinfo of origin volume
+ * @param fileformat This string provides formatting information
+ * for the file to be backed up. The format
+ * string should be of <string>%s<string> format.
+ * Where <string> can be any string and this
+ * function will replace %s with origin volume
+ * name. e.g. "trusted-%s-fuse.vol".
+ * @param volpath volume path
+ *
+ * @return 0 on success and negative value on failure.
+ */
+static inline int
+gd_format_path_and_backup_snap_files (glusterd_volinfo_t *origvol,
+ const char *fileformat,
+ const char *volpath)
+{
+ int ret = -1;
+ char origfile[PATH_MAX] = {0,};
+ char formatstr[PATH_MAX] = {0,};
+ char tmppath[PATH_MAX] = {0,};
+
+ snprintf (formatstr, sizeof (formatstr), "%s/%s", volpath, fileformat);
+ snprintf (origfile, sizeof (origfile), formatstr, origvol->volname);
+
+ /* If the volume is already a restored volume then we
+ * need not create a backup of files belonging to origin
+ * volume.
+ * We can simply delete the sym-link created by previous
+ * restore.
+ */
+ if (origvol->is_volume_restored) {
+ ret = remove (origfile);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Failed to "
+ "remove %s file", origfile);
+ }
+ goto out;
+ }
+
+ snprintf (tmppath, sizeof (tmppath), "%s.origin", origfile);
+
+ /* Create a backup of this file */
+ ret = rename (origfile, tmppath);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "failed to restore %s file",
+ origfile);
+ }
+
+out:
+ return ret;
+}
+
+/* This is a utility function which will backup the origin volume
+ * brick folder and then create sym link to the snap_vol brick
+ * folder.
+ *
+ * @param orig_vol volinfo of origin volume
+ * @param snap_vol volinfo of snap volume
+ *
+ * @return 0 on success and negative value on failure.
+ */
+static int
+gd_restore_snap_brick_vol_files (glusterd_volinfo_t *orig_vol,
+ glusterd_volinfo_t *snap_vol)
+{
+ int ret = -1;
+ char path[PATH_MAX] = {0,};
+ char brick[PATH_MAX] = {0,};
+ char oldfilename[PATH_MAX] = {0,};
+ char newfilename[PATH_MAX] = {0,};
+ glusterd_brickinfo_t *brickinfo = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
+
+ GLUSTERD_GET_VOLUME_DIR (path, orig_vol, conf);
+
+ /* brick count of origin volume and snapshot volume might be
+ * different. Therefore we need to run two different loop to
+ * restore snap brick vol files.
+ */
+ list_for_each_entry (brickinfo, &orig_vol->bricks, brick_list) {
+ GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, brick);
+
+ snprintf (oldfilename, sizeof (oldfilename), "%s/%s.%s.%s.vol",
+ path, orig_vol->volname, brickinfo->hostname,
+ brick);
+
+ /* If the volume is already a restored volume then we
+ * need not create a backup of files belonging to origin
+ * volume.
+ * We can simply delete the sym-link created by previous
+ * restore.
+ */
+ if (orig_vol->is_volume_restored) {
+ ret = remove (oldfilename);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "remove %s file", oldfilename);
+ goto out;
+ }
+ continue;
+ }
+
+ snprintf (newfilename, sizeof (newfilename), "%s.origin",
+ oldfilename);
+
+ /* Create a backup of origin volume file */
+ ret = rename (oldfilename, newfilename);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to rename "
+ "file from %s to %s", oldfilename,
+ newfilename);
+ goto out;
+ }
+ }
+
+ /* Recreate brick files for origin volume */
+ list_for_each_entry (brickinfo, &snap_vol->bricks, brick_list) {
+ ret = glusterd_generate_snap_brick_volfile (orig_vol,
+ brickinfo,
+ snap_vol,
+ _gf_true);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to generate "
+ "brick volfile");
+ goto out;
+ }
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+
+/* This function will update the in-memory representation
+ * of the origin volume with the snap volume details.
+ *
+ * @param orig_vol origin volume volinfo
+ * @param snap_vol snap volume volinfo
+ *
+ * @return 0 on success and negative value on failure.
+ */
+static int
+gd_update_origin_volume (glusterd_volinfo_t *orig_vol,
+ glusterd_volinfo_t *snap_vol)
+{
+ int ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ glusterd_brickinfo_t *brickinfo = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
+ GF_ASSERT (orig_vol);
+ GF_ASSERT (snap_vol);
+
+ /* Update the in-memory volinfo from the store */
+ ret = glusterd_store_update_volinfo (orig_vol, NULL);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to update "
+ "volinfo for %s volume", orig_vol->volname);
+ goto out;
+ }
+
+ /* Reset the port number to 0 */
+ orig_vol->port = 0;
+ /* Reset the volume status to stopped */
+ glusterd_set_volume_status (orig_vol, GLUSTERD_STATUS_STOPPED);
+
+ /* Stop the snap volume */
+ list_for_each_entry (brickinfo, &snap_vol->bricks, brick_list) {
+ ret = glusterd_snap_brick_stop (orig_vol, snap_vol,
+ brickinfo, _gf_false);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to stop "
+ " %s brick", brickinfo->path);
+ goto out;
+ }
+ }
+
+ /* Set the volume status to stopped for the snap volume */
+ glusterd_set_volume_status (snap_vol, GLUSTERD_STATUS_STOPPED);
+
+ /* The in-memory brick list for the origin volume should be
+ * replaced with the brick list of snap volume. Therefore
+ * first delete all the bricks from the origin volume and
+ * then read the brick list from the store which is already
+ * updated
+ */
+
+ /* Delete previous brick infos */
+ ret = glusterd_volume_brickinfos_delete (orig_vol);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to delete "
+ "brickinfos for %s volume", orig_vol->volname);
+ goto out;
+ }
+
+ /* Retrieve brick list */
+ ret = glusterd_store_retrieve_bricks (orig_vol, NULL);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to retrieve "
+ "bricks info from store for %s volume",
+ orig_vol->volname);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+/* This function will restore origin volume to it it's snap.
+ * The restore operation will simply replace the Gluster origin
+ * volume with the snap volume.
+ *
+ * @param orig_vol volinfo of origin volume
+ * @param snap_vol volinfo of snapshot volume
+ *
+ * @return 0 on success and negative value on error
+ */
+int
+gd_restore_snap_volume (glusterd_volinfo_t *orig_vol,
+ glusterd_volinfo_t *snap_vol)
+{
+ int ret = -1;
+ unsigned int i = 0;
+ char snappath[PATH_MAX] = {0,};
+ char volpath[PATH_MAX] = {0,};
+ char oldfilename[PATH_MAX] = {0,};
+ char newfilename[PATH_MAX] = {0,};
+ char *types[] = {NULL, NULL, NULL};
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ gf_transport_type type = GF_TRANSPORT_TCP;
+ char tmpname[GLUSTERD_MAX_VOLUME_NAME] = {0,};
+
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
+
+ GF_VALIDATE_OR_GOTO (this->name, orig_vol, out);
+ GF_VALIDATE_OR_GOTO (this->name, snap_vol, out);
+
+ GLUSTERD_GET_SNAP_DIR (snappath, orig_vol, snap_vol->volname, conf);
+ GLUSTERD_GET_VOLUME_DIR (volpath, orig_vol, conf);
+
+ /* As mentioned earlier the snapshot restore is done by replacing
+ * the origin volume with the snapshot volume. To do so we have to
+ * replace all backend files belonging to origin volume with the
+ * snapshot volume. And once all the backend files are updated
+ * update the in-memory structure of the origin volume. Also delete
+ * the snapshot volume.
+ * TODO: deleting of snapshot volume can be controlled by user
+ * controllable option.
+ */
+
+ /* Backup and restore info file */
+ ret = gd_backup_and_restore_snap_files (orig_vol,
+ orig_vol->shandle->path,
+ snap_vol->shandle->path);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to restore info "
+ "file for %s volume", orig_vol->volname);
+ goto out;
+ }
+
+ GLUSTERD_GET_BRICK_DIR (oldfilename, orig_vol, conf);
+ GLUSTERD_GET_SNAP_BRICK_DIR (newfilename, orig_vol,
+ snap_vol->volname, conf);
+
+ /* Backup and restore bricks folder and it's contents */
+ ret = gd_backup_and_restore_snap_files (orig_vol, oldfilename,
+ newfilename);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to restore bricks "
+ "folder for %s volume", orig_vol->volname);
+ goto out;
+ }
+
+ enumerate_transport_reqs (orig_vol->transport_type, types);
+
+
+ for (i = 0; NULL != types[i]; i++) {
+ type = transport_str_to_type (types[i]);
+
+ if ((orig_vol->transport_type == GF_TRANSPORT_BOTH_TCP_RDMA) &&
+ type == GF_TRANSPORT_RDMA) {
+ /* Backup trusted rdma-fuse.vol file */
+ ret = gd_format_path_and_backup_snap_files (orig_vol,
+ "trusted-%s.rdma-fuse.vol",
+ volpath);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ " backup trusted*.rdma-fuse.vol file");
+ goto out;
+ }
+
+ /* Backup rdma-fuse.vol file */
+ ret = gd_format_path_and_backup_snap_files (orig_vol,
+ "%s.rdma-fuse.vol", volpath);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ " backup rdma-fuse.vol file");
+ goto out;
+ }
+ } else {
+ /* Backup trusted fuse.vol file */
+ ret = gd_format_path_and_backup_snap_files (orig_vol,
+ "trusted-%s-fuse.vol", volpath);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ " backup trusted*-fuse.vol file");
+ goto out;
+ }
+
+ /* Backup fuse.vol file */
+ ret = gd_format_path_and_backup_snap_files (orig_vol,
+ "%s-fuse.vol", volpath);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ " backup fuse.vol file");
+ goto out;
+ }
+ }
+ }
+
+ /* The restored client and brick vol files should have all
+ * the entries present in snap vol files but the volume name
+ * for all these entries should still be the origin volume
+ * name.
+ * As of now these volfile generation takes volume name
+ * directly from the volinfo. Therefore instead of changing
+ * all the generate function simply replace the snap volume
+ * name with the origin volume name. And once the vol files
+ * are generated restore the volume name.
+ */
+ strncpy (tmpname, snap_vol->volname, sizeof(tmpname));
+ strncpy (snap_vol->volname, orig_vol->volname,
+ sizeof(snap_vol->volname));
+
+ /* Generate trusted client vol file */
+ ret = generate_snap_client_volfiles (orig_vol, snap_vol,
+ GF_CLIENT_TRUSTED, _gf_true);
+ if (ret) {
+ /* Restore the snap volume name */
+ strncpy (snap_vol->volname, tmpname, sizeof(snap_vol->volname));
+ gf_log (this->name, GF_LOG_ERROR, "Failed to generated "
+ " trusted client vol file for %s volume",
+ orig_vol->volname);
+ goto out;
+ }
+
+ ret = generate_snap_client_volfiles (orig_vol, snap_vol,
+ GF_CLIENT_OTHER, _gf_true);
+ if (ret) {
+ /* Restore the snap volume name */
+ strncpy (snap_vol->volname, tmpname, sizeof(snap_vol->volname));
+ gf_log (this->name, GF_LOG_ERROR, "Failed to generated "
+ " client vol file for %s volume", orig_vol->volname);
+ goto out;
+ }
+
+ ret = gd_restore_snap_brick_vol_files (orig_vol, snap_vol);
+ if (ret) {
+ /* Restore the snap volume name */
+ strncpy (snap_vol->volname, tmpname, sizeof(snap_vol->volname));
+ gf_log (this->name, GF_LOG_ERROR, "Failed to generated "
+ " brick vol files for %s volume", orig_vol->volname);
+ goto out;
+ }
+
+ /* Restore the snap volume name */
+ strncpy (snap_vol->volname, tmpname, sizeof(snap_vol->volname));
+
+ /* Update the in-memory structure of origin volume */
+ ret = gd_update_origin_volume (orig_vol, snap_vol);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to update "
+ "origin volume %s", orig_vol->volname);
+ goto out;
+ }
+
+ /* Update status to restored */
+ orig_vol->is_volume_restored = _gf_true;
+
+ ret = glusterd_store_volinfo (orig_vol, GLUSTERD_VOLINFO_VER_AC_NONE);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to store volume "
+ "info of %s volume", orig_vol->volname);
+ goto out;
+ }
+out:
+ return ret;
+}
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.h b/xlators/mgmt/glusterd/src/glusterd-volgen.h
index 2b22f52..f5163b4 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.h
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.h
@@ -148,7 +148,8 @@ int generate_client_volfiles (glusterd_volinfo_t *volinfo,
int
generate_snap_client_volfiles (glusterd_volinfo_t *actual_volinfo,
glusterd_volinfo_t *snap_volinfo,
- glusterd_client_type_t client_type);
+ glusterd_client_type_t client_type,
+ gf_boolean_t vol_restore);
int glusterd_get_volopt_content (dict_t *dict, gf_boolean_t xml_out);
char*
glusterd_get_trans_type_rb (gf_transport_type ttype);
@@ -169,4 +170,6 @@ gd_is_xlator_option (char *key);
gf_boolean_t
gd_is_boolean_option (char *key);
+int gd_restore_snap_volume (glusterd_volinfo_t *orig_vol,
+ glusterd_volinfo_t *snap_vol);
#endif
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
index f14b673..40ae611 100644
--- a/xlators/mgmt/glusterd/src/glusterd.h
+++ b/xlators/mgmt/glusterd/src/glusterd.h
@@ -278,6 +278,7 @@ struct glusterd_volinfo_ {
gf_lock_t lock;
char volname[GLUSTERD_MAX_VOLUME_NAME];
gf_boolean_t is_snap_volume;
+ gf_boolean_t is_volume_restored;
char parent_volname[GLUSTERD_MAX_VOLUME_NAME];
/* In case of a snap volume
i.e (is_snap_volume == TRUE) this
@@ -485,14 +486,15 @@ typedef ssize_t (*gd_serialize_t) (struct iovec outmsg, void *args);
volpath, brickinfo->hostname, exp_path); \
} while (0)
-#define GLUSTERD_GET_SNAP_BRICK_PIDFILE(pidfile,volinfo,snapname,brickinfo, \
- priv) do { \
- char exp_path[PATH_MAX] = {0,}; \
- char volpath[PATH_MAX] = {0,}; \
- GLUSTERD_GET_SNAP_DIR(volpath, volinfo, snapname, priv); \
- GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path); \
- snprintf (pidfile, PATH_MAX, "%s/run/%s-%s.pid", \
- volpath, brickinfo->hostname, exp_path); \
+#define GLUSTERD_GET_SNAP_BRICK_PIDFILE(pidfile,vol_name,snap_name, \
+ brickinfo, priv) do { \
+ char exp_path[PATH_MAX] = {0,}; \
+ char volpath[PATH_MAX] = {0,}; \
+ snprintf (volpath, sizeof (volpath), "%s/vols/%s/snaps/%s", \
+ priv->workdir, vol_name, snap_name); \
+ GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path);\
+ snprintf (pidfile, sizeof (pidfile), "%s/run/%s-%s.pid", \
+ volpath, brickinfo->hostname, exp_path); \
} while (0)
#define GLUSTERD_GET_NFS_PIDFILE(pidfile,nfspath) { \