diff options
-rw-r--r-- | cli/src/cli-cmd-parser.c | 54 | ||||
-rw-r--r-- | cli/src/cli-cmd-volume.c | 23 | ||||
-rw-r--r-- | cli/src/cli.h | 3 | ||||
-rw-r--r-- | rpc/xdr/src/cli1-xdr.x | 1 | ||||
-rw-r--r-- | xlators/features/marker/src/marker-quota.c | 55 | ||||
-rw-r--r-- | xlators/features/marker/src/marker.c | 15 | ||||
-rw-r--r-- | xlators/features/marker/src/marker.h | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 54 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-quota.c | 106 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 7 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 3 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.h | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-set.c | 8 |
13 files changed, 289 insertions, 42 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 5437b38d3a6..99ef7014d2d 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -926,6 +926,60 @@ out: } int32_t +cli_cmd_inode_quota_parse (const char **words, int wordcount, dict_t **options) +{ + dict_t *dict = NULL; + char *volname = NULL; + int ret = -1; + + GF_ASSERT (words); + GF_ASSERT (options); + + dict = dict_new (); + if (!dict) { + gf_log ("cli", GF_LOG_ERROR, "dict_new failed"); + goto out; + } + + if (wordcount != 4) + goto out; + + volname = (char *)words[2]; + if (!volname) { + ret = -1; + goto out; + } + + /* Validate the volume name here itself */ + if (cli_validate_volname (volname) < 0) + goto out; + + ret = dict_set_str (dict, "volname", volname); + if (ret < 0) + goto out; + + if (strcmp (words[3], "enable") != 0) { + cli_out ("Invalid quota option : %s", words[3]); + ret = -1; + goto out; + } + + ret = dict_set_int32 (dict, "type", + GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS); + if (ret < 0) + goto out; + + *options = dict; +out: + if (ret < 0) { + if (dict) + dict_destroy (dict); + } + + return ret; +} + +int32_t cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 9340067e256..0dfb647b92c 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1515,11 +1515,20 @@ cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word, "configuration. Do you want to continue?"; //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; + if (strcmp (words[1], "inode-quota") == 0) { + ret = cli_cmd_inode_quota_parse (words, wordcount, &options); + if (ret < 0) { + cli_usage_out (word->pattern); + parse_err = 1; + goto out; + } + } else { + ret = cli_cmd_quota_parse (words, wordcount, &options); + if (ret < 0) { + cli_usage_out (word->pattern); + parse_err = 1; + goto out; + } } ret = dict_get_int32 (options, "type", &type); @@ -2649,6 +2658,10 @@ struct cli_cmd volume_cmds[] = { cli_cmd_quota_cbk, "quota translator specific operations"}, + { "volume inode-quota <VOLNAME> enable", + cli_cmd_quota_cbk, + "quota translator specific operations"}, + { "volume top <VOLNAME> {open|read|write|opendir|readdir|clear} [nfs|brick <brick>] [list-cnt <value>] |\n" "volume top <VOLNAME> {read-perf|write-perf} [bs <size> count <count>] [brick <brick>] [list-cnt <value>]", cli_cmd_volume_top_cbk, diff --git a/cli/src/cli.h b/cli/src/cli.h index 243935230d1..27558a7830c 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -242,6 +242,9 @@ int32_t cli_cmd_quota_parse (const char **words, int wordcount, dict_t **opt); int32_t +cli_cmd_inode_quota_parse (const char **words, int wordcount, dict_t **opt); + +int32_t cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **opt); int32_t diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index dbc2fa52494..1a1dfcc9e87 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -81,6 +81,7 @@ enum gf_quota_type { GF_QUOTA_OPTION_TYPE_LIMIT_OBJECTS, GF_QUOTA_OPTION_TYPE_LIST_OBJECTS, GF_QUOTA_OPTION_TYPE_REMOVE_OBJECTS, + GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS, GF_QUOTA_OPTION_TYPE_MAX }; diff --git a/xlators/features/marker/src/marker-quota.c b/xlators/features/marker/src/marker-quota.c index e99dfe2331e..e9351ed4e88 100644 --- a/xlators/features/marker/src/marker-quota.c +++ b/xlators/features/marker/src/marker-quota.c @@ -2037,6 +2037,38 @@ err: return -1; } +int32_t +_quota_dict_get_meta (xlator_t *this, dict_t *dict, char *key, + quota_meta_t *meta, ia_type_t ia_type, + gf_boolean_t add_delta) +{ + int32_t ret = 0; + marker_conf_t *priv = NULL; + + priv = this->private; + + ret = quota_dict_get_meta (dict, key, meta); + if (ret == -2 && (priv->feature_enabled & GF_INODE_QUOTA) == 0) { + /* quota_dict_get_meta returns -2 if + * inode quota xattrs are not present. + * if inode quota self heal is turned off, + * then we should skip healing inode quotas + */ + + gf_log (this->name, GF_LOG_DEBUG, "inode quota disabled. " + "inode quota self heal will not be performed"); + ret = 0; + if (add_delta) { + if (ia_type == IA_IFDIR) + meta->dir_count = 1; + else + meta->file_count = 1; + } + } + + return ret; +} + void mq_compute_delta (quota_meta_t *delta, const quota_meta_t *op1, const quota_meta_t *op2) @@ -2116,7 +2148,8 @@ mq_are_xattrs_set (xlator_t *this, loc_t *loc, gf_boolean_t *result, *result = _gf_true; if (loc->inode->ia_type == IA_IFDIR) { - ret = quota_dict_get_meta (rsp_dict, QUOTA_SIZE_KEY, &meta); + ret = _quota_dict_get_meta (this, rsp_dict, QUOTA_SIZE_KEY, + &meta, IA_IFDIR, _gf_false); if (ret < 0 || meta.dir_count == 0) { ret = 0; *result = _gf_false; @@ -2126,7 +2159,8 @@ mq_are_xattrs_set (xlator_t *this, loc_t *loc, gf_boolean_t *result, } if (!loc_is_root(loc)) { - ret = quota_dict_get_meta (rsp_dict, contri_key, &meta); + ret = _quota_dict_get_meta (this, rsp_dict, contri_key, + &meta, IA_IFREG, _gf_false); if (ret < 0) { ret = 0; *result = _gf_false; @@ -2392,8 +2426,9 @@ _mq_get_metadata (xlator_t *this, loc_t *loc, quota_meta_t *contri, if (size) { if (loc->inode->ia_type == IA_IFDIR) { - ret = quota_dict_get_meta (rsp_dict, QUOTA_SIZE_KEY, - &meta); + ret = _quota_dict_get_meta (this, rsp_dict, + QUOTA_SIZE_KEY, &meta, + IA_IFDIR, _gf_true); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "dict_get failed."); @@ -2411,7 +2446,8 @@ _mq_get_metadata (xlator_t *this, loc_t *loc, quota_meta_t *contri, } if (contri && !loc_is_root(loc)) { - ret = quota_dict_get_meta (rsp_dict, contri_key, &meta); + ret = _quota_dict_get_meta (this, rsp_dict, contri_key, &meta, + loc->inode->ia_type, _gf_false); if (ret < 0) { contri->size = 0; contri->file_count = 0; @@ -3419,7 +3455,8 @@ mq_inspect_directory_xattr_task (void *opaque) if (ret < 0) goto out; - ret = quota_dict_get_meta (dict, QUOTA_SIZE_KEY, &size); + ret = _quota_dict_get_meta (this, dict, QUOTA_SIZE_KEY, &size, + IA_IFDIR, _gf_false); if (ret < 0) goto out; @@ -3428,7 +3465,8 @@ mq_inspect_directory_xattr_task (void *opaque) if (ret < 0) goto err; - ret = quota_dict_get_meta (dict, contri_key, &contri); + ret = _quota_dict_get_meta (this, dict, contri_key, &contri, + IA_IFDIR, _gf_false); if (ret < 0) goto out; @@ -3544,7 +3582,8 @@ mq_inspect_file_xattr_task (void *opaque) if (ret < 0) continue; - ret = quota_dict_get_meta (dict, contri_key, &contri); + ret = _quota_dict_get_meta (this, dict, contri_key, &contri, + IA_IFREG, _gf_true); if (ret < 0) { ret = mq_create_xattrs_blocking_txn (this, loc); } else { diff --git a/xlators/features/marker/src/marker.c b/xlators/features/marker/src/marker.c index 046df1fc44c..a465723c1bb 100644 --- a/xlators/features/marker/src/marker.c +++ b/xlators/features/marker/src/marker.c @@ -3043,6 +3043,13 @@ reconfigure (xlator_t *this, dict_t *options) } } + data = dict_get (options, "inode-quota"); + if (data) { + ret = gf_string2boolean (data->data, &flag); + if (ret == 0 && flag == _gf_true) + priv->feature_enabled |= GF_INODE_QUOTA; + } + data = dict_get (options, "xtime"); if (data) { ret = gf_string2boolean (data->data, &flag); @@ -3113,6 +3120,13 @@ init (xlator_t *this) } } + data = dict_get (options, "inode-quota"); + if (data) { + ret = gf_string2boolean (data->data, &flag); + if (ret == 0 && flag == _gf_true) + priv->feature_enabled |= GF_INODE_QUOTA; + } + data = dict_get (options, "xtime"); if (data) { ret = gf_string2boolean (data->data, &flag); @@ -3206,6 +3220,7 @@ struct volume_options options[] = { {.key = {"volume-uuid"}}, {.key = {"timestamp-file"}}, {.key = {"quota"}}, + {.key = {"inode-quota"} }, {.key = {"xtime"}}, {.key = {"gsync-force-xtime"}}, {.key = {NULL}} diff --git a/xlators/features/marker/src/marker.h b/xlators/features/marker/src/marker.h index b2d58d23f6c..aadd8776637 100644 --- a/xlators/features/marker/src/marker.h +++ b/xlators/features/marker/src/marker.h @@ -31,6 +31,7 @@ enum { GF_QUOTA = 1, GF_XTIME = 2, GF_XTIME_GSYNC_FORCE = 4, + GF_INODE_QUOTA = 8, }; /*initialize the local variable*/ diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index dfb3a2666d7..04cc75f545d 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -428,23 +428,49 @@ glusterd_check_quota_cmd (char *key, char *value, char *errstr, size_t size) if (ret) goto out; if (b) { - snprintf (errstr, size," 'gluster " - "volume set <VOLNAME> %s %s' is " - "deprecated. Use 'gluster volume " - "quota <VOLNAME> enable' instead.", - key, value); - ret = -1; - goto out; + snprintf (errstr, size, " 'gluster " + "volume set <VOLNAME> %s %s' is " + "deprecated. Use 'gluster volume " + "quota <VOLNAME> enable' instead.", + key, value); + ret = -1; + goto out; + } else { + snprintf (errstr, size, " 'gluster " + "volume set <VOLNAME> %s %s' is " + "deprecated. Use 'gluster volume " + "quota <VOLNAME> disable' instead.", + key, value); + ret = -1; + goto out; + } + } else if ((strcmp (key, "inode-quota") == 0) || + (strcmp (key, "features.inode-quota") == 0)) { + ret = gf_string2boolean (value, &b); + if (ret) + goto out; + if (b) { + snprintf (errstr, size, " 'gluster " + "volume set <VOLNAME> %s %s' is " + "deprecated. Use 'gluster volume " + "inode-quota <VOLNAME> enable' instead.", + key, value); + ret = -1; + goto out; } else { - snprintf (errstr, size, " 'gluster " - "volume set <VOLNAME> %s %s' is " - "deprecated. Use 'gluster volume " - "quota <VOLNAME> disable' instead.", - key, value); - ret = -1; - goto out; + /* inode-quota disable not supported, + * use quota disable + */ + snprintf (errstr, size, " 'gluster " + "volume set <VOLNAME> %s %s' is " + "deprecated. Use 'gluster volume " + "quota <VOLNAME> disable' instead.", + key, value); + ret = -1; + goto out; } } + ret = 0; out: return ret; diff --git a/xlators/mgmt/glusterd/src/glusterd-quota.c b/xlators/mgmt/glusterd/src/glusterd-quota.c index 9f2aa8ec9de..adf6662afae 100644 --- a/xlators/mgmt/glusterd/src/glusterd-quota.c +++ b/xlators/mgmt/glusterd/src/glusterd-quota.c @@ -58,6 +58,7 @@ const char *gd_quota_op_list[GF_QUOTA_OPTION_TYPE_MAX + 1] = { [GF_QUOTA_OPTION_TYPE_LIMIT_OBJECTS] = "limit-objects", [GF_QUOTA_OPTION_TYPE_LIST_OBJECTS] = "list-objects", [GF_QUOTA_OPTION_TYPE_REMOVE_OBJECTS] = "remove-objects", + [GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS] = "enable-objects", [GF_QUOTA_OPTION_TYPE_MAX] = NULL }; @@ -266,7 +267,8 @@ glusterd_quota_initiate_fs_crawl (glusterd_conf_t *priv, char *volname, } runinit (&runner); - if (type == GF_QUOTA_OPTION_TYPE_ENABLE) + if (type == GF_QUOTA_OPTION_TYPE_ENABLE || + type == GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS) runner_add_args (&runner, "/usr/bin/find", ".", "-exec", "/usr/bin/stat", "{}", "\\", ";", NULL); @@ -348,11 +350,66 @@ out: } int32_t +glusterd_inode_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr, + gf_boolean_t *crawl) +{ + int32_t ret = -1; + xlator_t *this = NULL; + + 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 " + "to enable inode quota."); + ret = -1; + goto out; + } + + ret = glusterd_check_if_quota_trans_enabled (volinfo); + if (ret != 0) { + *op_errstr = gf_strdup ("Quota is disabled. Enabling quota " + "will enable inode quota"); + ret = -1; + goto out; + } + + if (glusterd_is_volume_inode_quota_enabled (volinfo)) { + *op_errstr = gf_strdup ("Inode Quota is already enabled"); + ret = -1; + goto out; + } + + ret = dict_set_dynstr_with_alloc (volinfo->dict, + VKEY_FEATURES_INODE_QUOTA, "on"); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "dict set failed"); + goto out; + } + + *crawl = _gf_true; + + ret = glusterd_store_quota_config (volinfo, NULL, NULL, + GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS, + op_errstr); + + ret = 0; +out: + if (ret && op_errstr && !*op_errstr) + gf_asprintf (op_errstr, "Enabling inode quota on volume %s has " + "been unsuccessful", volinfo->volname); + return ret; +} + +int32_t glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr, gf_boolean_t *crawl) { int32_t ret = -1; - char *quota_status = NULL; xlator_t *this = NULL; this = THIS; @@ -376,15 +433,15 @@ glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr, goto out; } - quota_status = gf_strdup ("on"); - if (!quota_status) { - gf_log (this->name, GF_LOG_ERROR, "memory allocation failed"); - ret = -1; + ret = dict_set_dynstr_with_alloc (volinfo->dict, VKEY_FEATURES_QUOTA, + "on"); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "dict set failed"); goto out; } - ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, - quota_status); + ret = dict_set_dynstr_with_alloc (volinfo->dict, + VKEY_FEATURES_INODE_QUOTA, "on"); if (ret) { gf_log (this->name, GF_LOG_ERROR, "dict set failed"); goto out; @@ -410,7 +467,6 @@ glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr, { int32_t ret = -1; int i = 0; - char *quota_status = NULL; char *value = NULL; xlator_t *this = NULL; glusterd_conf_t *conf = NULL; @@ -435,14 +491,15 @@ glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr, goto out; } - quota_status = gf_strdup ("off"); - if (!quota_status) { - gf_log (this->name, GF_LOG_ERROR, "memory allocation failed"); - ret = -1; + ret = dict_set_dynstr_with_alloc (volinfo->dict, VKEY_FEATURES_QUOTA, + "off"); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "dict set failed"); goto out; } - ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); + ret = dict_set_dynstr_with_alloc (volinfo->dict, + VKEY_FEATURES_INODE_QUOTA, "off"); if (ret) { gf_log (this->name, GF_LOG_ERROR, "dict set failed"); goto out; @@ -793,7 +850,8 @@ glusterd_store_quota_config (glusterd_volinfo_t *volinfo, char *path, goto out; /* Just create empty quota.conf file if create */ - if (GF_QUOTA_OPTION_TYPE_ENABLE == opcode) { + if (GF_QUOTA_OPTION_TYPE_ENABLE == opcode || + GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS == opcode) { modified = _gf_true; goto out; } @@ -1251,6 +1309,13 @@ glusterd_op_quota (dict_t *dict, char **op_errstr, dict_t *rsp_dict) goto out; break; + case GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS: + ret = glusterd_inode_quota_enable (volinfo, op_errstr, + &start_crawl); + if (ret < 0) + goto out; + break; + case GF_QUOTA_OPTION_TYPE_DISABLE: ret = glusterd_quota_disable (volinfo, op_errstr, &start_crawl); @@ -1563,6 +1628,16 @@ glusterd_op_stage_quota (dict_t *dict, char **op_errstr, dict_t *rsp_dict) goto out; } + if (type > GF_QUOTA_OPTION_TYPE_VERSION_OBJECTS) { + if (!glusterd_is_volume_inode_quota_enabled (volinfo) && + type != GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS) { + *op_errstr = gf_strdup ("Inode Quota is disabled, " + "please enable inode quota"); + ret = -1; + goto out; + } + } + if (!glusterd_is_quota_supported (type, op_errstr)) { ret = -1; goto out; @@ -1578,6 +1653,7 @@ glusterd_op_stage_quota (dict_t *dict, char **op_errstr, dict_t *rsp_dict) switch (type) { case GF_QUOTA_OPTION_TYPE_ENABLE: + case GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS: case GF_QUOTA_OPTION_TYPE_LIST: case GF_QUOTA_OPTION_TYPE_LIST_OBJECTS: /* Fuse mount req. only for enable & list-usage options*/ diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 0f80354cdcc..40248d34614 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -8789,6 +8789,13 @@ glusterd_is_volume_quota_enabled (glusterd_volinfo_t *volinfo) } int +glusterd_is_volume_inode_quota_enabled (glusterd_volinfo_t *volinfo) +{ + return (glusterd_volinfo_get_boolean (volinfo, + VKEY_FEATURES_INODE_QUOTA)); +} + +int glusterd_is_bitrot_enabled (glusterd_volinfo_t *volinfo) { return glusterd_volinfo_get_boolean (volinfo, VKEY_FEATURES_BITROT); diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 39c4442b72b..15bbf2268f7 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -527,6 +527,9 @@ int glusterd_is_volume_quota_enabled (glusterd_volinfo_t *volinfo); int +glusterd_is_volume_inode_quota_enabled (glusterd_volinfo_t *volinfo); + +int glusterd_is_bitrot_enabled (glusterd_volinfo_t *volinfo); gf_boolean_t diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.h b/xlators/mgmt/glusterd/src/glusterd-volgen.h index 4575049ada9..571a13c02f4 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.h +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.h @@ -32,6 +32,7 @@ #define VKEY_MARKER_XTIME_FORCE GEOREP".ignore-pid-check" #define VKEY_CHANGELOG "changelog.changelog" #define VKEY_FEATURES_QUOTA "features.quota" +#define VKEY_FEATURES_INODE_QUOTA "features.inode-quota" #define VKEY_FEATURES_TRASH "features.trash" #define VKEY_FEATURES_BITROT "features.bitrot" #define VKEY_FEATURES_SCRUB "features.scrub" diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index 9f751c90f3d..699985c2718 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -1264,6 +1264,14 @@ struct volopt_map_entry glusterd_volopt_map[] = { .flags = OPT_FLAG_FORCE, .op_version = 1 }, + { .key = VKEY_FEATURES_INODE_QUOTA, + .voltype = "features/marker", + .option = "inode-quota", + .value = "off", + .type = NO_DOC, + .flags = OPT_FLAG_FORCE, + .op_version = 1 + }, { .key = VKEY_FEATURES_BITROT, .voltype = "features/bitrot", |