diff options
-rw-r--r-- | cli/src/cli-cmd-parser.c | 45 | ||||
-rw-r--r-- | cli/src/cli-cmd-snapshot.c | 2 | ||||
-rw-r--r-- | cli/src/cli-rpc-ops.c | 108 | ||||
-rw-r--r-- | libglusterfs/src/store.c | 31 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-locks.c | 56 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c | 22 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mgmt.c | 35 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 43 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-snapshot.c | 550 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-store.c | 202 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-store.h | 94 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 164 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 514 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.h | 5 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 23 |
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) { \ |