summaryrefslogtreecommitdiffstats
path: root/xlators/mgmt/glusterd
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mgmt/glusterd')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-handler.c23
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-quota.c720
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c216
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h22
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.c228
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.h2
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-ops.c58
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-set.c68
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.c19
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.h10
10 files changed, 1117 insertions, 249 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c
index a74c5230..ac508f0c 100644
--- a/xlators/mgmt/glusterd/src/glusterd-handler.c
+++ b/xlators/mgmt/glusterd/src/glusterd-handler.c
@@ -54,6 +54,8 @@
#include <lvm2app.h>
#endif
+extern glusterd_op_info_t opinfo;
+
int glusterd_big_locked_notify (struct rpc_clnt *rpc, void *mydata,
rpc_clnt_event_t event,
void *data, rpc_clnt_notify_t notify_fn)
@@ -307,10 +309,23 @@ _build_option_key (dict_t *d, char *k, data_t *v, void *tmp)
char reconfig_key[256] = {0, };
struct args_pack *pack = NULL;
int ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
pack = tmp;
if (strcmp (k, GLUSTERD_GLOBAL_OPT_VERSION) == 0)
return 0;
+
+ if (priv->op_version > GD_OP_VERSION_MIN) {
+ if ((strcmp (k, "features.limit-usage") == 0) ||
+ (strcmp (k, "features.soft-limit") == 0))
+ return 0;
+ }
snprintf (reconfig_key, 256, "volume%d.option.%s",
pack->vol_count, k);
ret = dict_set_str (pack->dict, reconfig_key, v->data);
@@ -3776,6 +3791,7 @@ __glusterd_peer_rpc_notify (struct rpc_clnt *rpc, void *mydata,
glusterd_peerinfo_t *peerinfo = NULL;
glusterd_peerctx_t *peerctx = NULL;
gf_boolean_t quorum_action = _gf_false;
+ uuid_t uuid;
peerctx = mydata;
if (!peerctx)
@@ -3817,6 +3833,13 @@ __glusterd_peer_rpc_notify (struct rpc_clnt *rpc, void *mydata,
glusterd_friend_remove_notify (peerctx);
goto out;
}
+ glusterd_get_lock_owner (&uuid);
+ if (!uuid_is_null (uuid) &&
+ !uuid_compare (peerinfo->uuid, uuid)) {
+ glusterd_unlock (peerinfo->uuid);
+ if (opinfo.state.state != GD_OP_STATE_DEFAULT)
+ opinfo.state.state = GD_OP_STATE_DEFAULT;
+ }
peerinfo->connected = 0;
break;
diff --git a/xlators/mgmt/glusterd/src/glusterd-quota.c b/xlators/mgmt/glusterd/src/glusterd-quota.c
index 31826719..ec4a6eb8 100644
--- a/xlators/mgmt/glusterd/src/glusterd-quota.c
+++ b/xlators/mgmt/glusterd/src/glusterd-quota.c
@@ -24,6 +24,22 @@
#include <sys/wait.h>
+
+const char *gd_quota_op_list[GF_QUOTA_OPTION_TYPE_DEFAULT_SOFT_LIMIT+1] = {
+ [GF_QUOTA_OPTION_TYPE_NONE] = "none",
+ [GF_QUOTA_OPTION_TYPE_ENABLE] = "enable",
+ [GF_QUOTA_OPTION_TYPE_DISABLE] = "disable",
+ [GF_QUOTA_OPTION_TYPE_LIMIT_USAGE] = "limit-usage",
+ [GF_QUOTA_OPTION_TYPE_REMOVE] = "remove",
+ [GF_QUOTA_OPTION_TYPE_LIST] = "list",
+ [GF_QUOTA_OPTION_TYPE_VERSION] = "version",
+ [GF_QUOTA_OPTION_TYPE_SOFT_LIMIT] = "soft-limit",
+ [GF_QUOTA_OPTION_TYPE_ALERT_TIME] = "alert-time",
+ [GF_QUOTA_OPTION_TYPE_SOFT_TIMEOUT] = "soft-timeout",
+ [GF_QUOTA_OPTION_TYPE_HARD_TIMEOUT] = "hard-timeout",
+ [GF_QUOTA_OPTION_TYPE_DEFAULT_SOFT_LIMIT] = "default-soft-limit",
+};
+
int
__glusterd_handle_quota (rpcsvc_request_t *req)
{
@@ -31,15 +47,17 @@ __glusterd_handle_quota (rpcsvc_request_t *req)
gf_cli_req cli_req = {{0,}};
dict_t *dict = NULL;
glusterd_op_t cli_op = GD_OP_QUOTA;
- char operation[256] = {0, };
char *volname = NULL;
int32_t type = 0;
char msg[2048] = {0,};
xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
GF_ASSERT (req);
this = THIS;
GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
if (ret < 0) {
@@ -82,23 +100,16 @@ __glusterd_handle_quota (rpcsvc_request_t *req)
goto out;
}
- switch (type) {
- case GF_QUOTA_OPTION_TYPE_ENABLE:
- strncpy (operation, "enable", sizeof (operation));
- break;
-
- case GF_QUOTA_OPTION_TYPE_DISABLE:
- strncpy (operation, "disable", sizeof (operation));
- break;
-
- case GF_QUOTA_OPTION_TYPE_LIMIT_USAGE:
- strncpy (operation, "limit-usage", sizeof (operation));
- break;
+ if ((conf->op_version == GD_OP_VERSION_MIN) &&
+ (type > GF_QUOTA_OPTION_TYPE_VERSION)) {
+ snprintf (msg, sizeof (msg), "Cannot execute command. The "
+ "cluster is operating at version 1. Executing command "
+ "%s is disallowed in this state",
+ gd_quota_op_list[type]);
+ ret = -1;
+ goto out;
+ }
- case GF_QUOTA_OPTION_TYPE_REMOVE:
- strncpy (operation, "remove", sizeof (operation));
- break;
- }
ret = glusterd_op_begin_synctask (req, GD_OP_QUOTA, dict);
out:
@@ -132,7 +143,6 @@ glusterd_check_if_quota_trans_enabled (glusterd_volinfo_t *volinfo)
}
if (flag == _gf_false) {
- gf_log ("", GF_LOG_ERROR, "first enable the quota translator");
ret = -1;
goto out;
}
@@ -141,13 +151,21 @@ out:
return ret;
}
-/* At the end of the function, the variable found will be set
+/* At the end of the function, the variable @found will be set
* to true if the path to be removed was present in the limit-list,
* else will be false.
+ *
+ * In addition, the function does the following things:
+ *
+ * a. places the path to be removed, if found, in @removed_path,
+ * b. places the new limit list formed after removing @path's entry, in
+ * @new_list. If @path is not found, the input limit string @quota_limits is
+ * dup'd as is and placed in @new_list.
*/
int32_t
-_glusterd_quota_remove_limits (char **quota_limits, char *path,
- gf_boolean_t *found)
+_glusterd_quota_remove_limits (char *quota_limits, char *path,
+ gf_boolean_t *found, char **new_list,
+ char **removed_path)
{
int ret = 0;
int i = 0;
@@ -158,14 +176,15 @@ _glusterd_quota_remove_limits (char **quota_limits, char *path,
int flag = 0;
char *limits = NULL;
char *qlimits = NULL;
+ char *rp = NULL;
if (found != NULL)
*found = _gf_false;
- if (*quota_limits == NULL)
+ if (quota_limits == NULL)
return -1;
- qlimits = *quota_limits;
+ qlimits = quota_limits;
pathlen = strlen (path);
@@ -192,6 +211,15 @@ _glusterd_quota_remove_limits (char **quota_limits, char *path,
} else {
skiplen = size + 1;
size = len - i - size;
+ if (removed_path) {
+ rp = GF_CALLOC (skiplen, sizeof (char), gf_gld_mt_char);
+ if (!rp) {
+ ret = -1;
+ goto out;
+ }
+ strncpy (rp, &qlimits[i], skiplen - 1);
+ *removed_path = rp;
+ }
memcpy ((void *) &limits [i], (void *) &qlimits [i + skiplen], size);
break;
}
@@ -200,42 +228,27 @@ _glusterd_quota_remove_limits (char **quota_limits, char *path,
size = 0;
}
- if (!flag) {
- ret = 1;
- } else {
- len = strlen (limits);
-
- if (len == 0) {
- GF_FREE (qlimits);
-
- *quota_limits = NULL;
-
- goto out;
- }
-
- if (limits[len - 1] == ',') {
- limits[len - 1] = '\0';
- len --;
- }
-
- GF_FREE (qlimits);
-
- qlimits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char);
-
- if (!qlimits) {
- ret = -1;
- goto out;
- }
-
- memcpy ((void *) qlimits, (void *) limits, len + 1);
+ len = strlen (limits);
+ if (len == 0)
+ goto out;
- *quota_limits = qlimits;
+ if (limits[len - 1] == ',') {
+ limits[len - 1] = '\0';
+ len --;
+ }
- ret = 0;
+ *new_list = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char);
+ if (!*new_list) {
+ ret = -1;
+ goto out;
}
+ memcpy ((void *) *new_list, (void *) limits, len + 1);
+ ret = 0;
out:
GF_FREE (limits);
+ if (ret != -1)
+ ret = flag ? 0 : 1;
return ret;
}
@@ -381,22 +394,30 @@ _glusterd_quota_get_limit_usages (glusterd_volinfo_t *volinfo,
int32_t
glusterd_quota_get_limit_usages (glusterd_conf_t *priv,
- glusterd_volinfo_t *volinfo,
- char *volname,
- dict_t *dict,
- char **op_errstr,
+ glusterd_volinfo_t *volinfo, char *volname,
+ dict_t *dict, char **op_errstr,
dict_t *rsp_dict)
{
- int32_t i = 0;
- int32_t ret = 0;
- int32_t count = 0;
- char *path = NULL;
- char cmd_str [1024] = {0, };
- char *ret_str = NULL;
+ int32_t i = 0;
+ int32_t ret = 0;
+ int32_t count = 0;
+ int entry_count = 0;
+ char *path = NULL;
+ char cmd_str [1024] = {0, };
+ char *ret_str = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ char *default_limit = NULL;
+ char *val = NULL;
if (rsp_dict == NULL)
return 0;
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
+
ret = dict_get_int32 (dict, "count", &count);
if (ret < 0)
goto out;
@@ -404,22 +425,60 @@ glusterd_quota_get_limit_usages (glusterd_conf_t *priv,
if (count == 0) {
ret_str = _glusterd_quota_get_limit_usages (volinfo, NULL,
op_errstr);
+ ret = dict_set_dynstr (rsp_dict, "limit_list", ret_str);
+ if (ret)
+ goto out;
} else {
i = 0;
while (count--) {
- snprintf (cmd_str, 1024, "path%d", i++);
+ snprintf (cmd_str, sizeof (cmd_str), "path%d", i++);
ret = dict_get_str (dict, cmd_str, &path);
if (ret < 0)
goto out;
+ ret = gf_canonicalize_path (path);
+ if (ret) {
+ goto out;
+ }
- ret_str = _glusterd_quota_get_limit_usages (volinfo, path, op_errstr);
+ ret_str = _glusterd_quota_get_limit_usages (volinfo,
+ path,
+ op_errstr);
+ /* Despite quota limits being absent on @path, we go
+ * ahead and place it in @rsp_dict with
+ * value = "Not set". This is because after commit op,
+ * as part of aggregation of @rsp_dict with @op_ctx,
+ * when we copy the rsp_dict into op_ctx, op_ctx would
+ * still be containing the old key (same as @cmd_str)
+ * with the old value. In order to overwrite the old
+ * value, we replace it with "Not set", something that
+ * the cli can easily interpret as a case of quota
+ * limits not having been set on the given path.
+ */
+ if (!ret_str) {
+ ret = dict_set_str (rsp_dict, cmd_str,
+ "Not set");
+ } else {
+ ret = dict_set_dynstr (rsp_dict, cmd_str,
+ ret_str);
+ entry_count = entry_count + 1;
+ }
}
}
+ ret = dict_set_int32 (rsp_dict, "entry-count", entry_count);
+ if (ret)
+ goto out;
- if (ret_str) {
- ret = dict_set_dynstr (rsp_dict, "limit_list", ret_str);
- }
+ ret = dict_set_uint32 (rsp_dict, "op-version", conf->op_version);
+
+ ret = glusterd_volinfo_get (volinfo, "features.default-soft-limit",
+ &default_limit);
+ if (default_limit)
+ val = gf_strdup (default_limit);
+ else
+ val = gf_strdup ("90%");
+
+ ret = dict_set_dynstr (rsp_dict, "default-soft-limit", val);
out:
return ret;
}
@@ -430,10 +489,14 @@ glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr,
{
int32_t ret = -1;
char *quota_status = NULL;
+ xlator_t *this = NULL;
- GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
- GF_VALIDATE_OR_GOTO ("glusterd", crawl, out);
- GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out);
+ this = THIS;
+ GF_ASSERT (this);
+
+ GF_VALIDATE_OR_GOTO (this->name, volinfo, out);
+ GF_VALIDATE_OR_GOTO (this->name, crawl, out);
+ GF_VALIDATE_OR_GOTO (this->name, op_errstr, out);
if (glusterd_is_volume_started (volinfo) == 0) {
*op_errstr = gf_strdup ("Volume is stopped, start volume "
@@ -449,15 +512,15 @@ glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr,
quota_status = gf_strdup ("on");
if (!quota_status) {
- gf_log ("", GF_LOG_ERROR, "memory allocation failed");
- *op_errstr = gf_strdup ("Enabling quota has been unsuccessful");
+ gf_log (this->name, GF_LOG_ERROR, "memory allocation failed");
+ ret = -1;
goto out;
}
- ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status);
+ ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA,
+ quota_status);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "dict set failed");
- *op_errstr = gf_strdup ("Enabling quota has been unsuccessful");
+ gf_log (this->name, GF_LOG_ERROR, "dict set failed");
goto out;
}
@@ -467,17 +530,34 @@ glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr,
ret = 0;
out:
+ if (ret && op_errstr && !*op_errstr)
+ gf_asprintf (op_errstr, "Enabling quota on volume %s has been "
+ "unsuccessful", volinfo->volname);
return ret;
}
int32_t
glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr)
{
- int32_t ret = -1;
- char *quota_status = NULL, *quota_limits = NULL;
+ int32_t ret = -1;
+ int i = 0;
+ char *quota_status = NULL;
+ char *value = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ char *quota_options[] = {VKEY_FEATURES_LIMIT_USAGE,
+ "features.soft-timeout",
+ "features.hard-timeout",
+ "features.alert-time",
+ "features.default-soft-limit", NULL};
- GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
- GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out);
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
+
+ GF_VALIDATE_OR_GOTO (this->name, volinfo, out);
+ GF_VALIDATE_OR_GOTO (this->name, op_errstr, out);
ret = glusterd_check_if_quota_trans_enabled (volinfo);
if (ret == -1) {
@@ -487,47 +567,84 @@ glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr)
quota_status = gf_strdup ("off");
if (!quota_status) {
- gf_log ("", GF_LOG_ERROR, "memory allocation failed");
- *op_errstr = gf_strdup ("Disabling quota has been unsuccessful");
+ gf_log (this->name, GF_LOG_ERROR, "memory allocation failed");
+ ret = -1;
goto out;
}
ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "dict set failed");
- *op_errstr = gf_strdup ("Disabling quota has been unsuccessful");
+ gf_log (this->name, GF_LOG_ERROR, "dict set failed");
goto out;
}
+ for (i = 0; quota_options [i]; i++) {
+ ret = glusterd_volinfo_get (volinfo, quota_options[i], &value);
+ if (ret) {
+ gf_log (this->name, GF_LOG_INFO, "failed to get option"
+ " %s",
+ quota_options[i]);
+ } else {
+ dict_del (volinfo->dict, quota_options[i]);
+ }
+ if ((i == 0) && (conf->op_version == GD_OP_VERSION_MIN))
+ break;
+ }
+
*op_errstr = gf_strdup ("Disabling quota has been successful");
+ ret = 0;
+out:
+ if (ret && op_errstr && !*op_errstr)
+ gf_asprintf (op_errstr, "Disabling quota on volume %s has been "
+ "unsuccessful", volinfo->volname);
+ return ret;
+}
- ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE,
- &quota_limits);
- if (ret) {
- gf_log ("", GF_LOG_WARNING, "failed to get the quota limits");
+static void
+gd_quota_get_formatted_limit_list (char **value, char *existing_list,
+ char *path, char *hard_limit,
+ char *soft_limit)
+{
+ if (!existing_list) {
+ if (!soft_limit)
+ gf_asprintf (value, "%s:%s", path, hard_limit);
+ else
+ gf_asprintf (value, "%s:%s:%s", path, hard_limit,
+ soft_limit);
} else {
- GF_FREE (quota_limits);
+ if (!soft_limit)
+ gf_asprintf (value, "%s,%s:%s", existing_list, path,
+ hard_limit);
+ else
+ gf_asprintf (value, "%s,%s:%s:%s", existing_list, path,
+ hard_limit, soft_limit);
}
-
- dict_del (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE);
-
-out:
- return ret;
}
int32_t
-glusterd_quota_limit_usage (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr)
+glusterd_quota_limit_usage (glusterd_volinfo_t *volinfo, dict_t *dict,
+ char **op_errstr)
{
- int32_t ret = -1;
- char *path = NULL;
- char *limit = NULL;
- char *value = NULL;
- char msg [1024] = {0,};
- char *quota_limits = NULL;
+ int32_t ret = -1;
+ char *path = NULL;
+ char *limit = NULL;
+ char *value = NULL;
+ char *sl = NULL;
+ char msg[5120] = {0,};
+ char *quota_limits = NULL;
+ char *new_list = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ char *removed_path = NULL;
- GF_VALIDATE_OR_GOTO ("glusterd", dict, out);
- GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
- GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out);
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ GF_VALIDATE_OR_GOTO (this->name, dict, out);
+ GF_VALIDATE_OR_GOTO (this->name, volinfo, out);
+ GF_VALIDATE_OR_GOTO (this->name, op_errstr, out);
ret = glusterd_check_if_quota_trans_enabled (volinfo);
if (ret == -1) {
@@ -539,109 +656,222 @@ glusterd_quota_limit_usage (glusterd_volinfo_t *volinfo, dict_t *dict, char **op
ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE,
&quota_limits);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "failed to get the quota limits");
- *op_errstr = gf_strdup ("failed to set limit");
+ gf_log (this->name, GF_LOG_ERROR, "failed to get quota limits");
goto out;
}
ret = dict_get_str (dict, "path", &path);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" );
- *op_errstr = gf_strdup ("failed to set limit");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to fetch path");
goto out;
}
+ ret = gf_canonicalize_path (path);
+ if (ret)
+ goto out;
ret = dict_get_str (dict, "limit", &limit);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" );
- *op_errstr = gf_strdup ("failed to set limit");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to fetch limit");
goto out;
}
- if (quota_limits) {
- ret = _glusterd_quota_remove_limits (&quota_limits, path, NULL);
- if (ret == -1) {
- gf_log ("", GF_LOG_ERROR, "Unable to allocate memory");
- *op_errstr = gf_strdup ("failed to set limit");
- goto out;
- }
- }
-
if (quota_limits == NULL) {
- ret = gf_asprintf (&value, "%s:%s", path, limit);
- if (ret == -1) {
- gf_log ("", GF_LOG_ERROR, "Unable to allocate memory");
- *op_errstr = gf_strdup ("failed to set limit");
- goto out;
- }
+ ; //do nothing and go past the else block
} else {
- ret = gf_asprintf (&value, "%s,%s:%s",
- quota_limits, path, limit);
+ ret = _glusterd_quota_remove_limits (quota_limits, path, NULL,
+ &new_list, &removed_path);
if (ret == -1) {
- gf_log ("", GF_LOG_ERROR, "Unable to allocate memory");
- *op_errstr = gf_strdup ("failed to set limit");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to remove "
+ "limit");
goto out;
}
- GF_FREE (quota_limits);
+ if (removed_path && (priv->op_version > GD_OP_VERSION_MIN)) {
+ ret = gf_get_soft_limit (removed_path, &sl);
+ if (ret == -1)
+ goto out;
+ }
}
-
- quota_limits = value;
+ gd_quota_get_formatted_limit_list (&value, new_list, path, limit, sl);
ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE,
- quota_limits);
+ value);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" );
- *op_errstr = gf_strdup ("failed to set limit");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to set quota limits");
goto out;
}
- snprintf (msg, 1024, "limit set on %s", path);
- *op_errstr = gf_strdup (msg);
+ snprintf (msg, sizeof (msg), "hard limit set on %s", path);
+ *op_errstr = gf_strdup (msg);
ret = 0;
out:
+ GF_FREE (sl);
+ GF_FREE (removed_path);
+ GF_FREE (new_list);
+
+ if (ret && op_errstr && !*op_errstr)
+ gf_asprintf (op_errstr, "Failed to set hard limit on path %s "
+ "for volume %s", path, volinfo->volname);
+ return ret;
+}
+
+int
+glusterd_quota_soft_limit (glusterd_volinfo_t *volinfo, dict_t *dict,
+ char **op_errstr)
+{
+ int ret = 0;
+ char *path = NULL;
+ char *limit = NULL;
+ char *quota_limits = NULL;
+ char *new_list = NULL;
+ char *removed_path = NULL;
+ char msg[1024] = {0,};
+ char *hl = NULL;
+ char *value = NULL;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ if (!volinfo || !dict || !op_errstr) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = glusterd_check_if_quota_trans_enabled (volinfo);
+ if (ret == -1) {
+ *op_errstr = gf_strdup ("Quota is disabled, please enable "
+ "quota");
+ goto out;
+ }
+
+ ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE,
+ &quota_limits);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to get quota limits");
+ goto out;
+ }
+
+ ret = dict_get_str (dict, "path", &path);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Unable to fetch path");
+ goto out;
+ }
+
+ ret = gf_canonicalize_path (path);
+ if (ret)
+ goto out;
+
+ ret = dict_get_str (dict, "limit", &limit);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Unable to fetch limit");
+ goto out;
+ }
+
+ if (quota_limits == NULL) {
+ gf_asprintf (op_errstr, "Soft-limit cannot be set on path %s, "
+ "without setting hard-limit on it first.", path);
+ ret = -1;
+ goto out;
+ } else {
+ ret = _glusterd_quota_remove_limits (quota_limits, path, NULL,
+ &new_list, &removed_path);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to remove "
+ "limit");
+ goto out;
+ }
+
+ if (!removed_path) {
+ gf_asprintf (op_errstr, "Soft-limit cannot be set on "
+ "path %s without setting hard-limit on it "
+ "first.", path);
+ ret = -1;
+ goto out;
+ } else {
+ ret = gf_get_hard_limit (removed_path, &hl);
+ if (ret)
+ goto out;
+ }
+ }
+
+ gd_quota_get_formatted_limit_list (&value, new_list, path, hl, limit);
+
+ ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE,
+ value);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Unable to set quota limits");
+ goto out;
+ }
+
+ snprintf (msg, sizeof (msg), "soft limit set on %s", path);
+ *op_errstr = gf_strdup (msg);
+ ret = 0;
+
+out:
+ GF_FREE (hl);
+ GF_FREE (removed_path);
+ GF_FREE (new_list);
+
+ if (ret && op_errstr && !*op_errstr)
+ gf_asprintf (op_errstr, "Failed to set soft limit for path %s "
+ "on volume %s", path, volinfo->volname);
return ret;
}
int32_t
-glusterd_quota_remove_limits (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr)
+glusterd_quota_remove_limits (glusterd_volinfo_t *volinfo, dict_t *dict,
+ char **op_errstr)
{
int32_t ret = -1;
char str [PATH_MAX + 1024] = {0,};
char *quota_limits = NULL;
+ char *new_list = NULL;
+ char *value = NULL;
char *path = NULL;
gf_boolean_t flag = _gf_false;
+ xlator_t *this = NULL;
- GF_VALIDATE_OR_GOTO ("glusterd", dict, out);
- GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out);
- GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out);
+ this = THIS;
+ GF_ASSERT (this);
+
+ GF_VALIDATE_OR_GOTO (this->name, dict, out);
+ GF_VALIDATE_OR_GOTO (this->name, volinfo, out);
+ GF_VALIDATE_OR_GOTO (this->name, op_errstr, out);
ret = glusterd_check_if_quota_trans_enabled (volinfo);
if (ret == -1) {
- *op_errstr = gf_strdup ("Quota is disabled, please enable quota");
+ *op_errstr = gf_strdup ("Quota is disabled, please enable "
+ "quota");
goto out;
}
ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE,
&quota_limits);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "failed to get the quota limits");
+ gf_log (this->name, GF_LOG_ERROR, "failed to get quota limits");
goto out;
}
ret = dict_get_str (dict, "path", &path);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" );
+ gf_log (this->name, GF_LOG_ERROR, "Unable to fetch path");
goto out;
}
- ret = _glusterd_quota_remove_limits (&quota_limits, path, &flag);
+ ret = gf_canonicalize_path (path);
+ if (ret)
+ goto out;
+
+ ret = _glusterd_quota_remove_limits (quota_limits, path, &flag,
+ &new_list, NULL);
if (ret == -1) {
if (flag == _gf_true)
snprintf (str, sizeof (str), "Removing limit on %s has "
"been unsuccessful", path);
else
- snprintf (str, sizeof (str), "%s has no limit set", path);
+ snprintf (str, sizeof (str), "%s has no limit set",
+ path);
*op_errstr = gf_strdup (str);
goto out;
} else {
@@ -654,11 +884,13 @@ glusterd_quota_remove_limits (glusterd_volinfo_t *volinfo, dict_t *dict, char **
*op_errstr = gf_strdup (str);
}
- if (quota_limits) {
+ if (new_list) {
+ value = gf_strdup (new_list);
ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE,
- quota_limits);
+ value);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" );
+ gf_log (this->name, GF_LOG_ERROR, "Unable to set quota "
+ "limits");
goto out;
}
} else {
@@ -668,9 +900,46 @@ glusterd_quota_remove_limits (glusterd_volinfo_t *volinfo, dict_t *dict, char **
ret = 0;
out:
+ GF_FREE (new_list);
return ret;
}
+int
+glusterd_set_quota_option (glusterd_volinfo_t *volinfo, dict_t *dict,
+ char *key, char **op_errstr)
+{
+ int ret = 0;
+ char *value = NULL;
+ xlator_t *this = NULL;
+ char *option = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ ret = glusterd_check_if_quota_trans_enabled (volinfo);
+ if (ret == -1) {
+ gf_asprintf (op_errstr, "Cannot set %s. Quota on volume %s is "
+ "disabled", key, volinfo->volname);
+ return -1;
+ }
+
+ ret = dict_get_str (dict, "value", &value);
+ if(ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Option value absent.");
+ return -1;
+ }
+
+ option = gf_strdup (value);
+ ret = dict_set_dynstr (volinfo->dict, key, option);
+ if(ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to set option %s",
+ key);
+ return -1;
+ }
+ gf_asprintf (op_errstr, "%s on volume %s set", key, volinfo->volname);
+
+ return 0;
+}
int
glusterd_op_quota (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
@@ -681,26 +950,41 @@ glusterd_op_quota (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
int type = -1;
gf_boolean_t start_crawl = _gf_false;
glusterd_conf_t *priv = NULL;
+ xlator_t *this = NULL;
GF_ASSERT (dict);
GF_ASSERT (op_errstr);
- priv = THIS->private;
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get volume name " );
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name");
goto out;
}
ret = glusterd_volinfo_find (volname, &volinfo);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to allocate memory");
+ gf_asprintf (op_errstr, FMTSTR_CHECK_VOL_EXISTS, volname);
goto out;
}
ret = dict_get_int32 (dict, "type", &type);
+ if ((priv->op_version == GD_OP_VERSION_MIN) &&
+ (type > GF_QUOTA_OPTION_TYPE_VERSION)) {
+ gf_asprintf (op_errstr, "Volume quota failed. The cluster is "
+ "operating at version %d. Option %s "
+ "is disallowed in this state.",
+ priv->op_version,
+ gd_quota_op_list[type]);
+ ret = -1;
+ goto out;
+ }
+
if (type == GF_QUOTA_OPTION_TYPE_ENABLE) {
ret = glusterd_quota_enable (volinfo, op_errstr, &start_crawl);
if (ret < 0)
@@ -708,7 +992,6 @@ glusterd_op_quota (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
goto create_vol;
}
-
if (type == GF_QUOTA_OPTION_TYPE_DISABLE) {
ret = glusterd_quota_disable (volinfo, op_errstr);
if (ret < 0)
@@ -742,15 +1025,59 @@ glusterd_op_quota (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
}
ret = glusterd_quota_get_limit_usages (priv, volinfo, volname,
- dict, op_errstr, rsp_dict);
+ dict, op_errstr,
+ rsp_dict);
goto out;
}
+
+ if (type == GF_QUOTA_OPTION_TYPE_SOFT_LIMIT) {
+ ret = glusterd_quota_soft_limit (volinfo, dict, op_errstr);
+ if (ret < 0)
+ goto out;
+ goto create_vol;
+ }
+
+ if (type == GF_QUOTA_OPTION_TYPE_SOFT_TIMEOUT) {
+ ret = glusterd_set_quota_option (volinfo, dict,
+ "features.soft-timeout",
+ op_errstr);
+ if (ret)
+ goto out;
+ goto create_vol;
+ }
+
+ if (type == GF_QUOTA_OPTION_TYPE_HARD_TIMEOUT) {
+ ret = glusterd_set_quota_option (volinfo, dict,
+ "features.hard-timeout",
+ op_errstr);
+ if (ret)
+ goto out;
+ goto create_vol;
+ }
+
+ if (type == GF_QUOTA_OPTION_TYPE_ALERT_TIME) {
+ ret = glusterd_set_quota_option (volinfo, dict,
+ "features.alert-time",
+ op_errstr);
+ if (ret)
+ goto out;
+ goto create_vol;
+ }
+ if (type == GF_QUOTA_OPTION_TYPE_DEFAULT_SOFT_LIMIT) {
+ ret = glusterd_set_quota_option (volinfo, dict,
+ "features.default-soft-limit",
+ op_errstr);
+ if (ret)
+ goto out;
+ goto create_vol;
+ }
+
create_vol:
ret = glusterd_create_volfiles_and_notify_services (volinfo);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to re-create volfile for"
- " 'quota'");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to re-create "
+ "volfiles");
ret = -1;
goto out;
}
@@ -759,20 +1086,31 @@ create_vol:
if (ret)
goto out;
- if (GLUSTERD_STATUS_STARTED == volinfo->status)
- ret = glusterd_check_generate_start_nfs ();
-
+ if (GLUSTERD_STATUS_STARTED == volinfo->status) {
+ if (priv->op_version == GD_OP_VERSION_MIN)
+ ret = glusterd_check_generate_start_nfs ();
+ }
ret = 0;
out:
if (rsp_dict && start_crawl == _gf_true)
glusterd_quota_initiate_fs_crawl (priv, volname);
+ if (priv->op_version > GD_OP_VERSION_MIN &&
+ is_origin_glusterd ()) {
+ if (type != GF_QUOTA_OPTION_TYPE_LIST) {
+ if (glusterd_all_volumes_with_quota_stopped ())
+ ret = glusterd_quotad_stop ();
+ else
+ ret = glusterd_check_generate_start_quotad ();
+ }
+ }
+
if (rsp_dict && *op_errstr) {
ret = dict_set_dynstr (rsp_dict, "errstr", *op_errstr);
if (ret) {
GF_FREE (*op_errstr);
- gf_log ("", GF_LOG_DEBUG,
+ gf_log (this->name, GF_LOG_DEBUG,
"failed to set error message in ctx");
}
*op_errstr = NULL;
@@ -789,51 +1127,63 @@ glusterd_op_stage_quota (dict_t *dict, char **op_errstr)
gf_boolean_t exists = _gf_false;
int type = 0;
dict_t *ctx = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
GF_ASSERT (dict);
GF_ASSERT (op_errstr);
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get volume name");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name");
goto out;
}
exists = glusterd_check_volume_exists (volname);
if (!exists) {
- gf_log ("", GF_LOG_ERROR, "Volume with name: %s "
- "does not exist",
- volname);
- *op_errstr = gf_strdup ("Invalid volume name");
+ gf_asprintf (op_errstr, FMTSTR_CHECK_VOL_EXISTS, volname);
ret = -1;
goto out;
}
ret = dict_get_int32 (dict, "type", &type);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get 'type' for quota op");
- *op_errstr = gf_strdup ("Volume quota failed, internal error "
- ", unable to get type of operation");
+ *op_errstr = gf_strdup ("Volume quota failed, internal error, "
+ "unable to get type of operation");
goto out;
}
-
- ctx = glusterd_op_get_ctx();
- if (ctx && (type == GF_QUOTA_OPTION_TYPE_ENABLE
- || type == GF_QUOTA_OPTION_TYPE_LIST)) {
- /* Fuse mount req. only for enable & list-usage options*/
- if (!glusterd_is_fuse_available ()) {
- gf_log ("glusterd", GF_LOG_ERROR, "Unable to open /dev/"
- "fuse (%s), quota command failed",
- strerror (errno));
- *op_errstr = gf_strdup ("Fuse unavailable");
- ret = -1;
- goto out;
- }
+ if ((priv->op_version == GD_OP_VERSION_MIN) &&
+ (type > GF_QUOTA_OPTION_TYPE_VERSION)) {
+ gf_asprintf (op_errstr, "Volume quota failed. The cluster is "
+ "operating at version %d. Option %s "
+ "is disallowed in this state.",
+ priv->op_version,
+ gd_quota_op_list[type]);
+ ret = -1;
+ goto out;
}
-out:
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
-
- return ret;
+ ctx = glusterd_op_get_ctx();
+ if (ctx && (type == GF_QUOTA_OPTION_TYPE_ENABLE
+ || type == GF_QUOTA_OPTION_TYPE_LIST)) {
+ /* Fuse mount req. only for enable & list-usage options*/
+ if (!glusterd_is_fuse_available ()) {
+ *op_errstr = gf_strdup ("Fuse unavailable");
+ ret = -1;
+ goto out;
+ }
+ }
+
+ out:
+ if (ret && op_errstr && *op_errstr)
+ gf_log (this->name, GF_LOG_ERROR, "%s", *op_errstr);
+ gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret);
+
+ return ret;
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index bde5b9b5..4a2b9454 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -3037,6 +3037,7 @@ glusterd_compare_friend_data (dict_t *vols, int32_t *status, char *hostname)
gf_boolean_t update = _gf_false;
gf_boolean_t stale_nfs = _gf_false;
gf_boolean_t stale_shd = _gf_false;
+ gf_boolean_t stale_qd = _gf_false;
GF_ASSERT (vols);
GF_ASSERT (status);
@@ -3066,6 +3067,8 @@ glusterd_compare_friend_data (dict_t *vols, int32_t *status, char *hostname)
stale_nfs = _gf_true;
if (glusterd_is_nodesvc_running ("glustershd"))
stale_shd = _gf_true;
+ if (glusterd_is_nodesvc_running ("quotad"))
+ stale_qd = _gf_true;
ret = glusterd_import_global_opts (vols);
if (ret)
goto out;
@@ -3079,6 +3082,8 @@ glusterd_compare_friend_data (dict_t *vols, int32_t *status, char *hostname)
glusterd_nfs_server_stop ();
if (stale_shd)
glusterd_shd_stop ();
+ if (stale_qd)
+ glusterd_quotad_stop ();
}
}
@@ -3161,7 +3166,10 @@ glusterd_get_nodesvc_volfile (char *server, char *workdir,
GF_ASSERT (len == PATH_MAX);
glusterd_get_nodesvc_dir (server, workdir, dir, sizeof (dir));
- snprintf (volfile, len, "%s/%s-server.vol", dir, server);
+ if (strcmp ("quotad", server) != 0)
+ snprintf (volfile, len, "%s/%s-server.vol", dir, server);
+ else
+ snprintf (volfile, len, "%s/%s.vol", dir, server);
}
void
@@ -3174,11 +3182,14 @@ glusterd_nodesvc_set_online_status (char *server, gf_boolean_t status)
GF_ASSERT (priv);
GF_ASSERT (priv->shd);
GF_ASSERT (priv->nfs);
+ GF_ASSERT (priv->quotad);
if (!strcmp("glustershd", server))
priv->shd->online = status;
else if (!strcmp ("nfs", server))
priv->nfs->online = status;
+ else if (!strcmp ("quotad", server))
+ priv->quotad->online = status;
}
gf_boolean_t
@@ -3192,11 +3203,14 @@ glusterd_is_nodesvc_online (char *server)
GF_ASSERT (conf);
GF_ASSERT (conf->shd);
GF_ASSERT (conf->nfs);
+ GF_ASSERT (conf->quotad);
if (!strcmp (server, "glustershd"))
online = conf->shd->online;
else if (!strcmp (server, "nfs"))
online = conf->nfs->online;
+ else if (!strcmp (server, "quotad"))
+ online = conf->quotad->online;
return online;
}
@@ -3262,11 +3276,14 @@ glusterd_nodesvc_get_rpc (char *server)
GF_ASSERT (priv);
GF_ASSERT (priv->shd);
GF_ASSERT (priv->nfs);
+ GF_ASSERT (priv->quotad);
if (!strcmp (server, "glustershd"))
rpc = priv->shd->rpc;
else if (!strcmp (server, "nfs"))
rpc = priv->nfs->rpc;
+ else if (!strcmp (server, "quotad"))
+ rpc = priv->quotad->rpc;
return rpc;
}
@@ -3284,11 +3301,14 @@ glusterd_nodesvc_set_rpc (char *server, struct rpc_clnt *rpc)
GF_ASSERT (priv);
GF_ASSERT (priv->shd);
GF_ASSERT (priv->nfs);
+ GF_ASSERT (priv->quotad);
if (!strcmp ("glustershd", server))
priv->shd->rpc = rpc;
else if (!strcmp ("nfs", server))
priv->nfs->rpc = rpc;
+ else if (!strcmp ("quotad", server))
+ priv->quotad->rpc = rpc;
return ret;
}
@@ -3415,6 +3435,14 @@ glusterd_nodesvc_start (char *server)
runner_add_args (&runner, "--xlator-option",
glusterd_uuid_option, NULL);
}
+ if (!strcmp (server, "quotad")) {
+ runner_add_args (&runner, "--xlator-option",
+ "*replicate*.data-self-heal=off",
+ "--xlator-option",
+ "*replicate*.metadata-self-heal=off",
+ "--xlator-option",
+ "*replicate*.entry-self-heal=off", NULL);
+ }
runner_log (&runner, "", GF_LOG_DEBUG,
"Starting the nfs/glustershd services");
@@ -3438,6 +3466,12 @@ glusterd_shd_start ()
return glusterd_nodesvc_start ("glustershd");
}
+int
+glusterd_quotad_start ()
+{
+ return glusterd_nodesvc_start ("quotad");
+}
+
gf_boolean_t
glusterd_is_nodesvc_running (char *server)
{
@@ -3556,6 +3590,12 @@ glusterd_shd_stop ()
}
int
+glusterd_quotad_stop ()
+{
+ return glusterd_nodesvc_stop ("quotad", SIGTERM);
+}
+
+int
glusterd_add_node_to_dict (char *server, dict_t *dict, int count,
dict_t *vol_opts)
{
@@ -3705,6 +3745,12 @@ glusterd_reconfigure_shd ()
}
int
+glusterd_reconfigure_quotad ()
+{
+ return glusterd_reconfigure_nodesvc (glusterd_create_quotad_volfile);
+}
+
+int
glusterd_reconfigure_nfs ()
{
int ret = -1;
@@ -3751,21 +3797,54 @@ glusterd_check_generate_start_shd ()
}
int
-glusterd_nodesvcs_batch_op (glusterd_volinfo_t *volinfo,
- int (*nfs_op) (), int (*shd_op) ())
+glusterd_check_generate_start_quotad ()
{
+ int ret = 0;
+
+ ret = glusterd_check_generate_start_service (glusterd_create_quotad_volfile,
+ glusterd_quotad_stop,
+ glusterd_quotad_start);
+ if (ret == -EINVAL)
+ ret = 0;
+ return ret;
+}
+
+int
+glusterd_nodesvcs_batch_op (glusterd_volinfo_t *volinfo, int (*nfs_op) (),
+ int (*shd_op) (), int (*qd_op) ())
+ {
int ret = 0;
+ xlator_t *this = THIS;
+ glusterd_conf_t *conf = NULL;
+
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
ret = nfs_op ();
if (ret)
goto out;
if (volinfo && !glusterd_is_volume_replicate (volinfo))
- goto out;
+ goto quotad_op;
ret = shd_op ();
if (ret)
goto out;
+
+quotad_op:
+
+ if (conf->op_version == GD_OP_VERSION_MIN)
+ goto out;
+
+ if (is_origin_glusterd ()) {
+ if (volinfo && !glusterd_is_volume_quota_enabled (volinfo))
+ goto out;
+ ret = qd_op ();
+ if (ret)
+ goto out;
+ }
+
out:
return ret;
}
@@ -3775,7 +3854,8 @@ glusterd_nodesvcs_start (glusterd_volinfo_t *volinfo)
{
return glusterd_nodesvcs_batch_op (volinfo,
glusterd_nfs_server_start,
- glusterd_shd_start);
+ glusterd_shd_start,
+ glusterd_quotad_start);
}
int
@@ -3783,7 +3863,8 @@ glusterd_nodesvcs_stop (glusterd_volinfo_t *volinfo)
{
return glusterd_nodesvcs_batch_op (volinfo,
glusterd_nfs_server_stop,
- glusterd_shd_stop);
+ glusterd_shd_stop,
+ glusterd_quotad_stop);
}
gf_boolean_t
@@ -3829,21 +3910,53 @@ glusterd_all_replicate_volumes_stopped ()
return _gf_true;
}
+gf_boolean_t
+glusterd_all_volumes_with_quota_stopped ()
+{
+ glusterd_conf_t *priv = NULL;
+ xlator_t *this = NULL;
+ glusterd_volinfo_t *voliter = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ list_for_each_entry (voliter, &priv->volumes, vol_list) {
+ if (!glusterd_is_volume_quota_enabled (voliter))
+ continue;
+ if (voliter->status == GLUSTERD_STATUS_STARTED)
+ return _gf_false;
+ }
+
+ return _gf_true;
+}
+
+
int
glusterd_nodesvcs_handle_graph_change (glusterd_volinfo_t *volinfo)
{
int (*shd_op) () = NULL;
int (*nfs_op) () = NULL;
+ int (*qd_op) () = NULL;
shd_op = glusterd_check_generate_start_shd;
nfs_op = glusterd_check_generate_start_nfs;
+ qd_op = glusterd_check_generate_start_quotad;
if (glusterd_are_all_volumes_stopped ()) {
shd_op = glusterd_shd_stop;
nfs_op = glusterd_nfs_server_stop;
- } else if (glusterd_all_replicate_volumes_stopped()) {
- shd_op = glusterd_shd_stop;
+ qd_op = glusterd_quotad_stop;
+ } else {
+ if (glusterd_all_replicate_volumes_stopped()) {
+ shd_op = glusterd_shd_stop;
+ }
+ if (glusterd_all_volumes_with_quota_stopped ()) {
+ qd_op = glusterd_quotad_stop;
+ }
}
- return glusterd_nodesvcs_batch_op (volinfo, nfs_op, shd_op);
+
+ return glusterd_nodesvcs_batch_op (volinfo, nfs_op, shd_op, qd_op);
}
int
@@ -3851,7 +3964,8 @@ glusterd_nodesvcs_handle_reconfigure (glusterd_volinfo_t *volinfo)
{
return glusterd_nodesvcs_batch_op (volinfo,
glusterd_reconfigure_nfs,
- glusterd_reconfigure_shd);
+ glusterd_reconfigure_shd,
+ glusterd_reconfigure_quotad);
}
int
@@ -5878,6 +5992,82 @@ out:
return ret;
}
+int
+glusterd_quotad_statedump (char *options, int option_cnt, char **op_errstr)
+{
+ int ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ char pidfile_path[PATH_MAX] = {0,};
+ char path[PATH_MAX] = {0,};
+ FILE *pidfile = NULL;
+ pid_t pid = -1;
+ char dumpoptions_path[PATH_MAX] = {0,};
+ char *option = NULL;
+ char *tmpptr = NULL;
+ char *dup_options = NULL;
+ char msg[256] = {0,};
+
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
+
+ dup_options = gf_strdup (options);
+ option = strtok_r (dup_options, " ", &tmpptr);
+ if (strcmp (option, "quotad")) {
+ snprintf (msg, sizeof (msg), "for quotad statedump, options "
+ "should be after the key 'quotad'");
+ *op_errstr = gf_strdup (msg);
+ ret = -1;
+ goto out;
+ }
+
+ GLUSTERD_GET_QUOTAD_DIR (path, conf);
+ GLUSTERD_GET_QUOTAD_PIDFILE (pidfile_path, path);
+
+ pidfile = fopen (pidfile_path, "r");
+ if (!pidfile) {
+ gf_log (this->name, GF_LOG_ERROR, "Unable to open pidfile: %s",
+ pidfile_path);
+ ret = -1;
+ goto out;
+ }
+
+ ret = fscanf (pidfile, "%d", &pid);
+ if (ret <= 0) {
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get pid of quotad "
+ "process");
+ ret = -1;
+ goto out;
+ }
+
+ snprintf (dumpoptions_path, sizeof (dumpoptions_path),
+ DEFAULT_VAR_RUN_DIRECTORY"/glusterdump.%d.options", pid);
+ ret = glusterd_set_dump_options (dumpoptions_path, options, option_cnt);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR, "error while parsing "
+ "statedump options");
+ ret = -1;
+ goto out;
+ }
+
+ gf_log (this->name, GF_LOG_INFO, "Performing statedump on quotad with "
+ "pid %d", pid);
+
+ kill (pid, SIGUSR1);
+
+ sleep (1);
+
+ ret = 0;
+out:
+ if (pidfile)
+ fclose (pidfile);
+ unlink (dumpoptions_path);
+ GF_FREE (dup_options);
+ return ret;
+}
+
/* Checks if the given peer contains all the bricks belonging to the
* given volume. Returns true if it does else returns false
*/
@@ -7619,3 +7809,9 @@ out:
gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
+
+int
+glusterd_is_volume_quota_enabled (glusterd_volinfo_t *volinfo)
+{
+ return (glusterd_volinfo_get_boolean (volinfo, VKEY_FEATURES_QUOTA));
+}
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
index 4d1dde7c..a5590db0 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
@@ -188,6 +188,12 @@ glusterd_shd_start ();
int32_t
glusterd_shd_stop ();
+int32_t
+glusterd_quotad_start ();
+
+int32_t
+glusterd_quotad_stop ();
+
void
glusterd_set_socket_filepath (char *sock_filepath, char *sockpath, size_t len);
@@ -228,6 +234,9 @@ int
glusterd_check_generate_start_shd (void);
int
+glusterd_check_generate_start_quotad (void);
+
+int
glusterd_nodesvcs_handle_graph_change (glusterd_volinfo_t *volinfo);
int
@@ -401,8 +410,13 @@ glusterd_brick_statedump (glusterd_volinfo_t *volinfo,
char *options, int option_cnt, char **op_errstr);
int
glusterd_nfs_statedump (char *options, int option_cnt, char **op_errstr);
+
+int
+glusterd_quotad_statedump (char *options, int option_cnt, char **op_errstr);
+
gf_boolean_t
glusterd_is_volume_replicate (glusterd_volinfo_t *volinfo);
+
gf_boolean_t
glusterd_is_brick_decommissioned (glusterd_volinfo_t *volinfo, char *hostname,
char *path);
@@ -565,4 +579,12 @@ glusterd_check_gsync_running_local (char *master, char *slave,
char *conf_path,
gf_boolean_t *is_run);
+int
+glusterd_is_volume_quota_enabled (glusterd_volinfo_t *volinfo);
+
+gf_boolean_t
+glusterd_all_volumes_with_quota_stopped ();
+
+int
+glusterd_reconfigure_quotad ();
#endif
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
index 06a2d37d..d0f3d5fa 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c
@@ -1423,6 +1423,7 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
char *vg = NULL;
glusterd_brickinfo_t *brickinfo = NULL;
char changelog_basepath[PATH_MAX] = {0,};
+ char *value = NULL;
brickinfo = param;
path = brickinfo->path;
@@ -1607,7 +1608,18 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
if (ret)
return -1;
- if (dict_get_str_boolean (set_dict, "features.read-only", 0) &&
+ xl = volgen_graph_add (graph, "features/quota", volname);
+ if (!xl)
+ return -1;
+
+ ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_QUOTA, &value);
+ if (value) {
+ ret = xlator_set_option (xl, "server-quota", value);
+ if (ret)
+ return -1;
+ }
+
+ if (dict_get_str_boolean (set_dict, "features.read-only", 0) &&
dict_get_str_boolean (set_dict, "features.worm",0)) {
gf_log (THIS->name, GF_LOG_ERROR,
"read-only and worm cannot be set together");
@@ -2310,13 +2322,15 @@ out:
static int
volgen_graph_build_dht_cluster (volgen_graph_t *graph,
- glusterd_volinfo_t *volinfo, size_t child_count)
+ glusterd_volinfo_t *volinfo, size_t child_count,
+ gf_boolean_t is_quotad)
{
int32_t clusters = 0;
int ret = -1;
char *decommissioned_children = NULL;
xlator_t *dht = NULL;
char *voltype = "cluster/distribute";
+ char *name_fmt = NULL;
/* NUFA and Switch section */
if (dict_get_str_boolean (volinfo->dict, "cluster.nufa", 0) &&
@@ -2335,9 +2349,14 @@ volgen_graph_build_dht_cluster (volgen_graph_t *graph,
if (dict_get_str_boolean (volinfo->dict, "cluster.switch", 0))
voltype = "cluster/switch";
+ if (is_quotad)
+ name_fmt = "%s";
+ else
+ name_fmt = "%s-dht";
+
clusters = volgen_graph_build_clusters (graph, volinfo,
voltype,
- "%s-dht",
+ name_fmt,
child_count,
child_count);
if (clusters < 0)
@@ -2362,7 +2381,8 @@ out:
static int
volume_volgen_graph_build_clusters (volgen_graph_t *graph,
- glusterd_volinfo_t *volinfo)
+ glusterd_volinfo_t *volinfo,
+ gf_boolean_t is_quotad)
{
char *replicate_args[] = {"cluster/replicate",
"%s-replicate-%d"};
@@ -2435,8 +2455,8 @@ build_distribute:
}
ret = volgen_graph_build_dht_cluster (graph, volinfo,
- dist_count);
- if (ret == -1)
+ dist_count, is_quotad);
+ if (ret)
goto out;
ret = 0;
@@ -2452,25 +2472,30 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
xlator_t *xl = NULL;
char *volname = NULL;
data_t *tmp_data = NULL;
+ glusterd_conf_t *conf = THIS->private;
+ GF_ASSERT (conf);
volname = volinfo->volname;
ret = volgen_graph_build_clients (graph, volinfo, set_dict, param);
if (ret)
goto out;
- ret = volume_volgen_graph_build_clusters (graph, volinfo);
- if (ret == -1)
- goto out;
-
- ret = glusterd_volinfo_get_boolean (volinfo, VKEY_FEATURES_QUOTA);
- if (ret == -1)
+ ret = volume_volgen_graph_build_clusters (graph, volinfo, _gf_false);
+ if (ret)
goto out;
- if (ret) {
- xl = volgen_graph_add (graph, "features/quota", volname);
- if (!xl) {
- ret = -1;
+ if (conf->op_version == GD_OP_VERSION_MIN) {
+ ret = glusterd_volinfo_get_boolean (volinfo,
+ VKEY_FEATURES_QUOTA);
+ if (ret == -1)
goto out;
+ if (ret) {
+ xl = volgen_graph_add (graph, "features/quota",
+ volname);
+ if (!xl) {
+ ret = -1;
+ goto out;
+ }
}
}
@@ -2740,6 +2765,60 @@ nfs_option_handler (volgen_graph_t *graph,
}
static int
+set_quotad_xlator_option (char *fmt_str, char *opt_name, char *volname,
+ xlator_t *xl, char *value)
+{
+ int ret = -1;
+ char *opt_str = NULL;
+
+ ret = gf_asprintf (&opt_str, fmt_str, volname, opt_name);
+ if (opt_str == NULL) {
+ ret = -1;
+ goto out;
+ }
+ ret = xlator_set_option (xl, opt_str, value);
+
+out:
+ GF_FREE (opt_str);
+ return ret;
+}
+
+int
+quotad_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme,
+ void *param)
+{
+ xlator_t *xl = NULL;
+ char *opt_str = NULL;
+ int ret = 0;
+ glusterd_volinfo_t *volinfo = NULL;
+ int i = 0;
+ char *ptr = NULL;
+ char *options[] = {"!*.soft-timeout", "!*.hard-timeout",
+ "limit-set", "!*.alert-time",
+ "default-soft-limit", NULL};
+
+ volinfo = param;
+ xl = first_of (graph);
+
+ for (i = 0; options[i]; i++) {
+ if (!strcmp (vme->option, options[i])) {
+ ptr = strchr (options[i], '.');
+ if (!ptr)
+ opt_str = options[i];
+ else
+ opt_str = ptr + 1;
+ ret = set_quotad_xlator_option ("%s.%s", opt_str,
+ volinfo->volname, xl,
+ vme->value);
+ if (ret)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
volgen_graph_set_iam_shd (volgen_graph_t *graph)
{
xlator_t *trav;
@@ -3024,9 +3103,6 @@ build_nfs_graph (volgen_graph_t *graph, dict_t *mod_dict)
return ret;
}
-
-
-
/****************************
*
* Volume generation interface
@@ -3113,7 +3189,109 @@ glusterd_generate_brick_volfile (glusterd_volinfo_t *volinfo,
return ret;
}
+static int
+build_quotad_graph (volgen_graph_t *graph, dict_t *mod_dict)
+{
+ volgen_graph_t cgraph = {0};
+ glusterd_volinfo_t *voliter = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ dict_t *set_dict = NULL;
+ int ret = 0;
+ xlator_t *quotad_xl = NULL;
+
+ this = THIS;
+ priv = this->private;
+
+ set_dict = dict_new ();
+ if (!set_dict) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ quotad_xl = volgen_graph_add_as (graph, "features/quotad", "quotad");
+ if (!quotad_xl) {
+ ret = -1;
+ goto out;
+ }
+
+ list_for_each_entry (voliter, &priv->volumes, vol_list) {
+ if (voliter->status != GLUSTERD_STATUS_STARTED)
+ continue;
+
+ if (1 != glusterd_is_volume_quota_enabled (voliter))
+ continue;
+
+ ret = dict_set_uint32 (set_dict, "trusted-client",
+ GF_CLIENT_TRUSTED);
+ if (ret)
+ goto out;
+
+ dict_copy (voliter->dict, set_dict);
+ if (mod_dict)
+ dict_copy (mod_dict, set_dict);
+
+ memset (&cgraph, 0, sizeof (cgraph));
+ ret = volgen_graph_build_clients (&cgraph, voliter, set_dict,
+ NULL);
+ if (ret)
+ goto out;
+
+ ret = volume_volgen_graph_build_clusters (&cgraph, voliter,
+ _gf_true);
+ if (ret) {
+ ret = -1;
+ goto out;
+ }
+
+ if (mod_dict) {
+ dict_copy (mod_dict, set_dict);
+ ret = volgen_graph_set_options_generic (&cgraph, set_dict,
+ voliter,
+ basic_option_handler);
+ } else {
+ ret = volgen_graph_set_options_generic (&cgraph,
+ voliter->dict,
+ voliter,
+ basic_option_handler);
+ }
+ if (ret)
+ goto out;
+
+ ret = volgen_graph_merge_sub (graph, &cgraph, 1);
+ if (ret)
+ goto out;
+
+ ret = dict_reset (set_dict);
+ if (ret)
+ goto out;
+ }
+
+ list_for_each_entry (voliter, &priv->volumes, vol_list) {
+ if (voliter->status != GLUSTERD_STATUS_STARTED)
+ continue;
+
+ if (1 != glusterd_is_volume_quota_enabled (voliter))
+ continue;
+ if (mod_dict) {
+ ret = volgen_graph_set_options_generic (graph, mod_dict,
+ voliter,
+ quotad_option_handler);
+ } else {
+ ret = volgen_graph_set_options_generic (graph,
+ voliter->dict, voliter,
+ quotad_option_handler);
+ }
+ if (ret)
+ gf_log (THIS->name, GF_LOG_ERROR, "Failed to set "
+ "options for the volume %s", voliter->volname);
+ }
+out:
+ if (set_dict)
+ dict_unref (set_dict);
+ return ret;
+}
static void
get_vol_tstamp_file (char *filename, glusterd_volinfo_t *volinfo)
@@ -3381,6 +3559,18 @@ out:
}
int
+glusterd_create_quotad_volfile ()
+{
+ char filepath[PATH_MAX] = {0,};
+ glusterd_conf_t *conf = THIS->private;
+
+ glusterd_get_nodesvc_volfile ("quotad", conf->workdir,
+ filepath, sizeof (filepath));
+ return glusterd_create_global_volfile (build_quotad_graph,
+ filepath, NULL);
+}
+
+int
glusterd_check_nfs_volfile_identical (gf_boolean_t *identical)
{
char nfsvol[PATH_MAX] = {0,};
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.h b/xlators/mgmt/glusterd/src/glusterd-volgen.h
index 4ff899f4..303acd90 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.h
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.h
@@ -22,6 +22,7 @@
#define VKEY_DIAG_CNT_FOP_HITS "diagnostics.count-fop-hits"
#define VKEY_DIAG_LAT_MEASUREMENT "diagnostics.latency-measurement"
#define VKEY_FEATURES_LIMIT_USAGE "features.limit-usage"
+#define VKEY_FEATURES_SOFT_LIMIT "features.soft-limit"
#define VKEY_MARKER_XTIME GEOREP".indexing"
#define VKEY_CHANGELOG "changelog.changelog"
#define VKEY_FEATURES_QUOTA "features.quota"
@@ -119,6 +120,7 @@ void glusterd_get_shd_filepath (char *filename);
int glusterd_create_nfs_volfile ();
int glusterd_create_shd_volfile ();
+int glusterd_create_quotad_volfile ();
int glusterd_delete_volfile (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo);
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
index 7cac938c..1b860df2 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
@@ -526,9 +526,12 @@ __glusterd_handle_cli_statedump_volume (rpcsvc_request_t *req)
glusterd_op_t cli_op = GD_OP_STATEDUMP_VOLUME;
char err_str[2048] = {0,};
xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
this = THIS;
GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
GF_ASSERT (req);
@@ -577,6 +580,14 @@ __glusterd_handle_cli_statedump_volume (rpcsvc_request_t *req)
goto out;
}
+ if (priv->op_version == GD_OP_VERSION_MIN &&
+ strstr (options, "quotad")) {
+ snprintf (err_str, sizeof (err_str), "The cluster is operating "
+ "at op-version 1. Taking quotad's statedump is "
+ "disallowed in this state");
+ ret = -1;
+ goto out;
+ }
gf_log (this->name, GF_LOG_INFO, "Received statedump request for "
"volume %s with options %s", volname, options);
@@ -1236,6 +1247,13 @@ glusterd_op_stage_statedump_volume (dict_t *dict, char **op_errstr)
gf_boolean_t is_running = _gf_false;
glusterd_volinfo_t *volinfo = NULL;
char msg[2408] = {0,};
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
ret = glusterd_op_statedump_volume_args_get (dict, &volname, &options,
&option_cnt);
@@ -1244,10 +1262,7 @@ glusterd_op_stage_statedump_volume (dict_t *dict, char **op_errstr)
ret = glusterd_volinfo_find (volname, &volinfo);
if (ret) {
- snprintf (msg, sizeof(msg), "Volume %s does not exist",
- volname);
- gf_log ("", GF_LOG_ERROR, "%s", msg);
- *op_errstr = gf_strdup (msg);
+ snprintf (msg, sizeof(msg), FMTSTR_CHECK_VOL_EXISTS, volname);
goto out;
}
@@ -1257,16 +1272,31 @@ glusterd_op_stage_statedump_volume (dict_t *dict, char **op_errstr)
is_running = glusterd_is_volume_started (volinfo);
if (!is_running) {
- snprintf (msg, sizeof(msg), "Volume %s is not in a started"
+ snprintf (msg, sizeof(msg), "Volume %s is not in the started"
" state", volname);
- gf_log ("", GF_LOG_ERROR, "%s", msg);
- *op_errstr = gf_strdup (msg);
ret = -1;
goto out;
}
+ if (priv->op_version == GD_OP_VERSION_MIN &&
+ strstr (options, "quotad")) {
+ snprintf (msg, sizeof (msg), "The cluster is operating "
+ "at op-version 1. Taking quotad's statedump is "
+ "disallowed in this state");
+ ret = -1;
+ goto out;
+ }
+ if ((strstr (options, "quotad")) &&
+ (!glusterd_is_volume_quota_enabled (volinfo))) {
+ snprintf (msg, sizeof (msg), "Quota is not enabled on "
+ "volume %s", volname);
+ ret = -1;
+ goto out;
+ }
out:
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
+ if (ret && msg[0] != '\0')
+ *op_errstr = gf_strdup (msg);
+ gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
@@ -1828,6 +1858,18 @@ glusterd_op_statedump_volume (dict_t *dict, char **op_errstr)
ret = glusterd_nfs_statedump (options, option_cnt, op_errstr);
if (ret)
goto out;
+
+ } else if (strstr (options, "quotad")) {
+ if (is_origin_glusterd()) {
+ ret = glusterd_quotad_statedump (options, option_cnt,
+ op_errstr);
+ if (ret)
+ goto out;
+ } else {
+ ret = 0;
+ goto out;
+ }
+
} else {
list_for_each_entry (brickinfo, &volinfo->bricks,
brick_list) {
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
index b6dd09a6..d59b81d3 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
@@ -945,29 +945,51 @@ struct volopt_map_entry glusterd_volopt_map[] = {
},
/* Quota xlator options */
- { .key = VKEY_FEATURES_LIMIT_USAGE,
- .voltype = "features/quota",
- .option = "limit-set",
- .type = NO_DOC,
- .op_version = 1,
- .flags = OPT_FLAG_CLIENT_OPT
- },
- { .key = "features.quota-timeout",
- .voltype = "features/quota",
- .option = "timeout",
- .value = "0",
- .op_version = 1,
- .validate_fn = validate_quota,
- .flags = OPT_FLAG_CLIENT_OPT
- },
- { .key = "features.quota-deem-statfs",
- .voltype = "features/quota",
- .option = "deem-statfs",
- .value = "off",
- .type = DOC,
- .op_version = 3,
- .validate_fn = validate_quota,
- .flags = OPT_FLAG_CLIENT_OPT
+ { .key = VKEY_FEATURES_LIMIT_USAGE,
+ .voltype = "features/quota",
+ .option = "limit-set",
+ .type = NO_DOC,
+ .op_version = 1,
+ },
+ {
+ .key = "features.quota-timeout",
+ .voltype = "features/quota",
+ .option = "timeout",
+ .value = "0",
+ .op_version = 1,
+ .validate_fn = validate_quota,
+ },
+ { .key = "features.default-soft-limit",
+ .voltype = "features/quota",
+ .option = "default-soft-limit",
+ .type = NO_DOC,
+ .op_version = 3,
+ },
+ { .key = "features.soft-timeout",
+ .voltype = "features/quotad",
+ .option = "!*.soft-timeout",
+ .type = NO_DOC,
+ .op_version = 3,
+ },
+ { .key = "features.hard-timeout",
+ .voltype = "features/quotad",
+ .option = "!*.hard-timeout",
+ .type = NO_DOC,
+ .op_version = 3,
+ },
+ { .key = "features.alert-time",
+ .voltype = "features/quotad",
+ .option = "!*.alert-time",
+ .type = NO_DOC,
+ .op_version = 3,
+ },
+ { .key = "features.quota-deem-statfs",
+ .voltype = "features/quota",
+ .option = "deem-statfs",
+ .value = "off",
+ .type = DOC,
+ .op_version = 2,
+ .validate_fn = validate_quota,
},
/* Marker xlator options */
diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c
index a43c8d54..291b6d0a 100644
--- a/xlators/mgmt/glusterd/src/glusterd.c
+++ b/xlators/mgmt/glusterd/src/glusterd.c
@@ -1061,6 +1061,15 @@ init (xlator_t *this)
exit (1);
}
+ snprintf (storedir, PATH_MAX, "%s/quotad", workdir);
+ ret = mkdir (storedir, 0777);
+ if ((-1 == ret) && (errno != EEXIST)) {
+ gf_log (this->name, GF_LOG_CRITICAL,
+ "Unable to create quotad directory %s"
+ " ,errno = %d", storedir, errno);
+ exit (1);
+ }
+
snprintf (storedir, PATH_MAX, "%s/groups", workdir);
ret = mkdir (storedir, 0777);
if ((-1 == ret) && (errno != EEXIST)) {
@@ -1114,12 +1123,14 @@ init (xlator_t *this)
conf = GF_CALLOC (1, sizeof (glusterd_conf_t),
gf_gld_mt_glusterd_conf_t);
GF_VALIDATE_OR_GOTO(this->name, conf, out);
- conf->shd = GF_CALLOC (1, sizeof (nodesrv_t),
- gf_gld_mt_nodesrv_t);
+
+ conf->shd = GF_CALLOC (1, sizeof (nodesrv_t), gf_gld_mt_nodesrv_t);
GF_VALIDATE_OR_GOTO(this->name, conf->shd, out);
- conf->nfs = GF_CALLOC (1, sizeof (nodesrv_t),
- gf_gld_mt_nodesrv_t);
+ conf->nfs = GF_CALLOC (1, sizeof (nodesrv_t), gf_gld_mt_nodesrv_t);
GF_VALIDATE_OR_GOTO(this->name, conf->nfs, out);
+ conf->quotad = GF_CALLOC (1, sizeof (nodesrv_t),
+ gf_gld_mt_nodesrv_t);
+ GF_VALIDATE_OR_GOTO(this->name, conf->quotad, out);
INIT_LIST_HEAD (&conf->peers);
INIT_LIST_HEAD (&conf->volumes);
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
index 8c043a9a..ac58e2a6 100644
--- a/xlators/mgmt/glusterd/src/glusterd.h
+++ b/xlators/mgmt/glusterd/src/glusterd.h
@@ -131,6 +131,7 @@ typedef struct {
rpcsvc_t *rpc;
nodesrv_t *shd;
nodesrv_t *nfs;
+ nodesrv_t *quotad;
struct pmap_registry *pmap;
struct list_head volumes;
pthread_mutex_t xprt_lock;
@@ -311,6 +312,7 @@ typedef enum gd_node_type_ {
GD_NODE_SHD,
GD_NODE_REBALANCE,
GD_NODE_NFS,
+ GD_NODE_QUOTAD,
} gd_node_type;
typedef struct glusterd_pending_node_ {
@@ -366,6 +368,9 @@ typedef ssize_t (*gd_serialize_t) (struct iovec outmsg, void *args);
#define GLUSTERD_GET_NFS_DIR(path, priv) \
snprintf (path, PATH_MAX, "%s/nfs", priv->workdir);
+#define GLUSTERD_GET_QUOTAD_DIR(path, priv) \
+ snprintf (path, PATH_MAX, "%s/quotad", priv->workdir);
+
#define GLUSTERD_REMOVE_SLASH_FROM_PATH(path,string) do { \
int i = 0; \
for (i = 1; i < strlen (path); i++) { \
@@ -389,6 +394,11 @@ typedef ssize_t (*gd_serialize_t) (struct iovec outmsg, void *args);
nfspath); \
}
+#define GLUSTERD_GET_QUOTAD_PIDFILE(pidfile,quotadpath) { \
+ snprintf (pidfile, PATH_MAX, "%s/run/quotad.pid", \
+ quotadpath); \
+ }
+
#define GLUSTERD_STACK_DESTROY(frame) do {\
frame->local = NULL; \
STACK_DESTROY (frame->root);\