summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src
diff options
context:
space:
mode:
authorRaghavendra G <raghavendra@gluster.com>2010-06-18 02:18:02 +0000
committerAnand V. Avati <avati@dev.gluster.com>2010-07-02 04:44:46 -0700
commit3dc79ca8e6119f5ff61058cc87f9a4fc251017ef (patch)
treebc19de662216017cc8d8d5ab5d06d5972de812c4 /libglusterfs/src
parent01923eed1115e53c5be9fba3e72f75c7c631bf95 (diff)
performance/write-behind: explicitly enforce ordering of overlapping writes.
- If there are non-contiguous offsets (offsets which do not start where previous write ended), wait for completion of previous writes to server, before sending new ones. - Send flush call to server only when all writes are completed. - If a file is opened with O_APPEND, at any point of time a maximum only one write call to server should be in transit. This is to avoid reordering of writes in the presence of afr which can result in data corruption. See bug #934 for more details. Signed-off-by: Raghavendra G <raghavendra@gluster.com> Signed-off-by: Anand V. Avati <avati@dev.gluster.com> BUG: 970 (extracting kernel tarball hangs midway.) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=970
Diffstat (limited to 'libglusterfs/src')
0 files changed, 0 insertions, 0 deletions
der'>Diffstat (limited to 'cli/src')
-rw-r--r--cli/src/Makefile.am4
-rw-r--r--cli/src/cli-cmd-parser.c129
-rw-r--r--cli/src/cli-cmd-volume.c354
-rw-r--r--cli/src/cli-cmd.c4
-rw-r--r--cli/src/cli-cmd.h2
-rw-r--r--cli/src/cli-quotad-client.c154
-rw-r--r--cli/src/cli-quotad-client.h33
-rw-r--r--cli/src/cli-rpc-ops.c509
-rw-r--r--cli/src/cli.c48
-rw-r--r--cli/src/cli.h9
10 files changed, 1065 insertions, 181 deletions
diff --git a/cli/src/Makefile.am b/cli/src/Makefile.am
index d5189da5e8c..6370c2203bb 100644
--- a/cli/src/Makefile.am
+++ b/cli/src/Makefile.am
@@ -2,7 +2,7 @@ sbin_PROGRAMS = gluster
gluster_SOURCES = cli.c registry.c input.c cli-cmd.c cli-rl.c \
cli-cmd-volume.c cli-cmd-peer.c cli-rpc-ops.c cli-cmd-parser.c\
- cli-cmd-system.c cli-cmd-misc.c cli-xml-output.c
+ cli-cmd-system.c cli-cmd-misc.c cli-xml-output.c cli-quotad-client.c
gluster_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(GF_LDADD)\
$(RLLIBS) $(top_builddir)/rpc/xdr/src/libgfxdr.la \
@@ -10,7 +10,7 @@ gluster_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(GF_LDADD)\
$(GF_GLUSTERFS_LIBS) $(XML_LIBS)
gluster_LDFLAGS = $(GF_LDFLAGS)
-noinst_HEADERS = cli.h cli-mem-types.h cli-cmd.h
+noinst_HEADERS = cli.h cli-mem-types.h cli-cmd.h cli-quotad-client.h
AM_CPPFLAGS = $(GF_CPPFLAGS) \
-I$(top_srcdir)/libglusterfs/src -I$(top_srcdir)/rpc/rpc-lib/src\
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index cd0370acc78..dd7b11bccd4 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -485,8 +485,12 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
uint64_t value = 0;
gf_quota_type type = GF_QUOTA_OPTION_TYPE_NONE;
char *opwords[] = { "enable", "disable", "limit-usage",
- "remove", "list", "version", NULL };
+ "remove", "list", "alert-time",
+ "soft-timeout", "hard-timeout",
+ "default-soft-limit", NULL};
char *w = NULL;
+ uint32_t time = 0;
+ double percent = 0;
GF_ASSERT (words);
GF_ASSERT (options);
@@ -558,7 +562,8 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
}
if (strcmp (w, "limit-usage") == 0) {
- if (wordcount != 6) {
+
+ if (wordcount < 6 || wordcount > 7) {
ret = -1;
goto out;
}
@@ -567,8 +572,8 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
if (words[4][0] != '/') {
cli_err ("Please enter absolute path");
-
- return -2;
+ ret = -1;
+ goto out;
}
ret = dict_set_str (dict, "path", (char *) words[4]);
if (ret)
@@ -576,20 +581,34 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
if (!words[5]) {
cli_err ("Please enter the limit value to be set");
-
- return -2;
+ ret = -1;
+ goto out;
}
ret = gf_string2bytesize (words[5], &value);
if (ret != 0) {
cli_err ("Please enter a correct value");
- return -1;
+ goto out;
}
- ret = dict_set_str (dict, "limit", (char *) words[5]);
+ ret = dict_set_str (dict, "hard-limit", (char *) words[5]);
if (ret < 0)
goto out;
+ if (wordcount == 7) {
+
+ ret = gf_string2percent (words[6], &percent);
+ if (ret != 0) {
+ cli_err ("Please enter a correct value");
+ goto out;
+ }
+
+ ret = dict_set_str (dict, "soft-limit",
+ (char *) words[6]);
+ if (ret < 0)
+ goto out;
+ }
+
goto set_type;
}
if (strcmp (w, "remove") == 0) {
@@ -602,8 +621,8 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
if (words[4][0] != '/') {
cli_err ("Please enter absolute path");
-
- return -2;
+ ret = -1;
+ goto out;
}
ret = dict_set_str (dict, "path", (char *) words[4]);
@@ -636,8 +655,75 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
goto set_type;
}
- if (strcmp (w, "version") == 0) {
- type = GF_QUOTA_OPTION_TYPE_VERSION;
+
+ if (strcmp (w, "alert-time") == 0) {
+ if (wordcount != 5) {
+ ret = -1;
+ goto out;
+ }
+ type = GF_QUOTA_OPTION_TYPE_ALERT_TIME;
+
+ ret = gf_string2time (words[4], &time);
+ if (ret) {
+ cli_err ("Invalid argument %s. Please enter a valid "
+ "string", words[4]);
+ goto out;
+ }
+
+ ret = dict_set_str (dict, "value", (char *)words[4]);
+ if (ret < 0)
+ goto out;
+ goto set_type;
+ }
+ if (strcmp (w, "soft-timeout") == 0) {
+ if (wordcount != 5) {
+ ret = -1;
+ goto out;
+ }
+ type = GF_QUOTA_OPTION_TYPE_SOFT_TIMEOUT;
+
+ ret = gf_string2time (words[4], &time);
+ if (ret) {
+ cli_err ("Invalid argument %s. Please enter a valid "
+ "string", words[4]);
+ goto out;
+ }
+
+ ret = dict_set_str (dict, "value", (char *)words[4]);
+ if (ret < 0)
+ goto out;
+ goto set_type;
+ }
+ if (strcmp (w, "hard-timeout") == 0) {
+ if(wordcount != 5) {
+ ret = -1;
+ goto out;
+ }
+ type = GF_QUOTA_OPTION_TYPE_HARD_TIMEOUT;
+
+ ret = gf_string2time (words[4], &time);
+ if (ret) {
+ cli_err ("Invalid argument %s. Please enter a valid "
+ "string", words[4]);
+ goto out;
+ }
+
+ ret = dict_set_str (dict, "value", (char *)words[4]);
+ if (ret < 0)
+ goto out;
+ goto set_type;
+ }
+ if (strcmp (w, "default-soft-limit") == 0) {
+ if(wordcount != 5) {
+ ret = -1;
+ goto out;
+ }
+ type = GF_QUOTA_OPTION_TYPE_DEFAULT_SOFT_LIMIT;
+
+ ret = dict_set_str (dict, "value", (char *)words[4]);
+ if (ret < 0)
+ goto out;
+ goto set_type;
} else {
GF_ASSERT (!"opword mismatch");
}
@@ -2225,6 +2311,8 @@ cli_cmd_volume_status_parse (const char **words, int wordcount,
cmd |= GF_CLI_STATUS_NFS;
} else if (!strcmp (words[3], "shd")) {
cmd |= GF_CLI_STATUS_SHD;
+ } else if (!strcmp (words[3], "quotad")) {
+ cmd |= GF_CLI_STATUS_QUOTAD;
} else {
cmd = GF_CLI_STATUS_BRICK;
ret = dict_set_str (dict, "brick",
@@ -2280,6 +2368,17 @@ cli_cmd_volume_status_parse (const char **words, int wordcount,
goto out;
}
cmd |= GF_CLI_STATUS_SHD;
+ } else if (!strcmp (words[3], "quotad")) {
+ if (cmd == GF_CLI_STATUS_FD ||
+ cmd == GF_CLI_STATUS_CLIENTS ||
+ cmd == GF_CLI_STATUS_DETAIL ||
+ cmd == GF_CLI_STATUS_INODE) {
+ cli_err ("Detail/FD/Clients/Inode status not "
+ "available for Quota Daemon");
+ ret = -1;
+ goto out;
+ }
+ cmd |= GF_CLI_STATUS_QUOTAD;
} else {
if (cmd == GF_CLI_STATUS_TASKS) {
cli_err ("Tasks status not available for "
@@ -2317,7 +2416,7 @@ cli_cmd_validate_dumpoption (const char *arg, char **option)
{
char *opwords[] = {"all", "nfs", "mem", "iobuf", "callpool", "priv",
"fd", "inode", "history", "inodectx", "fdctx",
- NULL};
+ "quotad", NULL};
char *w = NULL;
w = str_getunamb (arg, opwords);
@@ -2349,6 +2448,10 @@ cli_cmd_volume_statedump_options_parse (const char **words, int wordcount,
strncat (option_str, option, strlen (option));
strncat (option_str, " ", 1);
}
+ if((strstr (option_str, "nfs")) && strstr (option_str, "quotad")) {
+ ret = -1;
+ goto out;
+ }
dict = dict_new ();
if (!dict)
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
index 100be0b7337..9bc11d2dbb4 100644
--- a/cli/src/cli-cmd-volume.c
+++ b/cli/src/cli-cmd-volume.c
@@ -30,8 +30,10 @@
#include "run.h"
extern struct rpc_clnt *global_rpc;
+extern struct rpc_clnt *global_quotad_rpc;
extern rpc_clnt_prog_t *cli_rpc_prog;
+extern rpc_clnt_prog_t cli_quotad_clnt;
int
cli_cmd_volume_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
@@ -1007,6 +1009,283 @@ out:
return ret;
}
+static int
+gf_cli_create_auxiliary_mount (char *volname)
+{
+ int ret = -1;
+ char mountdir[PATH_MAX] = {0,};
+ char pidfile_path[PATH_MAX] = {0,};
+ char logfile[PATH_MAX] = {0,};
+
+ GLUSTERFS_GET_AUX_MOUNT_PIDFILE (pidfile_path, volname);
+
+ if (gf_is_service_running (pidfile_path, NULL)) {
+ gf_log ("cli", GF_LOG_DEBUG, "Aux mount of volume %s is running"
+ " already", volname);
+ ret = 0;
+ goto out;
+ }
+
+ snprintf (mountdir, sizeof (mountdir)-1, "/tmp/%s", volname);
+ ret = mkdir (mountdir, 0777);
+ if (ret && errno != EEXIST) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to create auxiliary mount "
+ "directory %s. Reason : %s", mountdir,
+ strerror (errno));
+ goto out;
+ }
+
+ snprintf (logfile, PATH_MAX-1, "%s/quota-mount-%s.log",
+ DEFAULT_LOG_FILE_DIRECTORY, volname);
+
+ ret = runcmd (SBIN_DIR"/glusterfs",
+ "-s", "localhost",
+ "--volfile-id", volname,
+ "-l", logfile,
+ "-p", pidfile_path,
+ mountdir,
+ "--client-pid", "-42", NULL);
+
+ if (ret) {
+ gf_log ("cli", GF_LOG_WARNING, "failed to mount glusterfs "
+ "client. Please check the log file %s for more details",
+ logfile);
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+static int
+cli_stage_quota_op (char *volname, int op_code)
+{
+ int ret = -1;
+
+ switch (op_code) {
+ case GF_QUOTA_OPTION_TYPE_ENABLE:
+ case GF_QUOTA_OPTION_TYPE_LIMIT_USAGE:
+ case GF_QUOTA_OPTION_TYPE_REMOVE:
+ case GF_QUOTA_OPTION_TYPE_LIST:
+ ret = gf_cli_create_auxiliary_mount (volname);
+ if (ret)
+ goto out;
+ ret = 0;
+ break;
+
+ default:
+ ret = 0;
+ break;
+ }
+
+out:
+ return ret;
+}
+
+static void
+print_quota_list_header (void)
+{
+ //Header
+ cli_out (" Path Hard-limit "
+ "Soft-limit Used Available");
+ cli_out ("-----------------------------------------------------"
+ "---------------------------");
+}
+
+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;
+}
+
+#define QUOTA_CONF_HEADER \
+ "GlusterFS Quota conf | version: v%d.%d\n"
+int
+cli_cmd_quota_conf_skip_header (int fd)
+{
+ char buf[PATH_MAX] = {0,};
+
+ snprintf (buf, sizeof(buf)-1, QUOTA_CONF_HEADER, 1, 1);
+ return gf_skip_header_section (fd, strlen (buf));
+}
+
+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 = NULL;
+ char *volname = NULL;
+ char *volname_dup = NULL;
+ unsigned char buf[16] = {0};
+ int fd = -1;
+ char quota_conf_file[PATH_MAX] = {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 = cli_get_soft_limit (options, words, xdata);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to fetch default "
+ "soft-limit");
+ goto out;
+ }
+
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame) {
+ ret = -1;
+ goto out;
+ }
+
+ volname_dup = gf_strdup (volname);
+ if (!volname_dup) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = dict_set_dynstr (xdata, "volume-uuid", volname_dup);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to set volume-uuid");
+ GF_FREE (volname_dup);
+ goto out;
+ }
+
+ //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) {
+ //This may because no limits were yet set on the volume
+ gf_log ("cli", GF_LOG_TRACE, "Unable to open "
+ "quota.conf");
+ ret = 0;
+ goto out;
+ }
+
+ ret = cli_cmd_quota_conf_skip_header (fd);
+ if (ret) {
+ goto out;
+ }
+ CLI_LOCAL_INIT (local, words, frame, xdata);
+ proc = &cli_quotad_clnt.proctable[GF_AGGREGATOR_GETLIMIT];
+
+ print_quota_list_header ();
+ gfid_str = GF_CALLOC (1, gf_common_mt_char, 64);
+ if (!gfid_str) {
+ ret = -1;
+ goto out;
+ }
+ for (count = 0;; count++) {
+ ret = read (fd, (void*) buf, 16);
+ if (ret <= 0) {
+ //Finished reading all entries in the conf file
+ break;
+ }
+ if (ret < 16) {
+ //This should never happen. We must have a multiple of
+ //entry_sz bytes in our configuration file.
+ gf_log (THIS->name, GF_LOG_CRITICAL, "Quota "
+ "configuration store may be corrupt.");
+ goto out;
+ }
+ uuid_utoa_r (buf, gfid_str);
+ ret = dict_set_str (xdata, "gfid", gfid_str);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to set gfid");
+ goto out;
+ }
+
+ ret = proc->fn (frame, THIS, xdata);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to get quota "
+ "limits for %s", uuid_utoa ((unsigned char*)buf));
+ }
+
+ dict_del (xdata, "gfid");
+ all_failed = all_failed && ret;
+ }
+
+ if (count > 0) {
+ ret = all_failed? 0: -1;
+ } 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");
+ }
+ CLI_STACK_DESTROY (frame);
+ return ret;
+}
+
int
cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word,
const char **words, int wordcount)
@@ -1020,47 +1299,78 @@ cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word,
dict_t *options = NULL;
gf_answer_t answer = GF_ANSWER_NO;
cli_local_t *local = NULL;
+ int sent = 0;
+ char *volname = NULL;
const char *question = "Disabling quota will delete all the quota "
"configuration. Do you want to continue?";
- proc = &cli_rpc_prog->proctable[GLUSTER_CLI_QUOTA];
- if (proc == NULL) {
- ret = -1;
+ //parse **words into options dictionary
+ ret = cli_cmd_quota_parse (words, wordcount, &options);
+ if (ret < 0) {
+ cli_usage_out (word->pattern);
+ parse_err = 1;
goto out;
}
- frame = create_frame (THIS, THIS->ctx->pool);
- if (!frame) {
- ret = -1;
+ ret = dict_get_int32 (options, "type", &type);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to get opcode");
goto out;
}
- ret = cli_cmd_quota_parse (words, wordcount, &options);
-
- if (ret < 0) {
- cli_usage_out (word->pattern);
- parse_err = 1;
- goto out;
- } else if (dict_get_int32 (options, "type", &type) == 0 &&
- type == GF_QUOTA_OPTION_TYPE_DISABLE) {
+ //handle quota-disable and quota-list-all different from others
+ switch (type) {
+ case GF_QUOTA_OPTION_TYPE_DISABLE:
answer = cli_cmd_get_confirmation (state, question);
if (answer == GF_ANSWER_NO)
goto out;
+ break;
+ case GF_QUOTA_OPTION_TYPE_LIST:
+ if (wordcount != 4)
+ break;
+ ret = cli_cmd_quota_handle_list_all (words, options);
+ goto out;
+ default:
+ break;
+ }
+
+ ret = dict_get_str (options, "volname", &volname);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to get volume name");
+ goto out;
+ }
+
+ //create auxillary mount need for quota commands that operate on path
+ ret = cli_stage_quota_op (volname, type);
+ if (ret)
+ goto out;
+
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame) {
+ ret = -1;
+ goto out;
}
CLI_LOCAL_INIT (local, words, frame, options);
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_QUOTA];
+ if (proc == NULL) {
+ ret = -1;
+ goto out;
+ }
if (proc->fn)
ret = proc->fn (frame, THIS, options);
out:
- if (ret && parse_err == 0)
- cli_out ("Quota command failed");
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if (sent == 0 && parse_err == 0)
+ cli_out ("Quota command failed. Please check the cli "
+ "logs for more details");
+ }
CLI_STACK_DESTROY (frame);
-
return ret;
-
}
int
@@ -1906,7 +2216,9 @@ struct cli_cmd volume_cmds[] = {
cli_cmd_volume_profile_cbk,
"volume profile operations"},
- { "volume quota <VOLNAME> <enable|disable|limit-usage|list|remove> [path] [value]",
+ { "volume quota <VOLNAME> {enable|disable|list [<path> ...]|remove <path>| default-soft-limit <percent>} |\n"
+ "volume quota <VOLNAME> {limit-usage <path> <size> [<percent>]} |\n"
+ "volume quota <VOLNAME> {alert-time|soft-timeout|hard-timeout} {<time>}",
cli_cmd_quota_cbk,
"quota translator specific operations"},
@@ -1915,7 +2227,7 @@ struct cli_cmd volume_cmds[] = {
cli_cmd_volume_top_cbk,
"volume top operations"},
- { "volume status [all | <VOLNAME> [nfs|shd|<BRICK>]]"
+ { "volume status [all | <VOLNAME> [nfs|shd|<BRICK>|quotad]]"
" [detail|clients|mem|inode|fd|callpool|tasks]",
cli_cmd_volume_status_cbk,
"display status of all or specified volume(s)/brick"},
@@ -1924,7 +2236,7 @@ struct cli_cmd volume_cmds[] = {
cli_cmd_volume_heal_cbk,
"self-heal commands on volume specified by <VOLNAME>"},
- {"volume statedump <VOLNAME> [nfs] [all|mem|iobuf|callpool|priv|fd|"
+ {"volume statedump <VOLNAME> [nfs|quotad] [all|mem|iobuf|callpool|priv|fd|"
"inode|history]...",
cli_cmd_volume_statedump_cbk,
"perform statedump on bricks"},
diff --git a/cli/src/cli-cmd.c b/cli/src/cli-cmd.c
index 1045f34f0f5..63b939282fa 100644
--- a/cli/src/cli-cmd.c
+++ b/cli/src/cli-cmd.c
@@ -352,7 +352,7 @@ cli_cmd_broadcast_connected ()
}
int
-cli_cmd_submit (void *req, call_frame_t *frame,
+cli_cmd_submit (struct rpc_clnt* rpc, void *req, call_frame_t *frame,
rpc_clnt_prog_t *prog,
int procnum, struct iobref *iobref,
xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc)
@@ -368,7 +368,7 @@ cli_cmd_submit (void *req, call_frame_t *frame,
cli_cmd_lock ();
cmd_sent = 0;
- ret = cli_submit_request (req, frame, prog,
+ ret = cli_submit_request (rpc, req, frame, prog,
procnum, NULL, this, cbkfn, xdrproc);
if (!ret) {
diff --git a/cli/src/cli-cmd.h b/cli/src/cli-cmd.h
index 06a1ed32aac..52396bbf755 100644
--- a/cli/src/cli-cmd.h
+++ b/cli/src/cli-cmd.h
@@ -110,7 +110,7 @@ int cli_cmd_lock ();
int cli_cmd_unlock ();
int
-cli_cmd_submit (void *req, call_frame_t *frame,
+cli_cmd_submit (struct rpc_clnt *rpc, void *req, call_frame_t *frame,
rpc_clnt_prog_t *prog,
int procnum, struct iobref *iobref,
xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc);
diff --git a/cli/src/cli-quotad-client.c b/cli/src/cli-quotad-client.c
new file mode 100644
index 00000000000..f0efc8640bd
--- /dev/null
+++ b/cli/src/cli-quotad-client.c
@@ -0,0 +1,154 @@
+/*
+ Copyright (c) 2010-2013 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "cli-quotad-client.h"
+
+extern struct rpc_clnt global_quotad_rpc;
+extern struct rpc_clnt_program cli_quotad_clnt;
+
+int
+cli_quotad_submit_request (void *req, call_frame_t *frame,
+ rpc_clnt_prog_t *prog,
+ int procnum, struct iobref *iobref,
+ xlator_t *this, fop_cbk_fn_t cbkfn,
+ xdrproc_t xdrproc)
+{
+ int ret = -1;
+ int count = 0;
+ struct iovec iov = {0, };
+ struct iobuf *iobuf = NULL;
+ char new_iobref = 0;
+ ssize_t xdr_size = 0;
+
+ GF_ASSERT (this);
+
+ if (req) {
+ xdr_size = xdr_sizeof (xdrproc, req);
+ iobuf = iobuf_get2 (this->ctx->iobuf_pool, xdr_size);
+ if (!iobuf) {
+ goto out;
+ };
+
+ if (!iobref) {
+ iobref = iobref_new ();
+ if (!iobref) {
+ goto out;
+ }
+
+ new_iobref = 1;
+ }
+
+ iobref_add (iobref, iobuf);
+
+ iov.iov_base = iobuf->ptr;
+ iov.iov_len = iobuf_size (iobuf);
+
+ /* Create the xdr payload */
+ ret = xdr_serialize_generic (iov, req, xdrproc);
+ if (ret == -1) {
+ goto out;
+ }
+ iov.iov_len = ret;
+ count = 1;
+ }
+
+ /* Send the msg */
+ ret = rpc_clnt_submit (&global_quotad_rpc, prog, procnum, cbkfn,
+ &iov, count,
+ NULL, 0, iobref, frame, NULL, 0, NULL, 0, NULL);
+ ret = 0;
+
+out:
+ if (new_iobref)
+ iobref_unref (iobref);
+ if (iobuf)
+ iobuf_unref (iobuf);
+
+ return ret;
+}
+
+int
+cli_quotad_notify (struct rpc_clnt *rpc, void *mydata,
+ rpc_clnt_event_t event, void *data)
+{
+ xlator_t *this = NULL;
+ int ret = 0;
+
+ this = mydata;
+
+ switch (event) {
+ case RPC_CLNT_CONNECT:
+ {
+ gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_CONNECT");
+ break;
+ }
+
+ case RPC_CLNT_DISCONNECT:
+ {
+ gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_DISCONNECT");
+ break;
+ }
+
+ default:
+ gf_log (this->name, GF_LOG_TRACE,
+ "got some other RPC event %d", event);
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+struct rpc_clnt *
+cli_quotad_clnt_init (xlator_t *this, dict_t *options)
+{
+ struct rpc_clnt *rpc = NULL;
+ int ret = -1;
+
+
+ ret = dict_set_str (options, "transport.address-family", "unix");
+ if (ret)
+ goto out;
+
+ ret = dict_set_str (options, "transport-type", "socket");
+ if (ret)
+ goto out;
+
+ ret = dict_set_str (options, "transport.socket.connect-path",
+ "/tmp/quotad.socket");
+ if (ret)
+ goto out;
+
+ rpc = rpc_clnt_new (options, this->ctx, this->name, 16);
+ if (!rpc)
+ goto out;
+
+ ret = rpc_clnt_register_notify (rpc, cli_quotad_notify, this);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "failed to register notify");
+ goto out;
+ }
+
+ rpc_clnt_start (rpc);
+out:
+ if (ret) {
+ if (rpc)
+ rpc_clnt_unref (rpc);
+ rpc = NULL;
+ }
+
+ return rpc;
+}
+
diff --git a/cli/src/cli-quotad-client.h b/cli/src/cli-quotad-client.h
new file mode 100644
index 00000000000..aa0b42af38d
--- /dev/null
+++ b/cli/src/cli-quotad-client.h
@@ -0,0 +1,33 @@
+/*
+ Copyright (c) 2010-2013 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+#include "cli.h"
+#include "compat-errno.h"
+#include "compat.h"
+#include "cli-cmd.h"
+#include "cli1-xdr.h"
+#include "xdr-generic.h"
+#include "protocol-common.h"
+#include "cli-mem-types.h"
+
+
+int
+cli_quotad_submit_request (void *req, call_frame_t *frame,
+ rpc_clnt_prog_t *prog,
+ int procnum, struct iobref *iobref,
+ xlator_t *this, fop_cbk_fn_t cbkfn,
+ xdrproc_t xdrproc);
+
+struct rpc_clnt *
+cli_quotad_clnt_init (xlator_t *this, dict_t *options);
+
+int
+cli_quotad_notify (struct rpc_clnt *rpc, void *mydata,
+ rpc_clnt_event_t event, void *data);
+
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index 208f7a281f0..07c081affcc 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -37,9 +37,13 @@
#include "syscall.h"
#include "glusterfs3.h"
#include "portmap-xdr.h"
+#include "byte-order.h"
+#include "cli-quotad-client.h"
#include "run.h"
+extern struct rpc_clnt *global_quotad_rpc;
+extern rpc_clnt_prog_t cli_quotad_clnt;
extern rpc_clnt_prog_t *cli_rpc_prog;
extern int cli_op_ret;
extern int connected;
@@ -2281,137 +2285,346 @@ out:
return ret;
}
-int32_t
-gf_cli_print_limit_list (char *volname, char *limit_list,
- char *op_errstr)
+static int
+print_quota_list_output (char *mountdir, char *default_sl, char *path)
{
- int64_t size = 0;
- int64_t limit_value = 0;
- int32_t i, j;
- int32_t len = 0, ret = -1;
- char *size_str = NULL;
- char path [PATH_MAX] = {0, };
- char ret_str [1024] = {0, };
- char value [1024] = {0, };
- char mountdir [] = "/tmp/mntXXXXXX";
- char abspath [PATH_MAX] = {0, };
- char *colon_ptr = NULL;
- runner_t runner = {0,};
+ uint64_t used_space = 0;
+ uint64_t avail = 0;
+ char *used_str = NULL;
+ char *avail_str = NULL;
+ int ret = -1;
+ char *sl_final = NULL;
+ char percent_str[20] = {0,};
+ char *hl_str = NULL;
+
+ struct quota_limit {
+ int64_t hl;
+ int64_t sl;
+ } __attribute__ ((__packed__)) existing_limits;
+
+ ret = sys_lgetxattr (mountdir, "trusted.glusterfs.quota.limit-set",
+ (void *)&existing_limits,
+ sizeof (existing_limits));
+ if (ret < 0) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to get the xattr "
+ "trusted.glusterfs.quota.limit-set on %s. Reason : %s",
+ mountdir, strerror (errno));
+ goto out;
+ }
- GF_VALIDATE_OR_GOTO ("cli", volname, out);
- GF_VALIDATE_OR_GOTO ("cli", limit_list, out);
+ existing_limits.hl = ntoh64 (existing_limits.hl);
+ existing_limits.sl = ntoh64 (existing_limits.sl);
- if (!connected)
+ hl_str = gf_uint64_2human_readable (existing_limits.hl);
+
+ if (existing_limits.sl < 0) {
+ sl_final = default_sl;
+ } else {
+ snprintf (percent_str, sizeof (percent_str), "%"PRIu64"%%",
+ existing_limits.sl);
+ sl_final = percent_str;
+ }
+
+ ret = sys_lgetxattr (mountdir, "trusted.glusterfs.quota.size",
+ &used_space, sizeof (used_space));
+
+ if (ret < 0) {
+ cli_out ("%-40s %7s %9s %11s %7s", path, hl_str, sl_final,
+ "N/A", "N/A");
+ } else {
+ used_space = ntoh64 (used_space);
+
+ used_str = gf_uint64_2human_readable (used_space);
+
+ if (existing_limits.hl > used_space)
+ avail = existing_limits.hl - used_space;
+ else
+ avail = 0;
+
+ avail_str = gf_uint64_2human_readable (avail);
+ if (used_str == NULL)
+ cli_out ("%-40s %7s %9s %11"PRIu64
+ "%9"PRIu64, path, hl_str,
+ sl_final, used_space, avail);
+ else
+ cli_out ("%-40s %7s %9s %11s %7s", path, hl_str,
+ sl_final, used_str, avail_str);
+ }
+
+out:
+ GF_FREE (used_str);
+ GF_FREE (avail_str);
+ GF_FREE (hl_str);
+ return ret;
+}
+
+int
+gf_cli_print_limit_list_from_dict (char *volname, dict_t *dict,
+ char *default_sl, int count, char *op_errstr)
+{
+ int ret = -1;
+ int i = 0;
+ char key[1024] = {0,};
+ char mountdir[PATH_MAX] = {0,};
+ char *path = NULL;
+
+ if (!dict|| count <= 0)
goto out;
- len = strlen (limit_list);
- if (len == 0) {
- cli_err ("%s", op_errstr?op_errstr:"quota limit not set ");
+ /*To-Do:
+ * Proper error reporting to handle the case where none of the given
+ * path arguments are present or have their limits set.
+ */
+
+ cli_out (" Path Hard-limit "
+ "Soft-limit Used Available");
+ cli_out ("-----------------------------------------------------"
+ "---------------------------");
+
+ while (count--) {
+ snprintf (key, sizeof (key), "path%d", i++);
+
+ ret = dict_get_str (dict, key, &path);
+ if (ret < 0) {
+ gf_log ("cli", GF_LOG_DEBUG, "Path not present in limit"
+ " list");
+ continue;
+ }
+
+ ret = gf_canonicalize_path (path);
+ if (ret)
+ goto out;
+ snprintf (mountdir, sizeof (mountdir), "/tmp/%s%s", volname,
+ path);
+
+ ret = print_quota_list_output (mountdir, default_sl, path);
+
+ }
+out:
+ return ret;
+}
+
+int
+print_quota_list_from_quotad (call_frame_t *frame, dict_t *rsp_dict)
+{
+ int64_t used_space = 0;
+ int64_t avail = 0;
+ int64_t *limit = NULL;
+ char *used_str = NULL;
+ char *avail_str = NULL;
+ char percent_str[20]= {0};
+ char *hl_str = NULL;
+ char *sl_final = NULL;
+ char *path = NULL;
+ char *default_sl = NULL;
+ int ret = -1;
+ cli_local_t *local = NULL;
+ dict_t *gd_rsp_dict = NULL;
+
+ local = frame->local;
+ gd_rsp_dict = local->dict;
+
+ struct quota_limit {
+ int64_t hl;
+ int64_t sl;
+ } __attribute__ ((__packed__)) *existing_limits = NULL;
+
+ ret = dict_get_str (rsp_dict, GET_ANCESTRY_PATH_KEY, &path);
+ if (ret) {
+ gf_log ("cli", GF_LOG_WARNING, "path key is not present "
+ "in dict");
goto out;
}
- if (mkdtemp (mountdir) == NULL) {
- gf_log ("cli", GF_LOG_WARNING, "failed to create a temporary "
- "mount directory");
- ret = -1;
+ ret = dict_get_bin (rsp_dict, QUOTA_LIMIT_KEY, (void**)&limit);
+ if (ret) {
+ gf_log ("cli", GF_LOG_WARNING,
+ "limit key not present in dict");
goto out;
}
- /* Mount a temporary client to fetch the disk usage
- * of the directory on which the limit is set.
- */
- ret = runcmd (SBIN_DIR"/glusterfs", "-s",
- "localhost", "--volfile-id", volname, "-l",
- DEFAULT_LOG_FILE_DIRECTORY"/quota-list.log",
- mountdir, NULL);
+ ret = dict_get_str (gd_rsp_dict, "default-soft-limit", &default_sl);
if (ret) {
- gf_log ("cli", GF_LOG_WARNING, "failed to mount glusterfs client");
- ret = -1;
- goto rm_dir;
+ gf_log (frame->this->name, GF_LOG_ERROR, "failed to "
+ "get default soft limit");
+ goto out;
}
+ existing_limits = (struct quota_limit *)limit;
+ existing_limits->hl = ntoh64 (existing_limits->hl);
+ existing_limits->sl = ntoh64 (existing_limits->sl);
- len = strlen (limit_list);
- if (len == 0) {
- cli_err ("quota limit not set ");
- goto unmount;
+ hl_str = gf_uint64_2human_readable (existing_limits->hl);
+
+ if (existing_limits->sl < 0) {
+ sl_final = default_sl;
+ } else {
+ snprintf (percent_str, sizeof (percent_str), "%"PRIu64"%%",
+ existing_limits->sl);
+ sl_final = percent_str;
}
- i = 0;
+ ret = dict_get_bin (rsp_dict, QUOTA_SIZE_KEY, (void**)&limit);
+ if (ret < 0) {
+ gf_log ("cli", GF_LOG_WARNING,
+ "size key not present in dict");
+ cli_out ("%-40s %7s %9s %11s %7s", path, hl_str, sl_final,
+ "N/A", "N/A");
+ } else {
+ used_space = *limit;
+ used_space = ntoh64 (used_space);
+ used_str = gf_uint64_2human_readable (used_space);
- cli_out ("\tpath\t\t limit_set\t size");
- cli_out ("-----------------------------------------------------------"
- "-----------------------");
- while (i < len) {
- j = 0;
+ if (existing_limits->hl > used_space)
+ avail = existing_limits->hl - used_space;
+ else
+ avail = 0;
- while (limit_list [i] != ',' && limit_list [i] != '\0') {
- path [j++] = limit_list[i++];
- }
- path [j] = '\0';
- //here path[] contains both path and limit value
+ avail_str = gf_uint64_2human_readable (avail);
+ if (used_str == NULL)
+ cli_out ("%-40s %7s %9s %11"PRIu64
+ "%9"PRIu64, path, hl_str,
+ sl_final, used_space, avail);
+ else
+ cli_out ("%-40s %7s %9s %11s %7s", path, hl_str,
+ sl_final, used_str, avail_str);
+ }
+
+ ret = 0;
+out:
+ GF_FREE (used_str);
+ GF_FREE (avail_str);
+ GF_FREE (hl_str);
+ return ret;
+}
+
+int
+cli_quotad_getlimit_cbk (struct rpc_req *req, struct iovec *iov,
+ int count, void *myframe)
+{
+ //TODO: we need to gather the path, hard-limit, soft-limit and used space
+ gf_cli_rsp rsp = {0,};
+ int ret = -1;
+ dict_t *dict = NULL;
+ call_frame_t *frame = NULL;
- colon_ptr = strrchr (path, ':');
- *colon_ptr = '\0';
- strcpy (value, ++colon_ptr);
+ if (-1 == req->rpc_status) {
+ goto out;
+ }
- snprintf (abspath, sizeof (abspath), "%s/%s", mountdir, path);
+ frame = myframe;
+
+ ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp);
+ if (ret < 0) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "Failed to decode xdr response");
+ goto out;
+ }
+
+ if (rsp.op_ret && strcmp (rsp.op_errstr, "") == 0) {
+ cli_err ("quota command : failed");
+ goto out;
+
+ } else if (strcmp (rsp.op_errstr, ""))
+ cli_err ("quota command failed : %s", rsp.op_errstr);
+
+ if (rsp.dict.dict_len) {
+ /* Unserialize the dictionary */
+ dict = dict_new ();
- ret = sys_lgetxattr (abspath, "trusted.limit.list", (void *) ret_str, 4096);
+ ret = dict_unserialize (rsp.dict.dict_val,
+ rsp.dict.dict_len,
+ &dict);
if (ret < 0) {
- cli_out ("%-20s %10s", path, value);
- } else {
- sscanf (ret_str, "%"PRId64",%"PRId64, &size,
- &limit_value);
- size_str = gf_uint64_2human_readable ((uint64_t) size);
- if (size_str == NULL) {
- cli_out ("%-20s %10s %20"PRId64, path,
- value, size);
- } else {
- cli_out ("%-20s %10s %20s", path,
- value, size_str);
- GF_FREE (size_str);
- }
+ gf_log ("cli", GF_LOG_ERROR,
+ "failed to "
+ "unserialize req-buffer to dictionary");
+ goto out;
}
- i++;
+ print_quota_list_from_quotad (frame, dict);
}
-unmount:
+out:
+ cli_cmd_broadcast_response (ret);
+ if (dict)
+ dict_unref (dict);
- runinit (&runner);
- runner_add_args (&runner, "umount",
-#if GF_LINUX_HOST_OS
- "-l",
-#endif
- mountdir, NULL);
- ret = runner_run_reuse (&runner);
- if (ret)
- runner_log (&runner, "cli", GF_LOG_WARNING, "error executing");
- runner_end (&runner);
+ free (rsp.dict.dict_val);
+ return ret;
+}
+
+int
+cli_quotad_getlimit (call_frame_t *frame, xlator_t *this, void *data)
+{
+ gf_cli_req req = {{0,}};
+ int ret = 0;
+ dict_t *dict = NULL;
+
+ if (!frame || !this || !data) {
+ ret = -1;
+ goto out;
+ }
+
+ dict = data;
+ ret = dict_allocate_and_serialize (dict, &req.dict.dict_val,
+ &req.dict.dict_len);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "failed to serialize the data");
+
+ goto out;
+ }
+
+ ret = cli_cmd_submit (global_quotad_rpc, &req, frame, &cli_quotad_clnt,
+ GF_AGGREGATOR_GETLIMIT, NULL,
+ this, cli_quotad_getlimit_cbk,
+ (xdrproc_t) xdr_gf_cli_req);
-rm_dir:
- rmdir (mountdir);
out:
+ gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
return ret;
+
+
+}
+
+void
+gf_cli_quota_list (char *volname, dict_t *dict, int count, char *op_errstr,
+ char *default_sl)
+{
+ GF_VALIDATE_OR_GOTO ("cli", volname, out);
+
+ if (!connected)
+ goto out;
+
+ if (count > 0)
+ gf_cli_print_limit_list_from_dict (volname, dict, default_sl,
+ count, op_errstr);
+out:
+ return;
}
int
gf_cli_quota_cbk (struct rpc_req *req, struct iovec *iov,
int count, void *myframe)
{
- gf_cli_rsp rsp = {0,};
- int ret = -1;
- dict_t *dict = NULL;
- char *volname = NULL;
- char *limit_list = NULL;
- int32_t type = 0;
- char msg[1024] = {0,};
- call_frame_t *frame = NULL;
-
+ gf_cli_rsp rsp = {0,};
+ int ret = -1;
+ dict_t *dict = NULL;
+ char *volname = NULL;
+ int32_t type = 0;
+ call_frame_t *frame = NULL;
+ char *default_sl = NULL;
+ char *limit_list = NULL;
+ cli_local_t *local = NULL;
+ dict_t *aggr = NULL;
+ char *default_sl_dup = NULL;
+ int32_t entry_count = 0;
if (-1 == req->rpc_status) {
goto out;
}
frame = myframe;
+ local = frame->local;
+ aggr = local->dict;
ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp);
if (ret < 0) {
@@ -2420,15 +2633,14 @@ gf_cli_quota_cbk (struct rpc_req *req, struct iovec *iov,
goto out;
}
- if (rsp.op_ret &&
- strcmp (rsp.op_errstr, "") == 0) {
- snprintf (msg, sizeof (msg), "command unsuccessful %s",
- rsp.op_errstr);
+ if (rsp.op_ret && strcmp (rsp.op_errstr, "") == 0) {
+ cli_err ("quota command : failed");
if (global_state->mode & GLUSTER_MODE_XML)
goto xml_output;
goto out;
- }
+ } else if (strcmp (rsp.op_errstr, ""))
+ cli_err ("quota command failed : %s", rsp.op_errstr);
if (rsp.dict.dict_len) {
/* Unserialize the dictionary */
@@ -2438,28 +2650,51 @@ gf_cli_quota_cbk (struct rpc_req *req, struct iovec *iov,
rsp.dict.dict_len,
&dict);
if (ret < 0) {
- gf_log ("glusterd", GF_LOG_ERROR,
+ gf_log ("cli", GF_LOG_ERROR,
"failed to "
"unserialize req-buffer to dictionary");
goto out;
}
}
+ gf_log ("cli", GF_LOG_DEBUG, "Received resp to quota command");
+
ret = dict_get_str (dict, "volname", &volname);
if (ret)
- gf_log (frame->this->name, GF_LOG_TRACE,
+ gf_log (frame->this->name, GF_LOG_ERROR,
"failed to get volname");
- ret = dict_get_str (dict, "limit_list", &limit_list);
+ ret = dict_get_str (dict, "default-soft-limit", &default_sl);
if (ret)
- gf_log (frame->this->name, GF_LOG_TRACE,
- "failed to get limit_list");
+ gf_log (frame->this->name, GF_LOG_TRACE, "failed to get "
+ "default soft limit");
+
+ // default-soft-limit is part of rsp_dict only iff we sent
+ // GLUSTER_CLI_QUOTA with type being GF_QUOTA_OPTION_TYPE_LIST
+ if (default_sl) {
+ default_sl_dup = gf_strdup (default_sl);
+ if (!default_sl_dup) {
+ ret = -1;
+ goto out;
+ }
+ ret = dict_set_dynstr (aggr, "default-soft-limit",
+ default_sl_dup);
+ if (ret) {
+ gf_log (frame->this->name, GF_LOG_TRACE,
+ "failed to set default soft limit");
+ GF_FREE (default_sl_dup);
+ }
+ }
ret = dict_get_int32 (dict, "type", &type);
if (ret)
gf_log (frame->this->name, GF_LOG_TRACE,
"failed to get type");
+ ret = dict_get_int32 (dict, "count", &entry_count);
+ if (ret)
+ gf_log (frame->this->name, GF_LOG_TRACE, "failed to get count");
+
if (type == GF_QUOTA_OPTION_TYPE_LIST) {
if (global_state->mode & GLUSTER_MODE_XML) {
ret = cli_xml_output_vol_quota_limit_list
@@ -2469,31 +2704,15 @@ gf_cli_quota_cbk (struct rpc_req *req, struct iovec *iov,
gf_log ("cli", GF_LOG_ERROR,
"Error outputting to xml");
goto out;
-
}
- if (limit_list) {
- gf_cli_print_limit_list (volname,
- limit_list,
- rsp.op_errstr);
- } else {
- gf_log ("cli", GF_LOG_INFO, "Received resp to quota "
- "command ");
- if (rsp.op_errstr)
- snprintf (msg, sizeof (msg), "%s",
- rsp.op_errstr);
- }
- } else {
- gf_log ("cli", GF_LOG_INFO, "Received resp to quota command ");
- if (rsp.op_errstr)
- snprintf (msg, sizeof (msg), "%s", rsp.op_errstr);
- else
- snprintf (msg, sizeof (msg), "successful");
+ gf_cli_quota_list (volname, dict, entry_count, rsp.op_errstr,
+ default_sl);
}
xml_output:
if (global_state->mode & GLUSTER_MODE_XML) {
- ret = cli_xml_output_str ("volQuota", msg, rsp.op_ret,
+ ret = cli_xml_output_str ("volQuota", NULL, rsp.op_ret,
rsp.op_errno, rsp.op_errstr);
if (ret)
gf_log ("cli", GF_LOG_ERROR,
@@ -2501,12 +2720,8 @@ xml_output:
goto out;
}
- if (strlen (msg) > 0) {
- if (rsp.op_ret)
- cli_err ("%s", msg);
- else
- cli_out ("%s", msg);
- }
+ if (!rsp.op_ret && type != GF_QUOTA_OPTION_TYPE_LIST)
+ cli_out ("volume quota : success");
ret = rsp.op_ret;
out:
@@ -2700,7 +2915,7 @@ gf_cli_list_friends (call_frame_t *frame, xlator_t *this,
flags = (long)data;
req.flags = flags;
frame->local = (void*)flags;
- ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,
GLUSTER_CLI_LIST_FRIENDS, NULL,
this, gf_cli_list_friends_cbk,
(xdrproc_t) xdr_gf1_cli_peer_list_req);
@@ -2814,7 +3029,7 @@ gf_cli_get_volume (call_frame_t *frame, xlator_t *this,
ret = dict_allocate_and_serialize (dict, &req.dict.dict_val,
&req.dict.dict_len);
- ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,
GLUSTER_CLI_GET_VOLUME, NULL,
this, gf_cli_get_volume_cbk,
(xdrproc_t) xdr_gf_cli_req);
@@ -3033,7 +3248,7 @@ gf_cli_rename_volume (call_frame_t *frame, xlator_t *this,
}
- ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,
GLUSTER_CLI_RENAME_VOLUME, NULL,
this, gf_cli_rename_volume_cbk,
(xdrproc_t) xdr_gf_cli_req);
@@ -3385,7 +3600,7 @@ gf_cli_getspec (call_frame_t *frame, xlator_t *this,
goto out;
}
- ret = cli_cmd_submit (&req, frame, &cli_handshake_prog,
+ ret = cli_cmd_submit (NULL, &req, frame, &cli_handshake_prog,
GF_HNDSK_GETSPEC, NULL,
this, gf_cli_getspec_cbk,
(xdrproc_t) xdr_gf_getspec_req);
@@ -3442,7 +3657,7 @@ gf_cli_pmap_b2p (call_frame_t *frame, xlator_t *this, void *data)
if (ret)
goto out;
- ret = cli_cmd_submit (&req, frame, &cli_pmap_prog,
+ ret = cli_cmd_submit (NULL, &req, frame, &cli_pmap_prog,
GF_PMAP_PORTBYBRICK, NULL,
this, gf_cli_pmap_b2p_cbk,
(xdrproc_t) xdr_pmap_port_by_brick_req);
@@ -3557,7 +3772,7 @@ gf_cli_fsm_log (call_frame_t *frame, xlator_t *this, void *data)
if (!frame || !this || !data)
goto out;
req.name = data;
- ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,
GLUSTER_CLI_FSM_LOG, NULL,
this, gf_cli_fsm_log_cbk,
(xdrproc_t) xdr_gf1_cli_fsm_log_req);
@@ -5125,7 +5340,7 @@ gf_cli_getwd (call_frame_t *frame, xlator_t *this, void *data)
if (!frame || !this)
goto out;
- ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,
GLUSTER_CLI_GETWD, NULL,
this, gf_cli_getwd_cbk,
(xdrproc_t) xdr_gf1_cli_getwd_req);
@@ -6329,7 +6544,8 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov,
goto out;
}
- if ((cmd & GF_CLI_STATUS_NFS) || (cmd & GF_CLI_STATUS_SHD))
+ if ((cmd & GF_CLI_STATUS_NFS) || (cmd & GF_CLI_STATUS_SHD) ||
+ (cmd & GF_CLI_STATUS_QUOTAD))
notbrick = _gf_true;
if (global_state->mode & GLUSTER_MODE_XML) {
@@ -6444,7 +6660,8 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov,
*/
memset (status.brick, 0, PATH_MAX + 255);
if (!strcmp (hostname, "NFS Server") ||
- !strcmp (hostname, "Self-heal Daemon"))
+ !strcmp (hostname, "Self-heal Daemon") ||
+ !strcmp (hostname, "Quota Daemon"))
snprintf (status.brick, PATH_MAX + 255, "%s on %s",
hostname, path);
else
@@ -6694,7 +6911,7 @@ gf_cli_mount (call_frame_t *frame, xlator_t *this, void *data)
goto out;
}
- ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,
GLUSTER_CLI_MOUNT, NULL,
this, gf_cli_mount_cbk,
(xdrproc_t)xdr_gf1_cli_mount_req);
@@ -6757,7 +6974,7 @@ gf_cli_umount (call_frame_t *frame, xlator_t *this, void *data)
goto out;
}
- ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,
GLUSTER_CLI_UMOUNT, NULL,
this, gf_cli_umount_cbk,
(xdrproc_t)xdr_gf1_cli_umount_req);
@@ -7326,7 +7543,7 @@ gf_cli_list_volume (call_frame_t *frame, xlator_t *this, void *data)
if (!frame || !this)
goto out;
- ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,
GLUSTER_CLI_LIST_VOLUME, NULL,
this, gf_cli_list_volume_cbk,
(xdrproc_t)xdr_gf_cli_req);
@@ -7499,7 +7716,7 @@ cli_to_glusterd (gf_cli_req *req, call_frame_t *frame,
goto out;
}
- ret = cli_cmd_submit (req, frame, prog, procnum, iobref, this,
+ ret = cli_cmd_submit (NULL, req, frame, prog, procnum, iobref, this,
cbkfn, (xdrproc_t) xdrproc);
out:
@@ -7556,3 +7773,17 @@ struct rpc_clnt_program cli_prog = {
.numproc = GLUSTER_CLI_MAXVALUE,
.proctable = gluster_cli_actors,
};
+
+struct rpc_clnt_procedure cli_quotad_procs[GF_AGGREGATOR_MAXVALUE] = {
+ [GF_AGGREGATOR_NULL] = {"NULL", NULL},
+ [GF_AGGREGATOR_LOOKUP] = {"LOOKUP", NULL},
+ [GF_AGGREGATOR_GETLIMIT] = {"GETLIMIT", cli_quotad_getlimit},
+};
+
+struct rpc_clnt_program cli_quotad_clnt = {
+ .progname = "CLI Quotad client",
+ .prognum = GLUSTER_AGGREGATOR_PROGRAM,
+ .progver = GLUSTER_AGGREGATOR_VERSION,
+ .numproc = GF_AGGREGATOR_MAXVALUE,
+ .proctable = cli_quotad_procs,
+};
diff --git a/cli/src/cli.c b/cli/src/cli.c
index 91b315ff169..67f1ad25793 100644
--- a/cli/src/cli.c
+++ b/cli/src/cli.c
@@ -45,6 +45,7 @@
#endif
#include "cli.h"
+#include "cli-quotad-client.h"
#include "cli-cmd.h"
#include "cli-mem-types.h"
@@ -82,6 +83,7 @@ const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
+struct rpc_clnt *global_quotad_rpc;
struct rpc_clnt *global_rpc;
rpc_clnt_prog_t *cli_rpc_prog;
@@ -184,7 +186,7 @@ logging_init (glusterfs_ctx_t *ctx, struct cli_state *state)
}
int
-cli_submit_request (void *req, call_frame_t *frame,
+cli_submit_request (struct rpc_clnt *rpc, void *req, call_frame_t *frame,
rpc_clnt_prog_t *prog,
int procnum, struct iobref *iobref,
xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc)
@@ -229,8 +231,10 @@ cli_submit_request (void *req, call_frame_t *frame,
count = 1;
}
+ if (!rpc)
+ rpc = global_rpc;
/* Send the msg */
- ret = rpc_clnt_submit (global_rpc, prog, procnum, cbkfn,
+ ret = rpc_clnt_submit (rpc, prog, procnum, cbkfn,
&iov, count,
NULL, 0, iobref, frame, NULL, 0, NULL, 0, NULL);
ret = 0;
@@ -491,6 +495,42 @@ _cli_out (const char *fmt, ...)
}
struct rpc_clnt *
+cli_quotad_clnt_rpc_init (void)
+{
+ struct rpc_clnt *rpc = NULL;
+ dict_t *rpc_opts = NULL;
+ int ret = -1;
+
+ rpc_opts = dict_new ();
+ if (!rpc_opts) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = dict_set_str (rpc_opts, "transport.address-family", "unix");
+ if (ret)
+ goto out;
+
+ ret = dict_set_str (rpc_opts, "transport-type", "socket");
+ if (ret)
+ goto out;
+
+ ret = dict_set_str (rpc_opts, "transport.socket.connect-path",
+ "/tmp/quotad.socket");
+ if (ret)
+ goto out;
+
+ rpc = cli_quotad_clnt_init (THIS, rpc_opts);
+ if (!rpc)
+ goto out;
+
+ global_quotad_rpc = rpc;
+out:
+ dict_unref (rpc_opts);
+ return rpc;
+}
+
+struct rpc_clnt *
cli_rpc_init (struct cli_state *state)
{
struct rpc_clnt *rpc = NULL;
@@ -634,6 +674,10 @@ main (int argc, char *argv[])
if (!global_rpc)
goto out;
+ global_quotad_rpc = cli_quotad_clnt_rpc_init ();
+ if (!global_quotad_rpc)
+ goto out;
+
ret = cli_cmds_register (&state);
if (ret)
goto out;
diff --git a/cli/src/cli.h b/cli/src/cli.h
index bc71ee2b4f0..b71140a810b 100644
--- a/cli/src/cli.h
+++ b/cli/src/cli.h
@@ -45,6 +45,13 @@ enum argp_option_keys {
#define GLUSTER_MODE_SCRIPT (1 << 0)
#define GLUSTER_MODE_ERR_FATAL (1 << 1)
#define GLUSTER_MODE_XML (1 << 2)
+
+
+#define GLUSTERFS_GET_AUX_MOUNT_PIDFILE(pidfile,volname) { \
+ snprintf (pidfile, PATH_MAX-1, \
+ DEFAULT_VAR_RUN_DIRECTORY"/%s.pid", volname); \
+ }
+
struct cli_state;
struct cli_cmd_word;
struct cli_cmd_tree;
@@ -212,7 +219,7 @@ int _cli_err (const char *fmt, ...);
} while (0)
int
-cli_submit_request (void *req, call_frame_t *frame,
+cli_submit_request (struct rpc_clnt *rpc, void *req, call_frame_t *frame,
rpc_clnt_prog_t *prog,
int procnum, struct iobref *iobref,
xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc);