summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/cli-cmd-parser.c54
-rw-r--r--cli/src/cli-cmd-volume.c23
-rw-r--r--cli/src/cli.h3
-rw-r--r--rpc/xdr/src/cli1-xdr.x1
-rw-r--r--xlators/features/marker/src/marker-quota.c55
-rw-r--r--xlators/features/marker/src/marker.c15
-rw-r--r--xlators/features/marker/src/marker.h1
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.c54
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-quota.c106
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c7
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h3
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.h1
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-set.c8
13 files changed, 289 insertions, 42 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index 7d7eee5af6f..38b3bbde13d 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 72a789de56c..f9d4041f3ca 100644
--- a/cli/src/cli-cmd-volume.c
+++ b/cli/src/cli-cmd-volume.c
@@ -1475,11 +1475,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);
@@ -2586,6 +2595,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 a8aa271b68e..71bf3add3d2 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 b7b949bc817..57d0bb2195f 100644
--- a/rpc/xdr/src/cli1-xdr.x
+++ b/rpc/xdr/src/cli1-xdr.x
@@ -67,6 +67,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 cb8080693c6..e55e6793f4a 100644
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
@@ -423,23 +423,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 29032e2d679..f532a9c4714 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -8641,6 +8641,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 e70a793363c..689ba9ae751 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
@@ -514,6 +514,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 b5e65f00a0b..02d59eddf5d 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
@@ -1300,6 +1300,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",