diff options
-rw-r--r-- | cli/src/cli-cmd-parser.c | 103 | ||||
-rw-r--r-- | cli/src/cli-cmd-snapshot.c | 10 | ||||
-rw-r--r-- | cli/src/cli-rpc-ops.c | 70 | ||||
-rw-r--r-- | libglusterfs/src/store.c | 31 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handshake.c | 6 | ||||
-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 | 247 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-store.c | 190 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-store.h | 95 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 118 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 3 | ||||
-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.c | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 19 |
18 files changed, 1179 insertions, 389 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 59e951636..6abd97ce7 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -2754,12 +2754,10 @@ out: int32_t cli_snap_create_desc_parse (dict_t *dict, const char **words, - int wordcount, int32_t desc_opt_loc, - unsigned int no_of_wrds_in_desc) + size_t wordcount, int32_t desc_opt_loc) { int32_t ret = -1; char *desc = NULL; - int32_t i = 0; int32_t desc_len = 0; desc = GF_CALLOC (MAX_SNAP_DESCRIPTION_LEN + 1, sizeof(char), @@ -2771,31 +2769,26 @@ cli_snap_create_desc_parse (dict_t *dict, const char **words, } /* Creating the description string */ - for (i = 0; i < no_of_wrds_in_desc; i++) { - if ((strcmp (words[desc_opt_loc + 1 + i], "-n") == 0) || - (strcmp (words[desc_opt_loc + 1 + i], "-d") == 0)) { - cli_out ("snapshot create: failed: Options(-n/-d) " - "are not valid descriptions"); - ret = -1; - goto out; - } - - strcat (desc, words[desc_opt_loc + 1 + i]); - strcat (desc, " "); - /* Calculating the size of the description as given by the user */ - desc_len += strlen(words[desc_opt_loc + 1 + i]); - desc_len++; + if ((strcmp (words[desc_opt_loc], "-n") == 0) || + (strcmp (words[desc_opt_loc], "-d") == 0)) { + cli_out ("snapshot create: failed: Options(-n/-d) " + "are not valid descriptions"); + ret = -1; + goto out; } - /* Removing the last space in the string */ - desc[--desc_len] = '\0'; - - if (desc_len > MAX_SNAP_DESCRIPTION_LEN) { + if (strlen (words[desc_opt_loc]) >= MAX_SNAP_DESCRIPTION_LEN) { cli_out ("snapshot create: description truncated: " "Description provided is longer than 1024 characters"); - desc[MAX_SNAP_DESCRIPTION_LEN] = '\0'; + desc_len = MAX_SNAP_DESCRIPTION_LEN; + } else { + desc_len = strlen (words[desc_opt_loc]); } + strncpy (desc, words[desc_opt_loc], desc_len); + desc[desc_len] = '\0'; + /* Calculating the size of the description as given by the user */ + ret = dict_set_dynstr (dict, "snap-description", desc); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to save snap description"); @@ -2804,11 +2797,8 @@ cli_snap_create_desc_parse (dict_t *dict, const char **words, ret = 0; out: - - if (ret) { - if (desc) - GF_FREE (desc); - } + if (ret && desc) + GF_FREE (desc); return ret; } @@ -2859,9 +2849,9 @@ cli_snap_create_parse (dict_t *dict, const char **words, int wordcount, /* Description should not be blank */ no_of_wrds_in_desc = (wordcount - 1) - desc_opt_loc; - if (no_of_wrds_in_desc == 0) { + if (no_of_wrds_in_desc != 1) { cli_out ("snapshot create: failed: " - "No description provided"); + "Invalid description"); ret = -1; goto out; } @@ -2882,9 +2872,9 @@ cli_snap_create_parse (dict_t *dict, const char **words, int wordcount, /* Description should not be blank */ no_of_wrds_in_desc = (wordcount - 1) - desc_opt_loc; - if (no_of_wrds_in_desc == 0) { + if (no_of_wrds_in_desc != 1) { cli_out ("snapshot create: failed: " - "No description provided"); + "Invalid description"); ret = -1; goto out; } @@ -2901,9 +2891,9 @@ cli_snap_create_parse (dict_t *dict, const char **words, int wordcount, /* Description should not be blank */ no_of_wrds_in_desc = (name_opt_loc) - desc_opt_loc -1; - if (no_of_wrds_in_desc == 0) { + if (no_of_wrds_in_desc != 1) { cli_out ("snapshot create: failed: " - "No description provided"); + "Invalid description"); ret = -1; goto out; } @@ -2977,10 +2967,14 @@ cli_snap_create_parse (dict_t *dict, const char **words, int wordcount, /* Parsing the description and saving it in the dict */ if (desc_opt_loc > cmdi + 1) { + /* desc_opt_loc contains the position of -d option + used to indicate description. So send directly + the position of the description (i.e desc_opt_loc + 1) + for parsing + */ ret = cli_snap_create_desc_parse (dict, words, wordcount, - desc_opt_loc, - no_of_wrds_in_desc); + desc_opt_loc + 1); if (ret) { gf_log ("", GF_LOG_ERROR, "Unable to parse snap-description"); @@ -3184,6 +3178,11 @@ out: return ret; } +/* function cli_snap_config_parse + return value: -1 on failure + 1 if user cancels the operation + 0 on success +*/ int32_t cli_snap_config_parse (const char **words, int wordcount, dict_t *options, struct cli_state *state) @@ -3297,7 +3296,9 @@ cli_snap_config_parse (const char **words, int wordcount, dict_t *options, answer = cli_cmd_get_confirmation (state, conf_vals->question); if (GF_ANSWER_NO == answer) { - ret = -1; + ret = 1; + gf_log ("", GF_LOG_DEBUG, "User cancelled " + "snapshot config operation"); goto out; } } @@ -3312,15 +3313,23 @@ out: also should be given in the command. If cg should be removed, then volume name is not necessary. "gluster snapshot delete (<volname> -s <snapname> | -c <cgname>)" + return value: -1 on failure + 1 if user cancels the operation + 0 on success */ int32_t cli_snap_remove_parse (dict_t *dict, const char **words, int wordcount, - unsigned int cmdi) + unsigned int cmdi, struct cli_state *state) { uint32_t name_opt_loc = 0; int32_t ret = -1; uint32_t i = 0; gf_boolean_t is_cg = _gf_false; + const char *question = NULL; + gf_answer_t answer = GF_ANSWER_NO; + + question = "Deleting snap will erase all information about the snap. " + "Do you want to continue?"; GF_ASSERT (dict); GF_ASSERT (words); @@ -3395,6 +3404,14 @@ cli_snap_remove_parse (dict_t *dict, const char **words, int wordcount, } } + answer = cli_cmd_get_confirmation (state, question); + if (GF_ANSWER_NO == answer) { + ret = 1; + gf_log ("", GF_LOG_DEBUG, "User cancelled " + "snapshot delete operation"); + goto out; + } + out: return ret; } @@ -3613,10 +3630,11 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, cmdi = 2; ret = cli_snap_remove_parse (dict, words, - wordcount, cmdi); + wordcount, cmdi, state); if (ret) { - gf_log ("", GF_LOG_ERROR, - "remove command parsing failed."); + if (ret < 0) + gf_log ("", GF_LOG_ERROR, + "remove command parsing failed."); goto out; } break; @@ -3628,8 +3646,9 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, ret = cli_snap_config_parse (words, wordcount, dict, state); if (ret) { - gf_log ("cli", GF_LOG_ERROR, - "config command parsing failed."); + if (ret < 0) + gf_log ("cli", GF_LOG_ERROR, + "config command parsing failed."); goto out; } break; diff --git a/cli/src/cli-cmd-snapshot.c b/cli/src/cli-cmd-snapshot.c index 6d31dc2d5..f16e68dd6 100644 --- a/cli/src/cli-cmd-snapshot.c +++ b/cli/src/cli-cmd-snapshot.c @@ -53,8 +53,14 @@ cli_cmd_snapshot_cbk (struct cli_state *state, struct cli_cmd_word *word, /* Parses the command entered by the user */ ret = cli_cmd_snapshot_parse (words, wordcount, &options, state); if (ret) { - cli_usage_out (word->pattern); - parse_err = 1; + if (ret < 0) { + cli_usage_out (word->pattern); + parse_err = 1; + } + else { + /* User might have cancelled the snapshot operation */ + ret = 0; + } goto out; } diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 648ab6d65..e9c24fe21 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -7560,22 +7560,25 @@ list_snap_of_volume (dict_t *dict_n, char *prefix_str) { if (ret < 0) { goto out; } + ret = dict_get_str (dict_n, buffer, &get_buffer); if (ret == 0) { cli_out ("%s",get_buffer); ret = 0; goto out; } + ret = snprintf (buffer, sizeof(buffer), "%s.volname", prefix_str); if (ret < 0) { /* Negative value is an error */ goto out; } + ret = dict_get_str (dict_n, buffer, &get_buffer); if (get_buffer == NULL){ ret = 0; goto out; } - cli_out ("\nVolume Name : %s", get_buffer); + cli_out ("\n%-28s %s %s", "Volume Name", ":", get_buffer); /* if Volume is present then get the snapcount. * string is "snaplist.vol{0..}.snap-count. */ @@ -7584,6 +7587,7 @@ list_snap_of_volume (dict_t *dict_n, char *prefix_str) { if (ret < 0) { /* Negative value is an error */ goto out; } + ret = dict_get_uint64 (dict_n, buffer, &snapcount); if (ret) { gf_log("", GF_LOG_ERROR, "Could not fetch snapcount"); @@ -7610,9 +7614,11 @@ list_snap_of_volume (dict_t *dict_n, char *prefix_str) { if (ret < 0) { goto out; } + ret = dict_get_uint64 (dict_n, buffer, &snapcount_total); if (!ret) - cli_out ("Number of snaps taken : %ld", snapcount_total); + cli_out ("%-28s %s %ld", "Number of snaps taken", ":", + snapcount_total); else gf_log ("", GF_LOG_ERROR, "Failed to get snapcount total"); @@ -7621,13 +7627,15 @@ list_snap_of_volume (dict_t *dict_n, char *prefix_str) { if (ret < 0) { goto out; } + ret = dict_get_uint64 (dict_n, buffer, &snap_available); if (!ret) - cli_out ("Number of snaps available : %ld", - snap_available); + cli_out ("%-28s %s %ld", "Number of snaps available", + ":", snap_available); else gf_log ("", GF_LOG_ERROR, "Failed to get snap-available"); + for (i = 0 ; i < snapcount; i++) { /* get snapname "snaplist.vol-{0..}.snap-{0..}.snapname" */ ret = snprintf (buffer, sizeof(buffer), @@ -7635,22 +7643,28 @@ list_snap_of_volume (dict_t *dict_n, char *prefix_str) { if (ret < 0) { /* Negative value is an error */ goto out; } + ret = dict_get_str (dict_n, buffer, &get_buffer); if (!ret) - cli_out ("\n\tSnap Name : %s",get_buffer); + cli_out ("\n\t%-17s %s %s", "Snap Name", ":", + get_buffer); else - cli_out ("\n\tSnap Name : %s","Does not exist"); + cli_out ("\n\t%-17s %s %s", "Snap Name", ":", + "Does not exist"); ret = snprintf (buffer, sizeof(buffer), "%s.snap-%ld.snap-time", prefix_str, i); if (ret < 0) { /* Negative value is an error */ goto out; } + ret = dict_get_str (dict_n, buffer, &get_buffer); if (!ret) - cli_out ("\tSnap Time : %s",get_buffer); + cli_out ("\t%-17s %s %s", "Snap Time", ":", + get_buffer); else - cli_out ("\tSnap Time : %s","Does not exist"); + cli_out ("\t%-17s %s %s", "Snap Time", ":", + "Does not exist"); ret = snprintf (buffer, sizeof(buffer), "%s.snap-%ld.snap-id" @@ -7658,11 +7672,14 @@ list_snap_of_volume (dict_t *dict_n, char *prefix_str) { if (ret < 0) { /* Negative value is an error */ goto out; } + ret = dict_get_str (dict_n, buffer, &get_buffer); if (!ret) - cli_out("\tSnap ID : %s",get_buffer); + cli_out("\t%-17s %s %s", "Snap UUID", ":", + get_buffer); else - cli_out("\tSnap ID : %s","Does not exist"); + cli_out("\t%-17s %s %s", "Snap UUID", ":", + "Does not exist"); if(detail == 0) { /* if snap_details is set to zero @@ -7675,45 +7692,56 @@ list_snap_of_volume (dict_t *dict_n, char *prefix_str) { if (ret < 0) { /* Negative value is an error */ goto out; } + ret = dict_get_str (dict_n, buffer, &get_buffer); if (!ret) - cli_out("\tCG Name : %s",get_buffer); + cli_out("\t%-17s %s %s", "CG Name", ":", + get_buffer); else - cli_out("\tCG Name : %s","Does not exist"); + cli_out("\t%-17s %s %s","CG Name", ":", + "Does not exist"); ret = snprintf (buffer, sizeof(buffer), "%s.snap-%ld.cg-id", prefix_str, i); if (ret < 0) { /* Negative value is an error */ goto out; } + ret = dict_get_str (dict_n, buffer, &get_buffer); if (!ret) - cli_out("\tCG ID : %s",get_buffer); + cli_out("\t%-17s %s %s", "CG ID", ":", + get_buffer); else - cli_out("\tCG ID : %s","Does not exist"); + cli_out("\t%-17s %s %s", "CG ID", ":", + "Does not exist"); ret = snprintf (buffer, sizeof(buffer), "%s.snap-%ld.snap-desc", prefix_str, i); if (ret < 0) { /* Negative value is an error */ goto out; } + ret = dict_get_str (dict_n, buffer, &get_buffer); if (!ret) - cli_out ("\tSnap Description : %s",get_buffer); + cli_out ("\t%-17s %s %s", "Snap Description", ":", + get_buffer); else - cli_out ("\tSnap Description : %s", - "Description not present"); + cli_out ("\t%-17s %s %s", "Snap Description", ":", + "Description not present"); ret = snprintf (buffer, sizeof(buffer), "%s.snap-%ld.snap-status", prefix_str, i); if (ret < 0) { /* Negative value is an error */ goto out; } + ret = dict_get_str (dict_n, buffer, &get_buffer); if (!ret) - cli_out ("\tSnap Status : %s",get_buffer); + cli_out ("\t%-17s %s %s", "Snap Status", ":", + get_buffer); else - cli_out ("\tSnap Status : %s","Does not exist"); + cli_out ("\t%-17s %s %s", "Snap Status", ":", + "Does not exist"); ret = 0; } @@ -8117,9 +8145,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-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index bea5540e4..dbf342cbc 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handshake.c +++ b/xlators/mgmt/glusterd/src/glusterd-handshake.c @@ -93,7 +93,11 @@ build_volfile_path (const char *volname, char *path, vol = strtok_r (dup_volname, ".", &tmp); if (!vol) goto out; - ret = glusterd_volinfo_find (vol, &volinfo); + if (!snap_volume) + ret = glusterd_volinfo_find (vol, &volinfo); + else + ret = glusterd_snap_volinfo_find (vol, + &volinfo); if (ret) goto out; } 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 1f6930718..8d7c33d43 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); @@ -2695,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; @@ -2724,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){ @@ -3047,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 = ""; @@ -3191,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", @@ -3216,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", @@ -3225,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", @@ -3234,7 +3146,7 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *snapname, dict_t *dict, } //check whether this is needed or not - list_add_tail (&snap_volume->vol_list, &priv->volumes); + list_add_tail (&snap_volume->vol_list, &priv->snap_list); list_for_each_entry (brickinfo, &snap_volume->bricks, brick_list) { if (uuid_compare (brickinfo->uuid, MY_UUID)) @@ -3399,7 +3311,7 @@ glusterd_handle_snapshot_remove (rpcsvc_request_t *req, glusterd_op_t op, cg = glusterd_find_snap_cg_by_name (conf, cgname); if (NULL == cg) { - snprintf (err_str, len, "CG %s not found", cgname); + snprintf (err_str, len, "CG %s does not exist", cgname); gf_log (this->name, GF_LOG_WARNING, "%s", err_str); ret = -1; goto out; @@ -3486,7 +3398,7 @@ glusterd_snapshot_remove_prevalidate (dict_t *dict, char **op_errstr, cg = glusterd_find_snap_cg_by_name (conf, name); if (!cg) { snprintf (err_str, sizeof (err_str), "consistency group" - "%s is not found", name); + "%s does not exist", name); gf_log (this->name, GF_LOG_ERROR, "%s", err_str); *op_errstr = gf_strdup (err_str); goto out; @@ -3527,9 +3439,10 @@ glusterd_snapshot_remove_prevalidate (dict_t *dict, char **op_errstr, } ret = glusterd_volinfo_find (volname, &volinfo); if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "failed to get the volinfo for " - "the volume %s", volname); + snprintf (err_str, sizeof (err_str), "Volume %s does " + "not exist", volname); + gf_log (this->name, GF_LOG_ERROR, "%s", err_str); + *op_errstr = gf_strdup (err_str); goto out; } ret = dict_get_str (dict, "snapname", &name); @@ -3541,8 +3454,8 @@ glusterd_snapshot_remove_prevalidate (dict_t *dict, char **op_errstr, snap = glusterd_find_snap_by_name (volinfo, name); if (!snap) { ret = -1; - snprintf (err_str, sizeof (err_str), "snap %s is not " - "found", name); + snprintf (err_str, sizeof (err_str), "snap %s does " + "not exist", name); gf_log (this->name, GF_LOG_ERROR, "%s, (volume: %s)", err_str, volinfo->volname); *op_errstr = gf_strdup (err_str); @@ -3999,13 +3912,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) @@ -4080,11 +4020,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 " @@ -4612,7 +4552,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 1a00aac88..16cafdc8e 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.c +++ b/xlators/mgmt/glusterd/src/glusterd-store.c @@ -607,14 +607,13 @@ int _storeopts (dict_t *this, char *key, data_t *value, void *data) int32_t glusterd_volume_exclude_options_write (int fd, glusterd_volinfo_t *volinfo) { - char *str = NULL; + char *str = NULL; + char buf[PATH_MAX] = {0,}; + int32_t ret = -1; GF_ASSERT (fd > 0); GF_ASSERT (volinfo); - char buf[PATH_MAX] = {0,}; - int32_t ret = -1; - snprintf (buf, sizeof (buf), "%d", volinfo->type); ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_VOL_TYPE, buf); if (ret) @@ -703,6 +702,14 @@ glusterd_volume_exclude_options_write (int fd, glusterd_volinfo_t *volinfo) goto out; } + snprintf (buf, sizeof (buf), "%d", volinfo->is_volume_restored); + ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_VOL_IS_RESTORED, buf); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Unable to write is_volume_restored"); + goto out; + } + snprintf (buf, sizeof (buf), "%"PRIu64, volinfo->snap_max_hard_limit); ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT, buf); @@ -1222,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)); @@ -1242,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); @@ -1287,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) @@ -1373,9 +1390,9 @@ glusterd_store_perform_snap_volume_store (glusterd_volinfo_t *volinfo, if (ret) goto out; - ret = gf_store_rename_tmppath (snap_volinfo->shandle); - if (ret) - goto out; + ret = gf_store_rename_tmppath (snap_volinfo->shandle); + if (ret) + goto out; out: if (ret && (fd > 0)) gf_store_unlink_tmppath (volinfo->shandle); @@ -1509,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); @@ -2670,53 +2693,65 @@ 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; + 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); @@ -2791,6 +2826,9 @@ glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap) } else if (!strncmp (key, GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT, strlen (GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT))) { volinfo->snap_max_hard_limit = (uint64_t) atoll (value); + } else if (!strncmp (key, GLUSTERD_STORE_KEY_VOL_IS_RESTORED, + strlen (GLUSTERD_STORE_KEY_VOL_IS_RESTORED))) { + volinfo->is_volume_restored = atoi (value); } else if (!strncmp (key, GLUSTERD_STORE_KEY_PARENT_VOLNAME, strlen (GLUSTERD_STORE_KEY_PARENT_VOLNAME))) { strncpy (volinfo->parent_volname, value, sizeof(volinfo->parent_volname) - 1); @@ -2881,10 +2919,58 @@ 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); + strncpy (volinfo->parent_volname, volname, GLUSTERD_MAX_VOLUME_NAME); + } 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 @@ -2906,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->snap_list); } out: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + gf_log ("", GF_LOG_TRACE, "Returning with %d", ret); return ret; } @@ -3070,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); @@ -3136,7 +3222,6 @@ glusterd_store_retrieve_snap_list (char *volname) gf_store_handle_t *shandle = NULL; priv = THIS->private; - ret = glusterd_volinfo_find (volname, &volinfo); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Couldn't get" @@ -3215,11 +3300,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..b8123f644 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.h +++ b/xlators/mgmt/glusterd/src/glusterd-store.h @@ -35,54 +35,56 @@ 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_CG_NAME "cg-name" +#define GLUSTERD_STORE_KEY_SNAP_DESC "desc" +#define GLUSTERD_STORE_KEY_SNAP_TIMESTAMP "time-stamp" +#define GLUSTERD_STORE_KEY_SNAP_STATUS "status" +#define GLUSTERD_STORE_KEY_SNAP_COUNT "count" +#define GLUSTERD_STORE_KEY_CG_VOL_COUNT "count" +#define GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT "snap-max-hard-limit" +#define GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT "snap-max-soft-limit" + +#define GLUSTERD_STORE_KEY_BRICK_HOSTNAME "hostname" +#define GLUSTERD_STORE_KEY_BRICK_PATH "path" +#define GLUSTERD_STORE_KEY_BRICK_PORT "listen-port" +#define GLUSTERD_STORE_KEY_BRICK_RDMA_PORT "rdma.listen-port" #define GLUSTERD_STORE_KEY_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 +141,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 6e8ef080c..d223fabb3 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -1155,7 +1155,6 @@ glusterd_volinfo_find (char *volname, glusterd_volinfo_t **volinfo) glusterd_conf_t *priv = NULL; GF_ASSERT (volname); - this = THIS; GF_ASSERT (this); @@ -1164,7 +1163,38 @@ glusterd_volinfo_find (char *volname, glusterd_volinfo_t **volinfo) list_for_each_entry (tmp_volinfo, &priv->volumes, vol_list) { if (!strcmp (tmp_volinfo->volname, volname)) { - gf_log (this->name, GF_LOG_DEBUG, "Volume %s found", volname); + gf_log (this->name, GF_LOG_DEBUG, "Volume %s found", + volname); + ret = 0; + *volinfo = tmp_volinfo; + break; + } + } + + gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int32_t +glusterd_snap_volinfo_find (char *volname, glusterd_volinfo_t **volinfo) +{ + glusterd_volinfo_t *tmp_volinfo = NULL; + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (volname); + gf_log ("", GF_LOG_DEBUG, "Snap Volname = %s", volname); + this = THIS; + GF_ASSERT (this); + + priv = this->private; + GF_ASSERT (priv); + + list_for_each_entry (tmp_volinfo, &priv->snap_list, vol_list) { + if (!strcmp (tmp_volinfo->volname, volname)) { + gf_log (this->name, GF_LOG_DEBUG, "Snap Volume %s found", + volname); ret = 0; *volinfo = tmp_volinfo; break; @@ -1542,7 +1572,7 @@ glusterd_snap_volume_start_glusterfs (glusterd_volinfo_t *volinfo, glusterd_set_socket_filepath (sock_filepath, socketpath, sizeof (socketpath)); - GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo, + GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo->volname, snap_volinfo->volname, brickinfo, priv); if (glusterd_is_service_running (pidfile, NULL)) @@ -1760,10 +1790,10 @@ glusterd_volume_stop_glusterfs (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo, gf_boolean_t del_brick) { - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - char pidfile[PATH_MAX] = {0,}; - int ret = 0; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + char pidfile[PATH_MAX] = {0,}; + int ret = 0; GF_ASSERT (volinfo); GF_ASSERT (brickinfo); @@ -1816,7 +1846,7 @@ glusterd_snap_volume_stop_glusterfs (glusterd_volinfo_t *volinfo, if (GLUSTERD_STATUS_STARTED == volinfo->status) { (void) glusterd_brick_disconnect (brickinfo); - GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo, + GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo->volname, snap_volinfo->volname, brickinfo, priv); ret = glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_false); @@ -2159,6 +2189,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); @@ -2213,6 +2252,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; @@ -2987,6 +3040,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); @@ -2998,6 +3052,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; @@ -3123,6 +3193,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); @@ -3405,6 +3491,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); @@ -5138,7 +5230,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; @@ -5173,11 +5264,10 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, if (volinfo->is_snap_volume == _gf_true) { /* Fetching the snap pidfile using parent volname */ - GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path); - snprintf (pidfile, sizeof(pidfile) - 1, - "%s/vols/%s/snaps/%s/run/%s-%s.pid", priv->workdir, - volinfo->parent_volname, volinfo->volname, - brickinfo->hostname, exp_path); + GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, + volinfo->parent_volname, + volinfo->volname, + brickinfo, priv); } else GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo, brickinfo, priv); diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 4c98559c9..e1e595669 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -119,6 +119,9 @@ int32_t glusterd_peer_hostname_new (char *hostname, glusterd_peer_hostname_t **name); int32_t +glusterd_snap_volinfo_find (char *volname, glusterd_volinfo_t **volinfo); + +int32_t glusterd_volinfo_find (char *volname, glusterd_volinfo_t **volinfo); int 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.c b/xlators/mgmt/glusterd/src/glusterd.c index 8b97a4e26..42fd8a725 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -1315,6 +1315,7 @@ init (xlator_t *this) INIT_LIST_HEAD (&conf->peers); INIT_LIST_HEAD (&conf->volumes); INIT_LIST_HEAD (&conf->snap_cg); + INIT_LIST_HEAD (&conf->snap_list); pthread_mutex_init (&conf->mutex, NULL); conf->rpc = rpc; diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index f14b6737b..b8f048817 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -139,6 +139,7 @@ typedef struct { nodesrv_t *nfs; struct pmap_registry *pmap; struct list_head volumes; + struct list_head snap_list; /*List of snap volumes */ pthread_mutex_t xprt_lock; struct list_head xprt_list; gf_store_handle_t *handle; @@ -278,6 +279,7 @@ struct glusterd_volinfo_ { gf_lock_t lock; char volname[GLUSTERD_MAX_VOLUME_NAME]; gf_boolean_t is_snap_volume; + gf_boolean_t is_volume_restored; char parent_volname[GLUSTERD_MAX_VOLUME_NAME]; /* In case of a snap volume i.e (is_snap_volume == TRUE) this @@ -485,14 +487,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) { \ |