From 182bad8bfd099da5e742da28c4820936eb1f3867 Mon Sep 17 00:00:00 2001 From: Krutika Dhananjay Date: Mon, 25 Nov 2013 15:16:23 +0530 Subject: cli, glusterd: More quota fixes ... ... which may be grouped under the following categories: 1. Fix incorrect cli exit status for 'quota list' cmd 2. Print appropriate error message on quota parse errors in cli Authored by: Anuradha Talur 3. glusterd: Improve quota validation during stage-op 4. Fix peer probe issues resulting from quota conf checksum mismatches 5. Enhancements to CLI output in the event of quota command failures Authored by: Kaushal Madappa 7. Move aux mount location from /tmp to /var/run/gluster Authored by: Krishnan Parthasarathi 8. Fix performance issues in quota limit-usage Authored by: Krutika Dhananjay Note: Some functions that were used in earlier version of quota, that aren't called anymore have been removed. Change-Id: I9d874f839ae5fdcfbe6d4f2d727eac091f27ac57 BUG: 969461 Signed-off-by: Krutika Dhananjay Reviewed-on: http://review.gluster.org/6366 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- cli/src/cli-cmd-parser.c | 6 ++- cli/src/cli-cmd-volume.c | 103 +++++++++++++++++++++++++++++++++++++++++++---- cli/src/cli-cmd.h | 6 +++ cli/src/cli-rpc-ops.c | 64 ++++++++++++++++++++--------- cli/src/cli.h | 4 ++ 5 files changed, 156 insertions(+), 27 deletions(-) (limited to 'cli/src') diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index dd7b11bcc..88fbf96ff 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -535,6 +535,7 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options) w = str_getunamb (words[3], opwords); if (!w) { + cli_out ("Invalid quota option : %s", words[3]); ret = - 1; goto out; } @@ -587,7 +588,10 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options) ret = gf_string2bytesize (words[5], &value); if (ret != 0) { - cli_err ("Please enter a correct value"); + if (errno == ERANGE) + cli_err ("Value too large: %s", words[5]); + else + cli_err ("Please enter a correct value"); goto out; } diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 9bc11d2db..22bf66b4f 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -28,6 +28,7 @@ #include "cli-mem-types.h" #include "cli1-xdr.h" #include "run.h" +#include "syscall.h" extern struct rpc_clnt *global_rpc; extern struct rpc_clnt *global_quotad_rpc; @@ -1026,7 +1027,7 @@ gf_cli_create_auxiliary_mount (char *volname) goto out; } - snprintf (mountdir, sizeof (mountdir)-1, "/tmp/%s", volname); + GLUSTERD_GET_QUOTA_AUX_MOUNT_PATH (mountdir, volname, "/"); ret = mkdir (mountdir, 0777); if (ret && errno != EEXIST) { gf_log ("cli", GF_LOG_ERROR, "Failed to create auxiliary mount " @@ -1071,8 +1072,11 @@ cli_stage_quota_op (char *volname, int op_code) case GF_QUOTA_OPTION_TYPE_REMOVE: case GF_QUOTA_OPTION_TYPE_LIST: ret = gf_cli_create_auxiliary_mount (volname); - if (ret) + if (ret) { + cli_err ("quota: Could not start quota " + "auxiliary mount"); goto out; + } ret = 0; break; @@ -1153,6 +1157,77 @@ cli_cmd_quota_conf_skip_header (int fd) return gf_skip_header_section (fd, strlen (buf)); } +/* 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) { + gf_boolean_t limits_set = _gf_false; + int ret = -1; + char quota_conf_file[PATH_MAX] = {0,}; + int fd = -1; + char buf[16] = {0,}; + + /* TODO: fix hardcoding; Need to perform an RPC call to glusterd + * to fetch working directory + */ + sprintf (quota_conf_file, "/var/lib/glusterd/vols/%s/quota.conf", + volname); + fd = open (quota_conf_file, O_RDONLY); + if (fd == -1) + goto out; + + ret = cli_cmd_quota_conf_skip_header (fd); + if (ret) + goto out; + + /* Try to read atleast one gfid */ + ret = read (fd, (void *)buf, 16); + if (ret == 16) + limits_set = _gf_true; +out: + if (fd != -1) + close (fd); + return limits_set; +} + +/* Checks if the mount is connected to the bricks + * + * Returns true if connected and false if not + */ +gf_boolean_t +_quota_aux_mount_online (char *volname) +{ + int ret = 0; + char mount_path[PATH_MAX + 1] = {0,}; + struct stat buf = {0,}; + + GF_ASSERT (volname); + + /* Try to create the aux mount before checking if bricks are online */ + ret = gf_cli_create_auxiliary_mount (volname); + if (ret) { + cli_err ("quota: Could not start quota auxiliary mount"); + return _gf_false; + } + + GLUSTERD_GET_QUOTA_AUX_MOUNT_PATH (mount_path, volname, "/"); + + ret = sys_stat (mount_path, &buf); + if (ret) { + if (ENOTCONN == errno) { + cli_err ("quota: Cannot connect to bricks. Check if " + "bricks are online."); + } else { + cli_err ("quota: Error on quota auxiliary mount (%s).", + strerror (errno)); + } + return _gf_false; + } + return _gf_true; +} + int cli_cmd_quota_handle_list_all (const char **words, dict_t *options) { @@ -1189,6 +1264,21 @@ cli_cmd_quota_handle_list_all (const char **words, dict_t *options) goto out; } + /* Check if at least one limit is set on volume. No need to check for + * quota enabled as cli_get_soft_limit() handles that + */ + if (!_limits_set_on_volume (volname)) { + cli_out ("quota: No quota configured on volume %s", volname); + ret = 0; + goto out; + } + + /* Check if the mount is online before doing any listing */ + if (!_quota_aux_mount_online (volname)) { + ret = -1; + goto out; + } + frame = create_frame (THIS, THIS->ctx->pool); if (!frame) { ret = -1; @@ -1265,22 +1355,19 @@ cli_cmd_quota_handle_list_all (const char **words, dict_t *options) } if (count > 0) { - ret = all_failed? 0: -1; + ret = all_failed? -1: 0; } else { ret = 0; } out: - if (count == 0) { - cli_out ("quota: No quota configured on volume %s", volname); - } if (fd != -1) { close (fd); } GF_FREE (gfid_str); if (ret) { - gf_log ("cli", GF_LOG_ERROR, "Couldn't fetch quota limits " - "for even one of the directories configured"); + gf_log ("cli", GF_LOG_ERROR, "Could not fetch and display quota" + " limits"); } CLI_STACK_DESTROY (frame); return ret; diff --git a/cli/src/cli-cmd.h b/cli/src/cli-cmd.h index 52396bbf7..541b4ff73 100644 --- a/cli/src/cli-cmd.h +++ b/cli/src/cli-cmd.h @@ -119,4 +119,10 @@ gf_answer_t cli_cmd_get_confirmation (struct cli_state *state, const char *question); int cli_cmd_sent_status_get (int *status); +gf_boolean_t +_limits_set_on_volume (char *volname); + +gf_boolean_t +_quota_aux_mount_online (char *volname); + #endif /* __CLI_CMD_H__ */ diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 07c081aff..d125a9284 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -2288,8 +2288,8 @@ out: static int print_quota_list_output (char *mountdir, char *default_sl, char *path) { - uint64_t used_space = 0; - uint64_t avail = 0; + int64_t used_space = 0; + int64_t avail = 0; char *used_str = NULL; char *avail_str = NULL; int ret = -1; @@ -2309,6 +2309,20 @@ print_quota_list_output (char *mountdir, char *default_sl, char *path) gf_log ("cli", GF_LOG_ERROR, "Failed to get the xattr " "trusted.glusterfs.quota.limit-set on %s. Reason : %s", mountdir, strerror (errno)); + switch (errno) { +#if defined(ENODATA) + case ENODATA: +#endif +#if defined(ENOATTR) && (ENOATTR != ENODATA) + case ENOATTR: +#endif + cli_err ("%-40s %s", path, "Limit not set"); + break; + default: + cli_err ("%-40s %s", path, strerror (errno)); + break; + } + goto out; } @@ -2371,10 +2385,20 @@ gf_cli_print_limit_list_from_dict (char *volname, dict_t *dict, if (!dict|| count <= 0) goto out; - /*To-Do: - * Proper error reporting to handle the case where none of the given - * path arguments are present or have their limits set. + /* Need to check if any quota limits are set on the volume before trying + * to list them */ + if (!_limits_set_on_volume (volname)) { + ret = 0; + cli_out ("quota: No quota configured on volume %s", volname); + goto out; + } + + /* Check if the mount is online before doing any listing */ + if (!_quota_aux_mount_online (volname)) { + ret = -1; + goto out; + } cli_out (" Path Hard-limit " "Soft-limit Used Available"); @@ -2394,9 +2418,7 @@ gf_cli_print_limit_list_from_dict (char *volname, dict_t *dict, ret = gf_canonicalize_path (path); if (ret) goto out; - snprintf (mountdir, sizeof (mountdir), "/tmp/%s%s", volname, - path); - + GLUSTERD_GET_QUOTA_AUX_MOUNT_PATH (mountdir, volname, path); ret = print_quota_list_output (mountdir, default_sl, path); } @@ -2520,12 +2542,14 @@ cli_quotad_getlimit_cbk (struct rpc_req *req, struct iovec *iov, goto out; } - if (rsp.op_ret && strcmp (rsp.op_errstr, "") == 0) { - cli_err ("quota command : failed"); - goto out; - - } else if (strcmp (rsp.op_errstr, "")) + if (rsp.op_ret) { + ret = -1; + if (strcmp (rsp.op_errstr, "")) cli_err ("quota command failed : %s", rsp.op_errstr); + else + cli_err ("quota command : failed"); + goto out; + } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ @@ -2633,14 +2657,18 @@ gf_cli_quota_cbk (struct rpc_req *req, struct iovec *iov, goto out; } - if (rsp.op_ret && strcmp (rsp.op_errstr, "") == 0) { - cli_err ("quota command : failed"); - + if (rsp.op_ret) { + ret = -1; if (global_state->mode & GLUSTER_MODE_XML) goto xml_output; - goto out; - } else if (strcmp (rsp.op_errstr, "")) + + if (strcmp (rsp.op_errstr, "")) cli_err ("quota command failed : %s", rsp.op_errstr); + else + cli_err ("quota command : failed"); + + goto out; + } if (rsp.dict.dict_len) { /* Unserialize the dictionary */ diff --git a/cli/src/cli.h b/cli/src/cli.h index b71140a81..1fe8ffff7 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -47,6 +47,10 @@ enum argp_option_keys { #define GLUSTER_MODE_XML (1 << 2) +#define GLUSTERD_GET_QUOTA_AUX_MOUNT_PATH(abspath, volname, path) \ + snprintf (abspath, sizeof (abspath)-1, \ + DEFAULT_VAR_RUN_DIRECTORY"/%s%s", volname, path); + #define GLUSTERFS_GET_AUX_MOUNT_PIDFILE(pidfile,volname) { \ snprintf (pidfile, PATH_MAX-1, \ DEFAULT_VAR_RUN_DIRECTORY"/%s.pid", volname); \ -- cgit