summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/cli-cmd-parser.c45
-rw-r--r--cli/src/cli-cmd-snapshot.c2
-rw-r--r--cli/src/cli-rpc-ops.c108
-rw-r--r--libglusterfs/src/store.c31
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-locks.c56
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c22
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mgmt.c35
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.c43
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot.c550
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-store.c202
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-store.h94
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c164
-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.h23
15 files changed, 1396 insertions, 498 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index 3b1a8a92d..1059ea90e 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -3197,8 +3197,11 @@ cli_snap_config_parse (const char **words, int wordcount, dict_t *options,
GF_ASSERT (options);
GF_ASSERT (state);
- if ((wordcount < 3) || (wordcount > 5))
+ if ((wordcount != 3) && (wordcount != 5)) {
+ gf_log ("", GF_LOG_ERROR,
+ "Invalid wordcount(%d)", wordcount);
goto out;
+ }
volname = (char *)words[2];
@@ -3220,11 +3223,19 @@ cli_snap_config_parse (const char **words, int wordcount, dict_t *options,
}
/* snapshot config <volname | all> [snap-max-hard-limit <count>
- * | snap-max-soft-limit <count>] */
+ * | snap-max-soft-limit <percent>] */
if (wordcount > 3) {
key = (char *) words[3];
value = (char *) words[4];
+ } else {
+ ret = dict_set_int32 (options, "config-command",
+ GF_SNAP_CONFIG_DISPLAY);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Unable to set config-command");
+ ret = -1;
+ goto out;
+ }
}
if (key) {
@@ -3258,15 +3269,7 @@ cli_snap_config_parse (const char **words, int wordcount, dict_t *options,
}
}
- if (!value) {
- ret = dict_set_int32 (options, "config-command",
- GF_SNAP_CONFIG_DISPLAY);
- if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to set config-command");
- ret = -1;
- goto out;
- }
- } else {
+ if (value) {
ret = dict_set_int32 (options, "config-command",
GF_SNAP_CONFIG_TYPE_SET);
if (ret) {
@@ -3282,17 +3285,18 @@ cli_snap_config_parse (const char **words, int wordcount, dict_t *options,
"Failed to set %s.", key);
goto out;
}
- }
- /* Ask question only for a set op */
- if (value && conf_vals && conf_vals->question) {
- answer = cli_cmd_get_confirmation (state,
- conf_vals->question);
- if (GF_ANSWER_NO == answer) {
- ret = -1;
- goto out;
+ /* Ask question only for a set op */
+ if (conf_vals->question) {
+ answer = cli_cmd_get_confirmation (state,
+ conf_vals->question);
+ if (GF_ANSWER_NO == answer) {
+ ret = -1;
+ goto out;
+ }
}
}
+
out:
return ret;
}
@@ -3613,7 +3617,8 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options,
}
case GF_SNAP_OPTION_TYPE_CONFIG:
{
- /* snapshot config <volname | all> [snap-max-hard-limit <count> | snap-max-soft-limit <count>] */
+ /* snapshot config <volname | all> [snap-max-hard-limit <count> |
+ * snap-max-soft-limit <percent>] */
ret = cli_snap_config_parse (words, wordcount, dict,
state);
if (ret) {
diff --git a/cli/src/cli-cmd-snapshot.c b/cli/src/cli-cmd-snapshot.c
index 556278931..6d31dc2d5 100644
--- a/cli/src/cli-cmd-snapshot.c
+++ b/cli/src/cli-cmd-snapshot.c
@@ -90,7 +90,7 @@ struct cli_cmd snapshot_cmds[] = {
cli_cmd_snapshot_cbk,
"Snapshot List."
},
- {"snapshot config < volname | all > [ snap-max-hard-limit <count> | snap-max-soft-limit <count> ]",
+ {"snapshot config < volname | all > [ snap-max-hard-limit <count> | snap-max-soft-limit <percent> ]",
cli_cmd_snapshot_cbk,
"Snapshot Config."
},
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index 926c01b70..90fb8e4b9 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -7898,11 +7898,15 @@ out:
int
cli_snapshot_config_display (dict_t *dict, gf_cli_rsp *rsp)
{
+ char buf[PATH_MAX] = "";
char *volname = NULL;
char *key = NULL;
int ret = -1;
int config_command = 0;
uint64_t value = 0;
+ uint64_t soft_limit = 0;
+ uint64_t i = 0;
+ uint64_t voldisplaycount = 0;
GF_ASSERT (dict);
GF_ASSERT (rsp);
@@ -7917,8 +7921,7 @@ cli_snapshot_config_display (dict_t *dict, gf_cli_rsp *rsp)
ret = dict_get_int32 (dict, "config-command", &config_command);
if (ret) {
- gf_log("", GF_LOG_DEBUG, "Could not fetch config type");
- ret = -1;
+ gf_log("", GF_LOG_ERROR, "Could not fetch config type");
goto out;
}
@@ -7926,7 +7929,6 @@ cli_snapshot_config_display (dict_t *dict, gf_cli_rsp *rsp)
if (ret) {
gf_log("", GF_LOG_ERROR, "Could not fetch "
"volname");
- ret = -1;
goto out;
}
@@ -7935,8 +7937,11 @@ cli_snapshot_config_display (dict_t *dict, gf_cli_rsp *rsp)
}
ret = dict_get_str (dict, "config-key", &key);
- if (ret)
- gf_log("", GF_LOG_ERROR, "No config-key set");
+ if (ret && config_command != GF_SNAP_CONFIG_DISPLAY) {
+ gf_log(THIS->name, GF_LOG_ERROR,
+ "Could not fetch config-key");
+ goto out;
+ }
switch (config_command) {
case GF_SNAP_CONFIG_TYPE_SET:
@@ -7945,49 +7950,74 @@ cli_snapshot_config_display (dict_t *dict, gf_cli_rsp *rsp)
break;
case GF_SNAP_CONFIG_DISPLAY :
- if (!key) {
- /* For all options */
- ret = dict_get_uint64 (dict, "snap-max-hard-limit",
- &value);
+ cli_out ("\nSnapshot System Configuration:");
+ ret = dict_get_uint64 (dict, "snap-max-hard-limit",
+ &value);
+ if (ret) {
+ gf_log("", GF_LOG_ERROR, "Could not fetch "
+ "snap_max_hard_limit for %s", volname);
+ ret = -1;
+ goto out;
+ }
+ cli_out ("snap-max-hard-limit : %"PRIu64, value);
+
+ ret = dict_get_uint64 (dict, "snap-max-soft-limit",
+ &soft_limit);
+ if (ret) {
+ gf_log("", GF_LOG_ERROR, "Could not fetch "
+ "snap-max-soft-limit for %s", volname);
+ ret = -1;
+ goto out;
+ }
+ cli_out ("snap-max-soft-limit : %"PRIu64"%%\n", soft_limit);
+
+ cli_out ("Snapshot Volume Configuration:");
+
+ ret = dict_get_uint64 (dict, "voldisplaycount",
+ &voldisplaycount);
+ if (ret) {
+ gf_log("", GF_LOG_ERROR, "Could not fetch voldisplaycount");
+ ret = -1;
+ goto out;
+ }
+
+ for (i = 0; i < voldisplaycount; i++) {
+ snprintf (buf, sizeof(buf), "volume%ld-volname", i);
+ ret = dict_get_str (dict, buf, &volname);
if (ret) {
- gf_log("", GF_LOG_DEBUG, "Could not fetch "
- "snap_max_hard_limit for %s", volname);
+ gf_log("", GF_LOG_ERROR, "Could not fetch "
+ " %s", buf);
ret = -1;
goto out;
}
- cli_out ("snapshot config: snap-max-hard-limit for "
- "%s set to %"PRIu64,
- volname, value);
+ cli_out ("\nVolume : %s", volname);
- ret = dict_get_uint64 (dict, "snap-max-soft-limit",
- &value);
+ snprintf (buf, sizeof(buf),
+ "volume%ld-snap-max-hard-limit", i);
+ ret = dict_get_uint64 (dict, buf, &value);
if (ret) {
- gf_log("", GF_LOG_DEBUG, "Could not fetch "
- "snap-max-soft-limit for %s", volname);
+ gf_log("", GF_LOG_ERROR, "Could not fetch "
+ " %s", buf);
ret = -1;
goto out;
}
- cli_out ("snapshot config: snap-max-soft-limit for "
- "%s set to %"PRIu64,
- volname, value);
- } else {
- if ((!strncmp (key, "snap-max-hard-limit", strlen(key))) ||
- (!strncmp (key, "snap-max-soft-limit", strlen(key)))) {
- ret = dict_get_uint64 (dict, key, &value);
- if (ret) {
- gf_log("", GF_LOG_DEBUG, "Could not fetch "
- "%s for %s", key, volname);
- ret = -1;
- goto out;
- }
- cli_out ("snapshot config: %s for "
- "%s set to %"PRIu64, key,
- volname, value);
+ cli_out ("snap-max-hard-limit : %"PRIu64, value);
+
+ snprintf (buf, sizeof(buf),
+ "volume%ld-snap-max-soft-limit-value", i);
+ ret = dict_get_uint64 (dict, buf, &value);
+ if (ret) {
+ gf_log("", GF_LOG_ERROR, "Could not fetch "
+ " %s", buf);
+ ret = -1;
+ goto out;
}
- }
- break;
+ cli_out ("snap-max-soft-limit : %"PRIu64" (%"PRIu64"%%)",
+ value, soft_limit);
+ }
+ break;
default :
- break;
+ break;
}
ret = 0;
@@ -8087,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/libglusterfs/src/store.c b/libglusterfs/src/store.c
index 55027fa9b..64497e9bb 100644
--- a/libglusterfs/src/store.c
+++ b/libglusterfs/src/store.c
@@ -168,10 +168,12 @@ int
gf_store_read_and_tokenize (FILE *file, char *str, char **iter_key,
char **iter_val, gf_store_op_errno_t *store_errno)
{
- int32_t ret = -1;
- char *savetok = NULL;
- char *key = NULL;
- char *value = NULL;
+ int32_t ret = -1;
+ char *savetok = NULL;
+ char *key = NULL;
+ char *value = NULL;
+ char *temp = NULL;
+ size_t str_len = 0;
GF_ASSERT (file);
GF_ASSERT (str);
@@ -179,8 +181,12 @@ gf_store_read_and_tokenize (FILE *file, char *str, char **iter_key,
GF_ASSERT (iter_val);
GF_ASSERT (store_errno);
- ret = fscanf (file, "%s", str);
- if (ret <= 0 || feof (file)) {
+ temp = fgets (str, PATH_MAX, file);
+ str_len = strlen(str);
+ str[str_len - 1] = '\0';
+ /* Truncate the "\n", as fgets stores "\n" in str */
+
+ if (temp == NULL || feof (file)) {
ret = -1;
*store_errno = GD_STORE_EOF;
goto out;
@@ -253,8 +259,13 @@ gf_store_retrieve_value (gf_store_handle_t *handle, char *key, char **value)
goto out;
}
- scan_str = GF_CALLOC (1, st.st_size,
+ /* "st.st_size + 1" is used as we are fetching each
+ * line of a file using fgets, fgets will append "\0"
+ * to the end of the string
+ */
+ scan_str = GF_CALLOC (1, st.st_size + 1,
gf_common_mt_char);
+
if (scan_str == NULL) {
ret = -1;
store_errno = GD_STORE_ENOMEM;
@@ -532,7 +543,11 @@ gf_store_iter_get_next (gf_store_iter_t *iter, char **key, char **value,
goto out;
}
- scan_str = GF_CALLOC (1, st.st_size,
+ /* "st.st_size + 1" is used as we are fetching each
+ * line of a file using fgets, fgets will append "\0"
+ * to the end of the string
+ */
+ scan_str = GF_CALLOC (1, st.st_size + 1,
gf_common_mt_char);
if (!scan_str) {
ret = -1;
diff --git a/xlators/mgmt/glusterd/src/glusterd-locks.c b/xlators/mgmt/glusterd/src/glusterd-locks.c
index f0658da3a..0737a731e 100644
--- a/xlators/mgmt/glusterd/src/glusterd-locks.c
+++ b/xlators/mgmt/glusterd/src/glusterd-locks.c
@@ -169,9 +169,10 @@ glusterd_multiple_volumes_lock (dict_t *dict, uuid_t uuid)
ret = glusterd_volume_lock (volname, uuid);
if (ret) {
gf_log ("", GF_LOG_ERROR,
- "Failed to acquire lock for %s. "
- "Unlocking other volumes locked "
- "by this transaction", volname);
+ "Failed to acquire lock for %s "
+ "on behalf of %s. Unlocking "
+ "other volumes locked by this "
+ "transaction", volname, uuid_utoa(uuid));
break;
}
locked_volcount ++;
@@ -214,23 +215,27 @@ glusterd_volume_lock (char *volname, uuid_t uuid)
uuid_t owner = {0};
if (!volname) {
- gf_log ("", GF_LOG_ERROR, "volname is null.");
+ gf_log (THIS->name, GF_LOG_ERROR, "volname is null.");
ret = -1;
goto out;
}
+ gf_log (THIS->name, GF_LOG_TRACE,
+ "Trying to acquire lock of %s for %s",
+ volname, uuid_utoa (uuid));
+
ret = glusterd_get_vol_lock_owner (volname, &owner);
if (ret) {
- gf_log ("", GF_LOG_DEBUG, "Unable to get volume lock owner");
+ gf_log (THIS->name, GF_LOG_DEBUG,
+ "Unable to get volume lock owner");
goto out;
}
/* If the lock has already been held for the given volume
* we fail */
if (!uuid_is_null (owner)) {
- gf_log ("", GF_LOG_ERROR, "Unable to acquire lock. "
- "Lock for %s held by %s", volname,
- uuid_utoa (owner));
+ gf_log (THIS->name, GF_LOG_ERROR, "Lock for %s held by %s",
+ volname, uuid_utoa (owner));
ret = -1;
goto out;
}
@@ -244,21 +249,22 @@ glusterd_volume_lock (char *volname, uuid_t uuid)
uuid_copy (lock_obj->lock_owner, uuid);
- ret = dict_set_bin (vol_lock, volname, lock_obj, sizeof(vol_lock_obj));
+ ret = dict_set_bin (vol_lock, volname, lock_obj,
+ sizeof(vol_lock_obj));
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to set lock owner "
- "in volume lock");
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Unable to set lock owner in volume lock");
if (lock_obj)
GF_FREE (lock_obj);
goto out;
}
- gf_log ("", GF_LOG_DEBUG, "Lock for %s successfully held by %s",
+ gf_log (THIS->name, GF_LOG_DEBUG, "Lock for %s successfully held by %s",
volname, uuid_utoa (uuid));
ret = 0;
out:
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
+ gf_log (THIS->name, GF_LOG_TRACE, "Returning %d", ret);
return ret;
}
@@ -269,37 +275,45 @@ glusterd_volume_unlock (char *volname, uuid_t uuid)
uuid_t owner = {0};
if (!volname) {
- gf_log ("", GF_LOG_ERROR, "volname is null.");
+ gf_log (THIS->name, GF_LOG_ERROR, "volname is null.");
ret = -1;
goto out;
}
+ gf_log (THIS->name, GF_LOG_TRACE, "Trying to release lock of %s for %s",
+ volname, uuid_utoa (uuid));
+
ret = glusterd_get_vol_lock_owner (volname, &owner);
- if (ret)
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_DEBUG,
+ "Unable to get volume lock owner");
goto out;
+ }
if (uuid_is_null (owner)) {
- gf_log ("", GF_LOG_ERROR, "Lock for %s not held", volname);
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Lock for %s not held", volname);
ret = -1;
goto out;
}
ret = uuid_compare (uuid, owner);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Lock for %s held by %s. "
- "Unlock req received from %s", volname,
- uuid_utoa (owner), uuid_utoa (uuid));
+
+ gf_log (THIS->name, GF_LOG_ERROR, "Lock owner mismatch. "
+ "Lock for %s held by %s",
+ volname, uuid_utoa (owner));
goto out;
}
/* Removing the volume lock from the global list */
dict_del (vol_lock, volname);
- gf_log ("", GF_LOG_DEBUG, "Lock for %s successfully released",
+ gf_log (THIS->name, GF_LOG_DEBUG, "Lock for %s successfully released",
volname);
ret = 0;
out:
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
+ gf_log (THIS->name, GF_LOG_TRACE, "Returning %d", ret);
return ret;
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c b/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c
index 236d9b72f..2ebe372cc 100644
--- a/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c
+++ b/xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c
@@ -63,6 +63,8 @@ glusterd_syctasked_volume_lock (rpcsvc_request_t *req,
this = THIS;
GF_ASSERT (this);
GF_ASSERT (req);
+ GF_ASSERT (ctx);
+ GF_ASSERT (ctx->dict);
ret = dict_get_int32 (ctx->dict, "volcount", &volcount);
if (ret) {
@@ -72,21 +74,22 @@ glusterd_syctasked_volume_lock (rpcsvc_request_t *req,
"Failed to get volname");
goto out;
}
- ret = glusterd_volume_lock (volname, MY_UUID);
+ ret = glusterd_volume_lock (volname, ctx->uuid);
if (ret)
gf_log (this->name, GF_LOG_ERROR,
"Unable to acquire local lock for %s", volname);
} else {
/* Trying to acquire volume locks on multiple volumes */
- ret = glusterd_multiple_volumes_lock (ctx->dict, MY_UUID);
+ ret = glusterd_multiple_volumes_lock (ctx->dict, ctx->uuid);
if (ret)
gf_log ("", GF_LOG_ERROR,
- "Failed to acquire volume locks on localhost");
+ "Failed to acquire volume locks for %s",
+ uuid_utoa (ctx->uuid));
}
out:
- glusterd_mgmt_v3_vol_lock_send_resp (req, ret);
+ ret = glusterd_mgmt_v3_vol_lock_send_resp (req, ret);
gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret);
return ret;
@@ -749,20 +752,21 @@ glusterd_syctasked_volume_unlock (rpcsvc_request_t *req,
"Failed to get volname");
goto out;
}
- ret = glusterd_volume_unlock (volname, MY_UUID);
+ ret = glusterd_volume_unlock (volname, ctx->uuid);
if (ret)
gf_log (this->name, GF_LOG_ERROR,
- "Unable to acquire local lock for %s", volname);
+ "Unable to release lock for %s", volname);
} else {
/* Trying to release volume locks on multiple volumes */
- ret = glusterd_multiple_volumes_unlock (ctx->dict, MY_UUID);
+ ret = glusterd_multiple_volumes_unlock (ctx->dict, ctx->uuid);
if (ret)
gf_log ("", GF_LOG_ERROR,
- "Failed to release volume locks on localhost");
+ "Failed to release volume locks for %s",
+ uuid_utoa(ctx->uuid));
}
out:
- glusterd_mgmt_v3_vol_unlock_send_resp (req, ret);
+ ret = glusterd_mgmt_v3_vol_unlock_send_resp (req, ret);
gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret);
return ret;
diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt.c b/xlators/mgmt/glusterd/src/glusterd-mgmt.c
index 852d60fb4..424bcca8a 100644
--- a/xlators/mgmt/glusterd/src/glusterd-mgmt.c
+++ b/xlators/mgmt/glusterd/src/glusterd-mgmt.c
@@ -448,12 +448,20 @@ gd_mgmt_v3_pre_validate_cbk_fn (struct rpc_req *req, struct iovec *iov,
}
pthread_mutex_unlock (&args->lock_dict);
- if (ret)
+ if (ret) {
gf_log ("", GF_LOG_ERROR, "%s",
"Failed to aggregate response from "
" node/brick");
- op_ret = rsp.op_ret;
- op_errno = rsp.op_errno;
+ if (!rsp.op_ret)
+ op_ret = ret;
+ else {
+ op_ret = rsp.op_ret;
+ op_errno = rsp.op_errno;
+ }
+ } else {
+ op_ret = rsp.op_ret;
+ op_errno = rsp.op_errno;
+ }
out:
if (rsp_dict)
dict_unref (rsp_dict);
@@ -852,15 +860,24 @@ gd_mgmt_v3_commit_cbk_fn (struct rpc_req *req, struct iovec *iov,
{
ret = glusterd_syncop_aggr_rsp_dict (rsp.op, args->dict,
rsp_dict);
- if (ret)
- gf_log ("", GF_LOG_ERROR, "%s",
- "Failed to aggregate response from "
- " node/brick");
}
pthread_mutex_unlock (&args->lock_dict);
- op_ret = rsp.op_ret;
- op_errno = rsp.op_errno;
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "%s",
+ "Failed to aggregate response from "
+ " node/brick");
+ if (!rsp.op_ret)
+ op_ret = ret;
+ else {
+ op_ret = rsp.op_ret;
+ op_errno = rsp.op_errno;
+ }
+ } else {
+ op_ret = rsp.op_ret;
+ op_errno = rsp.op_errno;
+ }
+
out:
gd_mgmt_v3_collate_errors (args, op_ret, op_errno, NULL,
GLUSTERD_MGMT_V3_COMMIT,
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
index 0162fd23e..28c58f036 100644
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
@@ -1510,14 +1510,47 @@ glusterd_stop_bricks (glusterd_volinfo_t *volinfo)
int
glusterd_start_bricks (glusterd_volinfo_t *volinfo)
{
- glusterd_brickinfo_t *brickinfo = NULL;
+ int ret = -1;
+ glusterd_brickinfo_t *brickinfo = NULL;
+ glusterd_volinfo_t *parent_volinfo = NULL;
- list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
- if (glusterd_brick_start (volinfo, brickinfo, _gf_false))
- return -1;
+ GF_ASSERT (volinfo);
+
+ if (volinfo->is_snap_volume == _gf_true) {
+ ret = glusterd_volinfo_find (volinfo->parent_volname, &parent_volinfo);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Unable to find parent volume %s for snap %s",
+ volinfo->parent_volname, volinfo->volname);
+ goto out;
+ }
+ list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
+ ret = glusterd_snap_brick_start (parent_volinfo, volinfo,
+ brickinfo, _gf_false);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Failed to start %s:%s for %s",
+ brickinfo->hostname, brickinfo->path,
+ volinfo->volname);
+ goto out;
+ }
+ }
+ } else {
+ list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
+ ret = glusterd_brick_start (volinfo, brickinfo, _gf_false);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Failed to start %s:%s for %s",
+ brickinfo->hostname, brickinfo->path,
+ volinfo->volname);
+ goto out;
+ }
+ }
}
- return 0;
+ ret = 0;
+out:
+ return ret;
}
static int
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
index cd9ed3f23..8419cfb25 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);
@@ -395,20 +289,21 @@ out:
}
int
-snap_max_limits_validate (dict_t *dict, char *key,
- char **op_errstr)
+snap_max_limits_validate (dict_t *dict, char *volname, char *key,
+ uint64_t value, char **op_errstr)
{
char err_str[PATH_MAX] = "";
glusterd_conf_t *conf = NULL;
+ glusterd_volinfo_t *volinfo = NULL;
int ret = -1;
- uint64_t value = 0;
- uint64_t max_limit = GLUSTERD_SNAPS_MAX_LIMIT;
+ uint64_t max_limit = GLUSTERD_SNAPS_MAX_HARD_LIMIT;
xlator_t *this = NULL;
this = THIS;
GF_ASSERT (this);
GF_ASSERT (dict);
+ GF_ASSERT (volname);
GF_ASSERT (key);
GF_ASSERT (op_errstr);
@@ -416,13 +311,31 @@ snap_max_limits_validate (dict_t *dict, char *key,
GF_ASSERT (conf);
- ret = dict_get_uint64 (dict, key, &value);
- if (ret) {
- snprintf (err_str, PATH_MAX,"Failed to get the"
- " value for %s", key);
- *op_errstr = gf_strdup (err_str);
- gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
- goto out;
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (!ret) {
+ if (volinfo->is_snap_volume) {
+ ret = -1;
+ snprintf (err_str, PATH_MAX,"%s is a snap volume. "
+ "Configuring %s for a snap volume is "
+ "prohibited.", volname, key);
+ goto out;
+ }
+ }
+
+ if (!strcmp (key, "snap-max-hard-limit")) {
+ max_limit = GLUSTERD_SNAPS_MAX_HARD_LIMIT;
+ if ((max_limit > conf->snap_max_hard_limit) &&
+ (strncmp (volname, "all", strlen(volname))))
+ max_limit = conf->snap_max_hard_limit;
+ } else {
+ max_limit = GLUSTERD_SNAPS_MAX_SOFT_LIMIT_PERCENT;
+ if (strncmp (volname, "all", strlen(volname))) {
+ ret = -1;
+ snprintf (err_str, PATH_MAX, "%s is not configurable "
+ "for individual volumes. Configure %s for "
+ "system.", key, key);
+ goto out;
+ }
}
if ((value < 0) ||
@@ -431,13 +344,15 @@ snap_max_limits_validate (dict_t *dict, char *key,
snprintf (err_str, PATH_MAX, "Invalid %s "
"%"PRIu64 ". Expected range 0 - %"PRIu64,
key, value, max_limit);
- *op_errstr = gf_strdup (err_str);
- gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
ret = 0;
out:
+ if (ret) {
+ *op_errstr = gf_strdup (err_str);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
+ }
return ret;
}
@@ -452,6 +367,7 @@ glusterd_snapshot_config_prevalidate (dict_t *dict, char **op_errstr)
int config_command = 0;
char err_str[PATH_MAX] = {0,};
glusterd_conf_t *conf = NULL;
+ uint64_t value = 0;
this = THIS;
@@ -471,34 +387,27 @@ glusterd_snapshot_config_prevalidate (dict_t *dict, char **op_errstr)
}
ret = dict_get_str (dict, "config-key", &key);
-
- switch (config_command) {
- case GF_SNAP_CONFIG_TYPE_SET:
- if ((!strncmp (key, "snap-max-hard-limit", strlen(key))) ||
- (!strncmp (key, "snap-max-soft-limit", strlen(key)))) {
- /* Validations for snap-max-hard-limit and snap-max-soft-limit */
- ret = snap_max_limits_validate (dict, key, op_errstr);
- if (ret) {
- gf_log (this->name, GF_LOG_ERROR,
- "%s validation failed.", key);
- goto out;
- }
- }
- break;
-
- case GF_SNAP_CONFIG_DISPLAY:
- ret = dict_get_str (dict, "volname", &volname);
+ if (!ret) {
+ ret = dict_get_uint64 (dict, key, &value);
if (ret) {
snprintf (err_str, PATH_MAX,"Failed to get the"
- " volume name");
+ " value for %s", key);
*op_errstr = gf_strdup (err_str);
gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
- if (!strncmp (volname, "all", strlen(volname))) {
- ret = 0;
- goto out;
- }
+ }
+
+ ret = dict_get_str (dict, "volname", &volname);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,"Failed to get the"
+ " volume name");
+ *op_errstr = gf_strdup (err_str);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
+ goto out;
+ }
+
+ if (strncmp (volname, "all", strlen(volname))) {
ret = glusterd_volinfo_find (volname, &volinfo);
if (ret) {
snprintf (err_str, PATH_MAX,"Volume %s does not exist.",
@@ -507,7 +416,23 @@ glusterd_snapshot_config_prevalidate (dict_t *dict, char **op_errstr)
gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
+ }
+
+ switch (config_command) {
+ case GF_SNAP_CONFIG_TYPE_SET:
+ if ((!strncmp (key, "snap-max-hard-limit", strlen(key))) ||
+ (!strncmp (key, "snap-max-soft-limit", strlen(key)))) {
+ /* Validations for snap-max-limits */
+ ret = snap_max_limits_validate (dict, volname,
+ key, value, op_errstr);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s validation failed.", key);
+ goto out;
+ }
+ }
break;
+
default:
break;
}
@@ -2664,7 +2589,7 @@ int32_t
glusterd_snap_create (glusterd_volinfo_t *volinfo,
glusterd_volinfo_t *snap_volinfo,
char *description, uuid_t *cg_id,
- char *cg_name)
+ glusterd_snap_cg_t *cg, char *cg_name)
{
glusterd_snap_t *snap = NULL;
xlator_t *this = NULL;
@@ -2693,8 +2618,26 @@ glusterd_snap_create (glusterd_volinfo_t *volinfo,
// for now ignore if description is not strduped
- if (description)
- snap->description = gf_strdup (description);
+ if (description) {
+ if (cg_id) {
+ cg->description = gf_strdup (description);
+ if (cg->description == NULL) {
+ gf_log ("", GF_LOG_ERROR,
+ "Saving the CG Description Failed");
+ ret = -1;
+ goto out;
+ }
+ }
+ else {
+ snap->description = gf_strdup (description);
+ if (snap->description == NULL) {
+ gf_log ("", GF_LOG_ERROR,
+ "Saving the Snap Description Failed");
+ ret = -1;
+ goto out;
+ }
+ }
+ }
snap->time_stamp = time (NULL);
uuid_copy (snap->snap_id, snap_volinfo->volume_id);
if (cg_id){
@@ -3016,7 +2959,7 @@ out:
*/
int32_t
glusterd_do_snap (glusterd_volinfo_t *volinfo, char *snapname, dict_t *dict,
- gf_boolean_t cg, uuid_t *cg_id, int volcount,
+ glusterd_snap_cg_t *cg, uuid_t *cg_id, int volcount,
uuid_t snap_volid, char *cg_name)
{
char *snap_brick_mount_path = "";
@@ -3160,7 +3103,7 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *snapname, dict_t *dict,
// for now continue the snap, if getting description fails.
ret = glusterd_snap_create (volinfo, snap_volume, description, cg_id,
- cg_name);
+ cg, cg_name);
if (ret) {
gf_log (this->name, GF_LOG_ERROR, "creating the"
"snap object failed for the volume %s",
@@ -3185,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",
@@ -3194,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",
@@ -3968,13 +3911,40 @@ glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr,
gf_log (this->name, GF_LOG_ERROR, "Unable to fetch snap-name");
goto out;
}
+ tmp = gf_strdup (name);
+ if (!tmp) {
+ gf_log (this->name, GF_LOG_ERROR, "Out of memory");
+ goto out;
+ }
+
+ ret = dict_set_dynstr (rsp_dict, "snap-name", tmp);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Unable to set snap-name in rsp_dict");
+ GF_FREE (tmp);
+ goto out;
+ }
} else {
ret = dict_get_str (dict, "cg-name", &name);
if (ret) {
gf_log (this->name, GF_LOG_ERROR, "Unable to fetch cg-name");
goto out;
}
+ tmp = gf_strdup (name);
+ if (!tmp) {
+ gf_log (this->name, GF_LOG_ERROR, "Out of memory");
+ goto out;
+ }
+
+ ret = dict_set_str (rsp_dict, "cg-name", tmp);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Unable to set cg-name in rsp_dict");
+ GF_FREE (tmp);
+ goto out;
+ }
}
+ tmp = NULL;
ret = dict_get_bin (dict, "cg-id", (void **)&cg_id);
if (ret)
@@ -4049,11 +4019,11 @@ glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr,
*/
if (is_cg) {
ret = glusterd_do_snap (volinfo, tmp, dict,
- is_cg, cg_id, i, *snap_volid, name);
+ cg, cg_id, i, *snap_volid, name);
}
else {
ret = glusterd_do_snap (volinfo, tmp, dict,
- is_cg, cg_id, i, *snap_volid, NULL);
+ cg, cg_id, i, *snap_volid, NULL);
}
if (ret) {
gf_log (this->name, GF_LOG_WARNING, "taking the "
@@ -4094,14 +4064,13 @@ out:
}
int
-snap_max_limits_set_commit (dict_t *dict, char *key, char *volname,
- char **op_errstr)
+snap_max_hard_limit_set_commit (dict_t *dict, char *key, uint64_t value,
+ char *volname, char **op_errstr)
{
char err_str[PATH_MAX] = "";
glusterd_conf_t *conf = NULL;
glusterd_volinfo_t *volinfo = NULL;
int ret = -1;
- uint64_t value = 0;
xlator_t *this = NULL;
this = THIS;
@@ -4116,20 +4085,10 @@ snap_max_limits_set_commit (dict_t *dict, char *key, char *volname,
GF_ASSERT (conf);
- ret = dict_get_uint64 (dict, key, &value);
- if (ret) {
- snprintf (err_str, PATH_MAX,"Failed to get the"
- " value for %s", key);
- goto out;
- }
-
/* TODO: Initiate auto deletion when there is a limit change */
if (!strncmp (volname, "all", strlen(volname))) {
/* For system limit */
- if (!strncmp (key, "snap-max-hard-limit", strlen(key)))
- conf->snap_max_hard_limit = value;
- else
- conf->snap_max_soft_limit = value;
+ conf->snap_max_hard_limit = value;
ret = glusterd_store_global_info (this);
if (ret) {
@@ -4146,10 +4105,7 @@ snap_max_limits_set_commit (dict_t *dict, char *key, char *volname,
goto out;
}
- if (!strncmp (key, "snap-max-hard-limit", strlen(key)))
- volinfo->snap_max_hard_limit = value;
- else
- volinfo->snap_max_soft_limit = value;
+ volinfo->snap_max_hard_limit = value;
ret = glusterd_store_volinfo (volinfo,
GLUSTERD_VOLINFO_VER_AC_INCREMENT);
@@ -4166,26 +4122,28 @@ out:
*op_errstr = gf_strdup (err_str);
gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
}
-
return ret;
}
int
-snap_max_limits_display_commit (dict_t *rsp_dict, char *key, char *volname,
+snap_max_limits_display_commit (dict_t *rsp_dict, char *volname,
char **op_errstr)
{
char err_str[PATH_MAX] = "";
+ char buf[PATH_MAX] = "";
glusterd_conf_t *conf = NULL;
glusterd_volinfo_t *volinfo = NULL;
int ret = -1;
- uint64_t value = 0;
+ uint64_t active_hard_limit = 0;
+ uint64_t snap_max_limit = 0;
+ uint64_t soft_limit_value = -1;
+ uint64_t count = 0;
xlator_t *this = NULL;
this = THIS;
GF_ASSERT (this);
GF_ASSERT (rsp_dict);
- GF_ASSERT (key);
GF_ASSERT (volname);
GF_ASSERT (op_errstr);
@@ -4195,38 +4153,122 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *key, char *volname,
if (!strncmp (volname, "all", strlen(volname))) {
/* For system limit */
- if (!strncmp (key, "snap-max-hard-limit", strlen(key)))
- value = conf->snap_max_hard_limit;
- else
- value = conf->snap_max_soft_limit;
+ list_for_each_entry (volinfo, &conf->volumes, vol_list) {
+ if (volinfo->is_snap_volume == _gf_true)
+ continue;
+ snap_max_limit = volinfo->snap_max_hard_limit;
+ if (snap_max_limit > conf->snap_max_hard_limit)
+ active_hard_limit = conf->snap_max_hard_limit;
+ else
+ active_hard_limit = snap_max_limit;
+ soft_limit_value = (active_hard_limit *
+ conf->snap_max_soft_limit) / 100;
+
+ snprintf (buf, sizeof(buf), "volume%ld-volname", count);
+ ret = dict_set_str (rsp_dict, buf, volinfo->volname);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,
+ "Failed to set %s", buf);
+ goto out;
+ }
+
+ snprintf (buf, sizeof(buf),
+ "volume%ld-snap-max-hard-limit", count);
+ ret = dict_set_uint64 (rsp_dict, buf, snap_max_limit);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,
+ "Failed to set %s", buf);
+ goto out;
+ }
+
+ snprintf (buf, sizeof(buf),
+ "volume%ld-snap-max-soft-limit-value", count);
+ ret = dict_set_uint64 (rsp_dict, buf, soft_limit_value);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,
+ "Failed to set %s", buf);
+ goto out;
+ }
+ count++;
+ }
+
+ ret = dict_set_uint64 (rsp_dict, "voldisplaycount", count);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,
+ "Failed to set voldisplaycount");
+ goto out;
+ }
} else {
- /* For one volume */
+ /* For one volume */
ret = glusterd_volinfo_find (volname, &volinfo);
if (ret) {
snprintf (err_str, PATH_MAX,"Failed to get the"
" volinfo for volume %s", volname);
- *op_errstr = gf_strdup (err_str);
- gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
- if (!strncmp (key, "snap-max-hard-limit", strlen(key)))
- value = volinfo->snap_max_hard_limit;
- else
- value = volinfo->snap_max_soft_limit;
+ snap_max_limit = volinfo->snap_max_hard_limit;
+ soft_limit_value = (volinfo->snap_max_hard_limit *
+ conf->snap_max_soft_limit) / 100;
+
+ snprintf (buf, sizeof(buf), "volume%ld-volname", count);
+ ret = dict_set_str (rsp_dict, buf, volinfo->volname);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,
+ "Failed to set %s", buf);
+ goto out;
+ }
+
+ snprintf (buf, sizeof(buf),
+ "volume%ld-snap-max-hard-limit", count);
+ ret = dict_set_uint64 (rsp_dict, buf, snap_max_limit);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,
+ "Failed to set %s", buf);
+ goto out;
+ }
+
+ snprintf (buf, sizeof(buf),
+ "volume%ld-snap-max-soft-limit-value", count);
+ ret = dict_set_uint64 (rsp_dict, buf, soft_limit_value);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,
+ "Failed to set %s", buf);
+ goto out;
+ }
+ count++;
+
+ ret = dict_set_uint64 (rsp_dict, "voldisplaycount", count);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,
+ "Failed to set voldisplaycount");
+ goto out;
+ }
+
}
- ret = dict_set_uint64 (rsp_dict, key, value);
+ ret = dict_set_uint64 (rsp_dict, "snap-max-hard-limit",
+ conf->snap_max_hard_limit);
if (ret) {
- snprintf (err_str, PATH_MAX,"Failed to set %s "
- "for volume %s", key, volname);
- *op_errstr = gf_strdup (err_str);
- gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
+ snprintf (err_str, PATH_MAX,
+ "Failed to set sys-snap-max-hard-limit ");
+ goto out;
+ }
+
+ ret = dict_set_uint64 (rsp_dict, "snap-max-soft-limit",
+ conf->snap_max_soft_limit);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,
+ "Failed to set sys-snap-max-hard-limit ");
goto out;
}
ret = 0;
out:
+ if (ret) {
+ *op_errstr = gf_strdup (err_str);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
+ }
return ret;
}
@@ -4241,12 +4283,12 @@ glusterd_snapshot_config_commit (dict_t *dict, char **op_errstr,
char err_str[PATH_MAX] = {0,};
glusterd_conf_t *conf = NULL;
int config_command = 0;
+ uint64_t value = 0;
this = THIS;
GF_ASSERT (this);
GF_ASSERT (dict);
- GF_ASSERT (rsp_dict);
GF_ASSERT (op_errstr);
conf = this->private;
@@ -4270,51 +4312,56 @@ glusterd_snapshot_config_commit (dict_t *dict, char **op_errstr,
}
ret = dict_get_str (dict, "config-key", &key);
+ if (!ret) {
+ ret = dict_get_uint64 (dict, key, &value);
+ if (ret) {
+ snprintf (err_str, PATH_MAX,"Failed to get the"
+ " value for %s", key);
+ *op_errstr = gf_strdup (err_str);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
+ goto out;
+ }
+ }
switch (config_command) {
case GF_SNAP_CONFIG_TYPE_SET:
- if ((!strncmp (key, "snap-max-hard-limit", strlen(key))) ||
- (!strncmp (key, "snap-max-soft-limit", strlen(key)))) {
- /* Commit ops for snap-max-hard-limit and snap-max-soft-limit */
- ret = snap_max_limits_set_commit (dict, key, volname, op_errstr);
+ if (!strncmp (key, "snap-max-hard-limit", strlen(key))) {
+ /* Commit ops for snap-max-hard-limit */
+ ret = snap_max_hard_limit_set_commit (dict, key, value,
+ volname, op_errstr);
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
"%s set commit failed.", key);
goto out;
}
- }
- break;
+ } else if (!strncmp (key, "snap-max-soft-limit", strlen(key))) {
+ /* For system limit */
+ conf->snap_max_soft_limit = value;
- case GF_SNAP_CONFIG_DISPLAY:
- if (!key) {
- /* For all options */
- ret = snap_max_limits_display_commit (rsp_dict, "snap-max-hard-limit",
- volname, op_errstr);
+ ret = glusterd_store_global_info (this);
if (ret) {
- gf_log (this->name, GF_LOG_ERROR,
- "snap-max-hard-limit "
- "display commit failed.");
+ snprintf (err_str, PATH_MAX,"Failed to store %s "
+ "for system", key);
+ *op_errstr = gf_strdup (err_str);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
+ }
+ break;
- ret = snap_max_limits_display_commit (rsp_dict, "snap-max-soft-limit",
- volname, op_errstr);
- if (ret) {
- gf_log (this->name, GF_LOG_ERROR,
- "snap-max-soft-limit "
- "display commit failed.");
- goto out;
- }
- } else if ((!strncmp (key, "snap-max-hard-limit", strlen(key))) ||
- (!strncmp (key, "snap-max-soft-limit", strlen(key)))) {
- /* Commit ops for snap-max-hard-limit or snap-max-soft-limit */
- ret = snap_max_limits_display_commit (rsp_dict, key,
- volname, op_errstr);
- if (ret) {
- gf_log (this->name, GF_LOG_ERROR,
- "%s display commit failed.", key);
- goto out;
- }
+ case GF_SNAP_CONFIG_DISPLAY:
+ /* Reading data from local node only */
+ if (!is_origin_glusterd (dict)) {
+ ret = 0;
+ break;
+ }
+
+ ret = snap_max_limits_display_commit (rsp_dict, volname, op_errstr);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "snap-max-limit "
+ "display commit failed.");
+ goto out;
}
break;
default:
@@ -4504,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 f37ad9bec..41633ebd8 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,21 +702,20 @@ glusterd_volume_exclude_options_write (int fd, glusterd_volinfo_t *volinfo)
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);
+ 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 snap-max-hard-limit");
+ "Unable to write is_volume_restored");
goto out;
}
- snprintf (buf, sizeof (buf), "%"PRIu64, volinfo->snap_max_soft_limit);
- ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT,
+ snprintf (buf, sizeof (buf), "%"PRIu64, volinfo->snap_max_hard_limit);
+ ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT,
buf);
if (ret) {
gf_log (THIS->name, GF_LOG_ERROR,
- "Unable to write snap-max-soft-limit");
+ "Unable to write snap-max-hard-limit");
goto out;
}
@@ -1231,6 +1229,16 @@ glusterd_store_snap_list_write (int fd, glusterd_snap_t *snap, uint64_t count)
if (ret)
goto out;
+ if ( strlen(snap->cg_name) > 0 ) {
+ snprintf (key, sizeof (key), "%s-%"PRIu64,
+ GLUSTERD_STORE_KEY_SNAP_CG_NAME, count);
+ ret = gf_store_save_value (fd, key, snap->cg_name);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Failed to store cg_name");
+ goto out;
+ }
+ }
+
snprintf (key, sizeof (key), "%s-%"PRIu64, GLUSTERD_STORE_KEY_SNAP_ID,
count);
ret = gf_store_save_value (fd, key, uuid_utoa(snap->snap_id));
@@ -1251,7 +1259,7 @@ glusterd_store_snap_list_write (int fd, glusterd_snap_t *snap, uint64_t count)
goto out;
if (snap->description) {
- snprintf (buf, sizeof (buf), "%s\n", snap->description);
+ snprintf (buf, sizeof (buf), "%s", snap->description);
snprintf (key, sizeof (key), "%s-%"PRIu64,
GLUSTERD_STORE_KEY_SNAP_DESC, count);
ret = gf_store_save_value (fd, key, buf);
@@ -1296,7 +1304,7 @@ glusterd_store_snap_cg_write (int fd, glusterd_snap_cg_t *cg)
goto out;
if (cg->description) {
- snprintf (buf, sizeof (buf), "%s\n", cg->description);
+ snprintf (buf, sizeof (buf), "%s", cg->description);
ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_SNAP_DESC,
buf);
if (ret)
@@ -1518,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);
@@ -2228,7 +2242,6 @@ glusterd_restore_op_version (xlator_t *this)
glusterd_conf_t *conf = NULL;
int ret = 0;
int op_version = 0;
- int snap_max_limit = GLUSTERD_SNAPS_MAX_LIMIT;
conf = this->private;
@@ -2238,8 +2251,9 @@ glusterd_restore_op_version (xlator_t *this)
if (ret) {
gf_log (this->name, GF_LOG_WARNING,
"Unable to retrieve system snap-max-hard-limit, "
- "setting it to %d", snap_max_limit);
- conf->snap_max_hard_limit = GLUSTERD_SNAPS_MAX_LIMIT;
+ "setting it to default value(%d)",
+ GLUSTERD_SNAPS_MAX_HARD_LIMIT);
+ conf->snap_max_hard_limit = GLUSTERD_SNAPS_MAX_HARD_LIMIT;
}
ret = glusterd_retrieve_sys_snap_max_limit (this,
@@ -2248,8 +2262,9 @@ glusterd_restore_op_version (xlator_t *this)
if (ret) {
gf_log (this->name, GF_LOG_WARNING,
"Unable to retrieve system snap-max-soft-limit, "
- "setting it to %d", snap_max_limit);
- conf->snap_max_soft_limit = GLUSTERD_SNAPS_MAX_LIMIT;
+ "setting it to default value(%d)",
+ GLUSTERD_SNAPS_DEF_SOFT_LIMIT_PERCENT);
+ conf->snap_max_soft_limit = GLUSTERD_SNAPS_DEF_SOFT_LIMIT_PERCENT;
}
ret = glusterd_retrieve_op_version (this, &op_version);
@@ -2678,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);
@@ -2799,9 +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_SNAP_MAX_SOFT_LIMIT,
- strlen (GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT))) {
- volinfo->snap_max_soft_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);
@@ -2892,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
@@ -2917,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;
}
@@ -3081,7 +3156,7 @@ glusterd_store_retrieve_snap_cg (char *cg_store_name, glusterd_conf_t *priv)
if (!strncmp(key, GLUSTERD_STORE_KEY_SNAP_NAME,
sizeof (*key))) {
- strncpy (cg->cg_name, value, sizeof (value));
+ strcpy (cg->cg_name, value);
} else if (!strncmp(key, GLUSTERD_STORE_KEY_SNAP_STATUS,
sizeof (*key))) {
cg->cg_status = atoi (value);
@@ -3226,11 +3301,26 @@ glusterd_store_retrieve_snap_list (char *volname)
GF_FREE (value);
value = NULL;
+ if (!uuid_is_null(snap -> cg_id)) {
+ snprintf (key, sizeof (key), "%s-%"PRIu64,
+ GLUSTERD_STORE_KEY_SNAP_CG_NAME, count);
+ ret = gf_store_retrieve_value (shandle, key, &value);
+ if (ret){
+ gf_log ("", GF_LOG_ERROR,"Failed to retreive "
+ "CG name");
+ goto out;
+ }
+ strcpy (snap->cg_name, value);
+ GF_FREE (value);
+ value = NULL;
+ }
+
snprintf (key, sizeof (key), "%s-%"PRIu64,
GLUSTERD_STORE_KEY_SNAP_DESC, count);
ret = gf_store_retrieve_value (shandle, key, &value);
if (!ret) {
- snap->description = value;
+ if (uuid_is_null (snap -> cg_id))
+ snap->description = value;
value = NULL;
} else {
ret = 0;
diff --git a/xlators/mgmt/glusterd/src/glusterd-store.h b/xlators/mgmt/glusterd/src/glusterd-store.h
index 13d408c44..d9192e396 100644
--- a/xlators/mgmt/glusterd/src/glusterd-store.h
+++ b/xlators/mgmt/glusterd/src/glusterd-store.h
@@ -35,54 +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_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 {\
@@ -139,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 6947facbd..dedfd890f 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -463,8 +463,7 @@ glusterd_volinfo_new (glusterd_volinfo_t **volinfo)
snprintf (new_volinfo->parent_volname, GLUSTERD_MAX_VOLUME_NAME, "N/A");
- new_volinfo->snap_max_hard_limit = GLUSTERD_SNAPS_MAX_LIMIT;
- new_volinfo->snap_max_soft_limit = GLUSTERD_SNAPS_MAX_LIMIT;
+ new_volinfo->snap_max_hard_limit = GLUSTERD_SNAPS_MAX_HARD_LIMIT;
new_volinfo->xl = THIS;
@@ -1543,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))
@@ -1761,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);
@@ -1817,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);
@@ -2160,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);
@@ -2214,6 +2222,20 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
if (ret)
goto out;
+ snprintf (key, sizeof (key), "volume%d.is_snap_volume", count);
+ ret = dict_set_uint32 (dict, key, volinfo->is_snap_volume);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Unable to set %s", key);
+ goto out;
+ }
+
+ snprintf (key, sizeof (key), "volume%d.snap-max-hard-limit", count);
+ ret = dict_set_uint64 (dict, key, volinfo->snap_max_hard_limit);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Unable to set %s", key);
+ goto out;
+ }
+
volume_id_str = gf_strdup (uuid_utoa (volinfo->volume_id));
if (!volume_id_str) {
ret = -1;
@@ -2988,6 +3010,7 @@ glusterd_import_volinfo (dict_t *vols, int count,
char *rb_id_str = NULL;
int op_version = 0;
int client_op_version = 0;
+ uint32_t is_snap_volume = 0;
GF_ASSERT (vols);
GF_ASSERT (volinfo);
@@ -2999,6 +3022,22 @@ glusterd_import_volinfo (dict_t *vols, int count,
goto out;
}
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "volume%d.is_snap_volume", count);
+ ret = dict_get_uint32 (vols, key, &is_snap_volume);
+ if (ret) {
+ snprintf (msg, sizeof (msg), "%s missing in payload for %s",
+ key, volname);
+ goto out;
+ }
+
+ if (is_snap_volume == _gf_true) {
+ gf_log (THIS->name, GF_LOG_DEBUG,
+ "Not syncing snap volume %s", volname);
+ ret = 0;
+ goto out;
+ }
+
ret = glusterd_volinfo_new (&new_volinfo);
if (ret)
goto out;
@@ -3124,6 +3163,22 @@ glusterd_import_volinfo (dict_t *vols, int count,
goto out;
}
+ snprintf (key, sizeof (key), "volume%d.is_snap_volume", count);
+ ret = dict_get_uint32 (vols, key, &new_volinfo->is_snap_volume);
+ if (ret) {
+ snprintf (msg, sizeof (msg), "%s missing in payload for %s",
+ key, volname);
+ goto out;
+ }
+
+ snprintf (key, sizeof (key), "volume%d.snap-max-hard-limit", count);
+ ret = dict_get_uint64 (vols, key, &new_volinfo->snap_max_hard_limit);
+ if (ret) {
+ snprintf (msg, sizeof (msg), "%s missing in payload for %s",
+ key, volname);
+ goto out;
+ }
+
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "volume%d.rebalance", count);
ret = dict_get_uint32 (vols, key, &new_volinfo->rebal.defrag_cmd);
@@ -3406,6 +3461,12 @@ glusterd_import_friend_volume (dict_t *vols, size_t count)
if (ret)
goto out;
+ if (!new_volinfo) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "Not importing snap volume");
+ goto out;
+ }
+
ret = glusterd_volinfo_find (new_volinfo->volname, &old_volinfo);
if (0 == ret) {
(void) glusterd_delete_stale_volume (old_volinfo, new_volinfo);
@@ -5139,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;
@@ -5174,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);
@@ -7855,9 +7914,13 @@ out:
int
glusterd_snap_config_use_rsp_dict (dict_t *dst, dict_t *src)
{
+ char buf[PATH_MAX] = "";
+ char *volname = NULL;
int ret = -1;
- uint64_t value = 0;
int config_command = 0;
+ uint64_t i = 0;
+ uint64_t value = 0;
+ uint64_t voldisplaycount = 0;
if (!dst || !src) {
gf_log ("", GF_LOG_ERROR, "Source or Destination "
@@ -7881,13 +7944,78 @@ glusterd_snap_config_use_rsp_dict (dict_t *dst, dict_t *src)
gf_log ("", GF_LOG_ERROR, "Unable to set snap_max_hard_limit");
goto out;
}
+ } else {
+ /* Received dummy response from other nodes */
+ ret = 0;
+ goto out;
}
ret = dict_get_uint64 (src, "snap-max-soft-limit", &value);
- if (!ret) {
- ret = dict_set_uint64 (dst, "snap-max-soft-limit", value);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Unable to get snap_max_soft_limit");
+ goto out;
+ }
+
+ ret = dict_set_uint64 (dst, "snap-max-soft-limit", value);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Unable to set snap_max_soft_limit");
+ goto out;
+ }
+
+ ret = dict_get_uint64 (src, "voldisplaycount", &voldisplaycount);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Unable to get voldisplaycount");
+ goto out;
+ }
+
+ ret = dict_set_uint64 (dst, "voldisplaycount", voldisplaycount);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Unable to set voldisplaycount");
+ goto out;
+ }
+
+ for (i = 0; i < voldisplaycount; i++) {
+ snprintf (buf, sizeof(buf), "volume%ld-volname", i);
+ ret = dict_get_str (src, buf, &volname);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR,
+ "Unable to get %s", buf);
+ goto out;
+ }
+ ret = dict_set_str (dst, buf, volname);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR,
+ "Unable to set %s", buf);
+ goto out;
+ }
+
+ snprintf (buf, sizeof(buf),
+ "volume%ld-snap-max-hard-limit", i);
+ ret = dict_get_uint64 (src, buf, &value);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR,
+ "Unable to get %s", buf);
+ goto out;
+ }
+ ret = dict_set_uint64 (dst, buf, value);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR,
+ "Unable to set %s", buf);
+ goto out;
+ }
+
+ snprintf (buf, sizeof(buf),
+ "volume%ld-snap-max-soft-limit-value", i);
+ ret = dict_get_uint64 (src, buf, &value);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to set snap_max_soft_limit");
+ gf_log ("", GF_LOG_ERROR,
+ "Unable to get %s", buf);
+ goto out;
+ }
+ ret = dict_set_uint64 (dst, buf, value);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR,
+ "Unable to set %s", buf);
goto out;
}
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
index 1bc0db6ce..3b8e7648c 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 2b22f5226..f5163b477 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 343e6fe4d..40ae611fa 100644
--- a/xlators/mgmt/glusterd/src/glusterd.h
+++ b/xlators/mgmt/glusterd/src/glusterd.h
@@ -52,7 +52,9 @@
"S56glusterd-geo-rep-create-post.sh"
-#define GLUSTERD_SNAPS_MAX_LIMIT 256
+#define GLUSTERD_SNAPS_MAX_HARD_LIMIT 256
+#define GLUSTERD_SNAPS_DEF_SOFT_LIMIT_PERCENT 90
+#define GLUSTERD_SNAPS_MAX_SOFT_LIMIT_PERCENT 100
#define GLUSTERD_SERVER_QUORUM "server"
#define FMTSTR_CHECK_VOL_EXISTS "Volume %s does not exist"
@@ -276,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
@@ -287,7 +290,6 @@ struct glusterd_volinfo_ {
int brick_count;
uint64_t snap_count;
uint64_t snap_max_hard_limit;
- uint64_t snap_max_soft_limit;
struct list_head vol_list;
struct list_head bricks;
struct list_head snaps;
@@ -484,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) { \