summaryrefslogtreecommitdiffstats
path: root/cli
diff options
context:
space:
mode:
authorAmar Tumballi <amar@gluster.com>2011-09-26 17:42:40 +0530
committerVijay Bellur <vijay@gluster.com>2011-09-27 05:37:59 -0700
commitea71efe027e9f741032b6bf9dd995bcaa2fa7947 (patch)
tree0cc90449ee5bb0331b52da83c6f99b31587fe9cf /cli
parent0286dd866a89c035073294c348a43beca3109c38 (diff)
cluster/distribute: fixed a spurious inode ref
While bringing in support to open-fd migration, dht_local_init() itself started doing 'loc_copy()'. I had left one case in dht_lookup() where there is a extra loc_copy() on existing copied 'local->loc', which would cause 2 inode_refs on a given inode, and only one inode_unref() happens in dht_local_wipe(). Change-Id: Idd0375bdf9a6408db1e97e80389249ef8d802adb BUG: 3590 Reviewed-on: http://review.gluster.com/504 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Shishir Gowda <shishirng@gluster.com>
Diffstat (limited to 'cli')
0 files changed, 0 insertions, 0 deletions
if (!frame) goto out; dict = dict_new(); if (!dict) goto out; if (wordcount != 3) { cli_usage_out(word->pattern); parse_error = 1; goto out; } volname = (char *)words[2]; ret = dict_set_str(dict, "volname", volname); if (ret) { gf_log(THIS->name, GF_LOG_WARNING, "dict set failed"); goto out; } if (!strcmp(volname, GLUSTER_SHARED_STORAGE)) { question = "Deleting the shared storage volume" "(gluster_shared_storage), will affect features " "like snapshot scheduler, geo-replication " "and NFS-Ganesha. Do you still want to " "continue?"; } answer = cli_cmd_get_confirmation(state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } CLI_LOCAL_INIT(local, words, frame, dict); if (proc->fn) { ret = proc->fn(frame, THIS, dict); } out: if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("Volume delete failed"); } CLI_STACK_DESTROY(frame); if (ret == 0 && GF_ANSWER_YES == answer) { gf_event(EVENT_VOLUME_DELETE, "name=%s", (char *)words[2]); } return ret; } int cli_cmd_volume_start_cbk(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; int sent = 0; int parse_error = 0; dict_t *dict = NULL; int flags = 0; cli_local_t *local = NULL; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) goto out; if (wordcount < 3 || wordcount > 4) { cli_usage_out(word->pattern); parse_error = 1; goto out; } dict = dict_new(); if (!dict) { goto out; } if (!words[2]) goto out; ret = dict_set_str(dict, "volname", (char *)words[2]); if (ret) { gf_log(THIS->name, GF_LOG_ERROR, "dict set failed"); goto out; } if (wordcount == 4) { if (!strcmp("force", words[3])) { flags |= GF_CLI_FLAG_OP_FORCE; } else { ret = -1; cli_usage_out(word->pattern); parse_error = 1; goto out; } } ret = dict_set_int32(dict, "flags", flags); if (ret) { gf_log(THIS->name, GF_LOG_ERROR, "dict set failed"); goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_START_VOLUME]; CLI_LOCAL_INIT(local, words, frame, dict); if (proc->fn) { ret = proc->fn(frame, THIS, dict); } out: if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("Volume start failed"); } CLI_STACK_DESTROY(frame); if (ret == 0) { gf_event(EVENT_VOLUME_START, "name=%s;force=%d", (char *)words[2], (flags & GF_CLI_FLAG_OP_FORCE)); } return ret; } gf_answer_t cli_cmd_get_confirmation(struct cli_state *state, const char *question) { char answer[5] = { '\0', }; int flush = '\0'; size_t len; if (state->mode & GLUSTER_MODE_SCRIPT) return GF_ANSWER_YES; printf("%s (y/n) ", question); if (fgets(answer, 4, stdin) == NULL) { cli_out("gluster cli read error"); goto out; } len = strlen(answer); if (len && answer[len - 1] == '\n') { answer[--len] = '\0'; } else { do { flush = getchar(); } while (flush != '\n'); } if (len > 3) goto out; if (!strcasecmp(answer, "y") || !strcasecmp(answer, "yes")) return GF_ANSWER_YES; else if (!strcasecmp(answer, "n") || !strcasecmp(answer, "no")) return GF_ANSWER_NO; out: cli_out("Invalid input, please enter y/n"); return GF_ANSWER_NO; } int cli_cmd_volume_stop_cbk(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; int flags = 0; gf_answer_t answer = GF_ANSWER_NO; int sent = 0; int parse_error = 0; dict_t *dict = NULL; char *volname = NULL; cli_local_t *local = NULL; const char *question = "Stopping volume will make its data inaccessible. " "Do you want to continue?"; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) goto out; if (wordcount < 3 || wordcount > 4) { cli_usage_out(word->pattern); parse_error = 1; goto out; } volname = (char *)words[2]; dict = dict_new(); ret = dict_set_str(dict, "volname", volname); if (ret) { gf_log(THIS->name, GF_LOG_ERROR, "dict set failed"); goto out; } if (!strcmp(volname, GLUSTER_SHARED_STORAGE)) { question = "Stopping the shared storage volume" "(gluster_shared_storage), will affect features " "like snapshot scheduler, geo-replication " "and NFS-Ganesha. Do you still want to " "continue?"; } if (wordcount == 4) { if (!strcmp("force", words[3])) { flags |= GF_CLI_FLAG_OP_FORCE; } else { ret = -1; cli_usage_out(word->pattern); parse_error = 1; goto out; } } ret = dict_set_int32(dict, "flags", flags); if (ret) { gf_log(THIS->name, GF_LOG_ERROR, "dict set failed"); goto out; } answer = cli_cmd_get_confirmation(state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STOP_VOLUME]; CLI_LOCAL_INIT(local, words, frame, dict); if (proc->fn) { ret = proc->fn(frame, THIS, dict); } out: if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("Volume stop on '%s' failed", volname); } CLI_STACK_DESTROY(frame); if (dict) dict_unref(dict); if (ret == 0 && GF_ANSWER_YES == answer) { gf_event(EVENT_VOLUME_STOP, "name=%s;force=%d", (char *)words[2], (flags & GF_CLI_FLAG_OP_FORCE)); } return ret; } int cli_cmd_volume_rename_cbk(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *dict = NULL; int sent = 0; int parse_error = 0; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) goto out; dict = dict_new(); if (!dict) goto out; if (wordcount != 4) { cli_usage_out(word->pattern); parse_error = 1; goto out; } ret = dict_set_str(dict, "old-volname", (char *)words[2]); if (ret) goto out; ret = dict_set_str(dict, "new-volname", (char *)words[3]); if (ret) goto out; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_RENAME_VOLUME]; if (proc->fn) { ret = proc->fn(frame, THIS, dict); } out: if (dict) dict_unref(dict); if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("Volume rename on '%s' failed", (char *)words[2]); } CLI_STACK_DESTROY(frame); return ret; } int cli_cmd_volume_defrag_cbk(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *dict = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; #if (USE_EVENTS) eventtypes_t event = EVENT_LAST; #endif #ifdef GF_SOLARIS_HOST_OS cli_out("Command not supported on Solaris"); goto out; #endif frame = create_frame(THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_defrag_parse(words, wordcount, &dict); if (ret) { cli_usage_out(word->pattern); parse_error = 1; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_DEFRAG_VOLUME]; CLI_LOCAL_INIT(local, words, frame, dict); if (proc->fn) { ret = proc->fn(frame, THIS, dict); } out: if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("Volume rebalance failed"); } else { #if (USE_EVENTS) if (!(strcmp(words[wordcount - 1], "start")) || !(strcmp(words[wordcount - 1], "force"))) { event = EVENT_VOLUME_REBALANCE_START; } else if (!strcmp(words[wordcount - 1], "stop")) { event = EVENT_VOLUME_REBALANCE_STOP; } if (event != EVENT_LAST) gf_event(event, "volume=%s", (char *)words[2]); #endif } CLI_STACK_DESTROY(frame); return ret; } int cli_cmd_volume_reset_cbk(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int sent = 0; int parse_error = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; cli_local_t *local = NULL; #if (USE_EVENTS) int ret1 = -1; char *tmp_opt = NULL; #endif proc = &cli_rpc_prog->proctable[GLUSTER_CLI_RESET_VOLUME]; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_reset_parse(words, wordcount, &options); if (ret) { cli_usage_out(word->pattern); parse_error = 1; goto out; } CLI_LOCAL_INIT(local, words, frame, options); if (proc->fn) { ret = proc->fn(frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("Volume reset failed"); } #if (USE_EVENTS) if (ret == 0) { ret1 = dict_get_str(options, "key", &tmp_opt); if (ret1) tmp_opt = ""; gf_event(EVENT_VOLUME_RESET, "name=%s;option=%s", (char *)words[2], tmp_opt); } #endif CLI_STACK_DESTROY(frame); return ret; } int cli_cmd_volume_profile_cbk(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int sent = 0; int parse_error = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; cli_local_t *local = NULL; ret = cli_cmd_volume_profile_parse(words, wordcount, &options); if (ret) { cli_usage_out(word->pattern); parse_error = 1; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_PROFILE_VOLUME]; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) { gf_log(THIS->name, GF_LOG_ERROR, "failed to create frame"); ret = -1; goto out; } CLI_LOCAL_INIT(local, words, frame, options); if (proc->fn) { ret = proc->fn(frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("Volume profile failed"); } CLI_STACK_DESTROY(frame); return ret; } int cli_cmd_volume_set_cbk(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int sent = 0; int parse_error = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; cli_local_t *local = NULL; char *op_errstr = NULL; #if (USE_EVENTS) int ret1 = -1; int i = 1; char dict_key[50] = { 0, }; char *tmp_opt = NULL; char *opts_str = NULL; int num_options = 0; #endif proc = &cli_rpc_prog->proctable[GLUSTER_CLI_SET_VOLUME]; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_set_parse(state, words, wordcount, &options, &op_errstr); if (ret) { if (op_errstr) { cli_err("%s", op_errstr); GF_FREE(op_errstr); } else cli_usage_out(word->pattern); parse_error = 1; goto out; } CLI_LOCAL_INIT(local, words, frame, options); if (proc->fn) { ret = proc->fn(frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("Volume set failed"); } #if (USE_EVENTS) if (ret == 0 && strcmp(words[2], "help") != 0) { ret1 = dict_get_int32(options, "count", &num_options); if (ret1) { num_options = 0; goto end; } else { num_options = num_options / 2; } char *free_list_key[num_options]; char *free_list_val[num_options]; for (i = 0; i < num_options; i++) { free_list_key[i] = NULL; free_list_val[i] = NULL; } /* Initialize opts_str */ opts_str = ""; /* Prepare String in format options=KEY1,VALUE1,KEY2,VALUE2 */ for (i = 1; i <= num_options; i++) { sprintf(dict_key, "key%d", i); ret1 = dict_get_str(options, dict_key, &tmp_opt); if (ret1) tmp_opt = ""; gf_asprintf(&opts_str, "%s,%s", opts_str, tmp_opt); free_list_key[i - 1] = opts_str; sprintf(dict_key, "value%d", i); ret1 = dict_get_str(options, dict_key, &tmp_opt); if (ret1) tmp_opt = ""; gf_asprintf(&opts_str, "%s,%s", opts_str, tmp_opt); free_list_val[i - 1] = opts_str; } gf_event(EVENT_VOLUME_SET, "name=%s;options=%s", (char *)words[2], opts_str); /* Allocated by gf_strdup and gf_asprintf */ for (i = 0; i < num_options; i++) { GF_FREE(free_list_key[i]); GF_FREE(free_list_val[i]); } } #endif end: CLI_STACK_DESTROY(frame); return ret; } static int cli_event_remove_brick_str(dict_t *options, char **event_str, eventtypes_t *event) { int ret = -1; char *bricklist = NULL; char *brick = NULL; char *volname = NULL; char key[256] = { 0, }; const char *eventstrformat = "volume=%s;bricks=%s"; int32_t command = 0; int32_t i = 1; int32_t count = 0; int32_t eventstrlen = 1; int bricklen = 0; char *tmp_ptr = NULL; if (!options || !event_str || !event) goto out; ret = dict_get_str(options, "volname", &volname); if (ret || !volname) { gf_log("cli", GF_LOG_ERROR, "Failed to fetch volname"); ret = -1; goto out; } /* Get the list of bricks for the event */ ret = dict_get_int32(options, "command", &command); if (ret) { gf_log("cli", GF_LOG_ERROR, "Failed to fetch command"); ret = -1; goto out; } switch (command) { case GF_OP_CMD_START: *event = EVENT_VOLUME_REMOVE_BRICK_START; break; case GF_OP_CMD_COMMIT: *event = EVENT_VOLUME_REMOVE_BRICK_COMMIT; break; case GF_OP_CMD_COMMIT_FORCE: *event = EVENT_VOLUME_REMOVE_BRICK_FORCE; break; case GF_OP_CMD_STOP: *event = EVENT_VOLUME_REMOVE_BRICK_STOP; break; default: *event = EVENT_LAST; break; } ret = -1; if (*event == EVENT_LAST) { goto out; } /* I could just get this from words[] but this is cleaner in case the * format changes */ while (i) { snprintf(key, sizeof(key), "brick%d", i); ret = dict_get_str(options, key, &brick); if (ret) { break; } eventstrlen += strlen(brick) + 1; i++; } count = --i; eventstrlen += 1; bricklist = GF_CALLOC(eventstrlen, sizeof(char), gf_common_mt_char); if (!bricklist) { gf_log(THIS->name, GF_LOG_ERROR, "memory allocation failed for" "bricklist"); ret = -1; goto out; } tmp_ptr = bricklist; i = 1; while (i <= count) { snprintf(key, sizeof(key), "brick%d", i); ret = dict_get_str(options, key, &brick); if (ret) { break; } snprintf(tmp_ptr, eventstrlen, "%s ", brick); bricklen = strlen(brick); eventstrlen -= (bricklen + 1); tmp_ptr += (bricklen + 1); i++; } if (!ret) { gf_asprintf(event_str, eventstrformat, volname, bricklist); } else { gf_asprintf(event_str, eventstrformat, volname, ""); } ret = 0; out: GF_FREE(bricklist); return ret; } int cli_cmd_volume_add_brick_cbk(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; gf_answer_t answer = GF_ANSWER_NO; cli_local_t *local = NULL; #if (USE_EVENTS) char *event_str = NULL; char *bricks = NULL; const char *eventstrformat = "volume=%s;bricks=%s"; #endif const char *question = "Changing the 'stripe count' of the volume is " "not a supported feature. In some cases it may result in data " "loss on the volume. Also there may be issues with regular " "filesystem operations on the volume after the change. Do you " "really want to continue with 'stripe' count option ? "; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_add_brick_parse(state, words, wordcount, &options, 0); if (ret) { cli_usage_out(word->pattern); parse_error = 1; goto out; } /* TODO: there are challenges in supporting changing of stripe-count, until it is properly supported give warning to user */ if (dict_get(options, "stripe-count")) { answer = cli_cmd_get_confirmation(state, question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } } #if (USE_EVENTS) /* Get the list of bricks for the event */ ret = dict_get_str(options, "bricks", &bricks); if (!ret) { gf_asprintf(&event_str, eventstrformat, (char *)words[2], &bricks[1] /*Skip leading space*/); } else { gf_asprintf(&event_str, eventstrformat, (char *)words[2], ""); } #endif if (state->mode & GLUSTER_MODE_WIGNORE) { ret = dict_set_int32(options, "force", _gf_true); if (ret) { gf_log("cli", GF_LOG_ERROR, "Failed to set force " "option"); goto out; } } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_ADD_BRICK]; CLI_LOCAL_INIT(local, words, frame, options); if (proc->fn) { ret = proc->fn(frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("Volume add-brick failed"); } else { #if (USE_EVENTS) gf_event(EVENT_VOLUME_ADD_BRICK, "%s", event_str); #endif } #if (USE_EVENTS) GF_FREE(event_str); #endif CLI_STACK_DESTROY(frame); return ret; } int cli_tier_validate_replica_type(dict_t *dict, int type) { int brick_count = -1; int replica_count = 1; int ret = -1; ret = dict_get_int32(dict, "count", &brick_count); if (ret) { gf_log("cli", GF_LOG_ERROR, "Failed to get brick count"); goto out; } ret = dict_get_int32(dict, "replica-count", &replica_count); if (ret) { gf_log("cli", GF_LOG_DEBUG, "Failed to get replica count. " "Defaulting to one"); replica_count = 1; } /* * Change the calculation of sub_count once attach-tier support * disperse volume. * sub_count = disperse_count for disperse volume * */ if (brick_count % replica_count) { if (type == GF_CLUSTER_TYPE_REPLICATE) cli_err( "number of bricks is not a multiple of " "replica count"); else if (type == GF_CLUSTER_TYPE_DISPERSE) cli_err( "number of bricks is not a multiple of " "disperse count"); else cli_err( "number of bricks given doesn't match " "required count"); ret = -1; goto out; } ret = 0; out: return ret; } int do_cli_cmd_volume_attach_tier(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; cli_local_t *local = NULL; int type = 0; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_add_brick_parse(state, words, wordcount, &options, &type); if (ret) { cli_usage_out(word->pattern); parse_error = 1; goto out; } /* * Merge this check when attach-tier has it's own cli parse function. */ ret = cli_tier_validate_replica_type(options, type); if (ret) { cli_usage_out(word->pattern); parse_error = 1; goto out; } if (state->mode & GLUSTER_MODE_WIGNORE) { ret = dict_set_int32(options, "force", _gf_true); if (ret) { gf_log("cli", GF_LOG_ERROR, "Failed to set force " "option"); goto out; } } ret = dict_set_int32(options, "attach-tier", 1); if (ret) goto out; ret = dict_set_int32(options, "hot-type", type); if (ret) goto out; proc = &cli_rpc_prog->proctable[GLUSTER_CLI_ADD_TIER_BRICK]; CLI_LOCAL_INIT(local, words, frame, options); if (proc->fn) { ret = proc->fn(frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("attach-tier failed"); } CLI_STACK_DESTROY(frame); return ret; } int do_cli_cmd_volume_detach_tier(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount, gf_boolean_t *aborted) { int ret = -1; rpc_clnt_procedure_t *proc = NULL; call_frame_t *frame = NULL; dict_t *options = NULL; int sent = 0; int parse_error = 0; gf_answer_t answer = GF_ANSWER_NO; cli_local_t *local = NULL; int need_question = 0; const char *question = "Removing tier can result in data loss. " "Do you want to Continue?"; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) goto out; ret = cli_cmd_volume_detach_tier_parse(words, wordcount, &options, &need_question); if (ret) { cli_usage_out(word->pattern); parse_error = 1; goto out; } ret = dict_set_int32(options, "force", 1); if (ret) goto out; ret = dict_set_int32(options, "count", 0); if (ret) goto out; *aborted = _gf_false; if (!(state->mode & GLUSTER_MODE_SCRIPT) && need_question) { /* we need to ask question only in case of 'commit or force' */ answer = cli_cmd_get_confirmation(state, question); if (GF_ANSWER_NO == answer) { ret = 0; *aborted = _gf_true; goto out; } } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_REMOVE_TIER_BRICK]; CLI_LOCAL_INIT(local, words, frame, options); if (proc->fn) { ret = proc->fn(frame, THIS, options); } out: if (ret) { cli_cmd_sent_status_get(&sent); if ((sent == 0) && (parse_error == 0)) cli_out("Volume detach tier failed"); } CLI_STACK_DESTROY(frame); return ret; } int cli_cmd_volume_tier_cbk(struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { int ret = -1; call_frame_t *frame = NULL; dict_t *options = NULL; rpc_clnt_procedure_t *proc = NULL; cli_local_t *local = NULL; int i = 0; eventtypes_t event = EVENT_LAST; gf_boolean_t aborted = _gf_false; gf_answer_t answer = GF_ANSWER_NO; const char *detach_question = "gluster volume detach-tier " " is " "deprecated. Use the new command \'" "gluster volume tier detach \'\n" "Do you want to Continue?"; const char *attach_question = "gluster volume attach-tier " "[] ... is " "deprecated. Use the new command \'" "gluster volume tier attach [] ... [force]\'\n" "Do you want to Continue?"; if (wordcount < 4) { if (wordcount == 3 && !strcmp(words[2], "help")) { cli_cmd_tier_help_cbk(state, word, words, wordcount); ret = 0; } else { cli_usage_out(word->pattern); } goto out; } if (!strcmp(words[1], "detach-tier")) { /* we need to ask question when older command is used */ answer = cli_cmd_get_confirmation(state, detach_question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } ret = do_cli_cmd_volume_detach_tier(state, word, words, wordcount, &aborted); goto out; } else if (!strcmp(words[3], "detach")) { for (i = 3; i < wordcount; i++) words[i] = words[i + 1]; ret = do_cli_cmd_volume_detach_tier(state, word, words, wordcount - 1, &aborted); if (!aborted) { if (!strcmp(words[wordcount - 2], "commit")) { event = EVENT_TIER_DETACH_COMMIT; } else if (!strcmp(words[wordcount - 2], "start")) { event = EVENT_TIER_DETACH_START; } else if (!strcmp(words[wordcount - 2], "stop")) { event = EVENT_TIER_DETACH_STOP; } else if (!strcmp(words[wordcount - 2], "force")) { event = EVENT_TIER_DETACH_FORCE; } } goto out; } else if (!strcmp(words[1], "attach-tier")) { /* we need to ask question when the older command is used */ answer = cli_cmd_get_confirmation(state, attach_question); if (GF_ANSWER_NO == answer) { ret = 0; goto out; } ret = do_cli_cmd_volume_attach_tier(state, word, words, wordcount); goto out; } else if (!strcmp(words[3], "attach")) { for (i = 3; i < wordcount; i++) words[i] = words[i + 1]; ret = do_cli_cmd_volume_attach_tier(state, word, words, wordcount - 1); if (!strcmp(words[wordcount - 2], "force")) { event = EVENT_TIER_ATTACH_FORCE; } else { event = EVENT_TIER_ATTACH; } goto out; } ret = cli_cmd_volume_tier_parse(words, wordcount, &options); if (ret) { cli_usage_out(word->pattern); goto out; } if (!strcmp(words[wordcount - 1], "start")) { event = EVENT_TIER_START; } else { if (!strcmp(words[wordcount - 2], "start") && !strcmp(words[wordcount - 1], "force")) { event = EVENT_TIER_START_FORCE; } } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_TIER]; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) { gf_log(THIS->name, GF_LOG_ERROR, "failed to create frame"); ret = -1; goto out; } CLI_LOCAL_INIT(local, words, frame, options); if (proc->fn) { ret = proc->fn(frame, THIS, options); } out: if (ret) { cli_out("Tier command failed"); } else { if (event != EVENT_LAST) { gf_event(event, "vol=%s", words[2]); } } if (options) dict_unref(options); return ret; } int cli_get_soft_limit(dict_t *options, const char **words, dict_t *xdata) { call_frame_t *frame = NULL; cli_local_t *local = NULL; rpc_clnt_procedure_t *proc = NULL; char *default_sl = NULL; char *default_sl_dup = NULL; int ret = -1; frame = create_frame(THIS, THIS->ctx->pool); if (!frame) { ret = -1; goto out; } // We need a ref on @options to prevent CLI_STACK_DESTROY // from destroying it prematurely. dict_ref(options); CLI_LOCAL_INIT(local, words, frame, options); proc = &cli_rpc_prog->proctable[GLUSTER_CLI_QUOTA]; ret = proc->fn(frame, THIS, options); ret = dict_get_str(options, "default-soft-limit", &default_sl); if (ret) { gf_log("cli", GF_LOG_ERROR, "Failed to get default soft limit"); goto out; } default_sl_dup = gf_strdup(default_sl); if (!default_sl_dup) { ret = -1; goto out; } ret = dict_set_dynstr(xdata, "default-soft-limit", default_sl_dup); if (ret) { gf_log("cli", GF_LOG_ERROR, "Failed to set default soft limit"); GF_FREE(default_sl_dup); goto out; } out: CLI_STACK_DESTROY(frame); return ret; } /* Checks if at least one limit has been set on the volume * * Returns true if at least one limit is set. Returns false otherwise. */ gf_boolean_t _limits_set_on_volume(char *volname, int type) { gf_boolean_t limits_set = _gf_false; int ret = -1; char quota_conf_file[PATH_MAX] = { 0, }; int fd = -1; char buf[16] = { 0, }; float version = 0.0f; char gfid_type_stored = 0; char gfid_type = 0; /* TODO: fix hardcoding; Need to perform an RPC call to glusterd * to fetch working directory */ snprintf(quota_conf_file, sizeof quota_conf_file, "%s/vols/%s/quota.conf", GLUSTERD_DEFAULT_WORKDIR, volname); fd = open(quota_conf_file, O_RDONLY); if (fd == -1) goto out; ret = quota_conf_read_version(fd, &version); if (ret) goto out; if (type == GF_QUOTA_OPTION_TYPE_LIST) gfid_type = GF_QUOTA_CONF_TYPE_USAGE; else gfid_type = GF_QUOTA_CONF_TYPE_OBJECTS; /* Try to read at least one gfid of type 'gfid_type' */ while (1) { ret = quota_conf_read_gfid(fd, buf, &gfid_type_stored, version); if (ret <= 0) break; if (gfid_type_stored == gfid_type) { limits_set = _gf_true; break; } } out: if (fd != -1) sys_close(fd); return limits_set; } int cli_cmd_quota_handle_list_all(const char **words, dict_t *options) { int all_failed = 1; int count = 0; int ret = -1; rpc_clnt_procedure_t *proc = NULL; cli_local_t *local = NULL; call_frame_t *frame = NULL; dict_t *xdata = NULL; char gfid_str[UUID_CANONICAL_FORM_LEN + 1]; char *volname = NULL; char *volname_dup = NULL; unsigned char buf[16] = {0}; int fd = -1; char quota_conf_file[PATH_MAX] = {0}; gf_boolean_t xml_err_flag = _gf_false; char err_str[NAME_MAX] = { 0, }; int32_t type = 0; char gfid_type = 0; float version = 0.0f; int32_t max_count = 0; xdata = dict_new(); if (!xdata) { ret = -1; goto out; } ret = dict_get_str(options, "volname", &volname); if (ret) { gf_log("cli", GF_LOG_ERROR, "Failed to get volume name"); goto out; } ret = dict_get_int32(options, "type", &type); if (ret) { gf_log("cli", GF_LOG_ERROR, "Failed to get quota option type"); goto out; } ret = dict_set_int32(xdata, "type", type); if (ret) { gf_log("cli", GF_LOG_ERROR, "Failed to set type in xdata"); goto out; } ret = cli_get_soft_limit(options, words, xdata); if (ret) { gf_log("cli", GF_LOG