diff --git a/libglusterfs/src/glusterfs/list.h b/libglusterfs/src/glusterfs/list.h index bd070b2655..0e1303acb5 100644 --- a/libglusterfs/src/glusterfs/list.h +++ b/libglusterfs/src/glusterfs/list.h @@ -167,6 +167,17 @@ list_append(struct list_head *list, struct list_head *head) __list_append(list, head); } +static inline int +list_count(struct list_head *list) +{ + int s = 0; + while (list != list->next) { + list = list->next; + ++s; + } + return s; +} + /* Append moves @list to the end of @head */ static inline void list_append_init(struct list_head *list, struct list_head *head) diff --git a/libglusterfs/src/glusterfs/xlator.h b/libglusterfs/src/glusterfs/xlator.h index 7a00f4ddf7..74e1297183 100644 --- a/libglusterfs/src/glusterfs/xlator.h +++ b/libglusterfs/src/glusterfs/xlator.h @@ -972,6 +972,9 @@ get_xlator_by_type(xlator_t *this, char *target); void xlator_set_inode_lru_limit(xlator_t *this, void *data); +void +xlator_set_inode_table_size(xlator_t *this, void *data); + int loc_copy(loc_t *dst, loc_t *src); int diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index c17eed3043..e5ca927bea 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -2419,6 +2419,20 @@ inode_dump(inode_t *inode, char *prefix) return; } +static +size_t __itable_count_dentry_hash_entries(inode_table_t *itable) +{ + size_t ret = 0; + int i; + + pthread_mutex_lock(&itable->lock); + for (i = 0; i < itable->dentry_hashsize; ++i) + ret += list_count(&itable->name_hash[i]); + pthread_mutex_unlock(&itable->lock); + + return ret; +} + void inode_table_dump(inode_table_t *itable, char *prefix) { @@ -2436,6 +2450,8 @@ inode_table_dump(inode_table_t *itable, char *prefix) gf_proc_dump_build_key(key, prefix, "dentry_hashsize"); gf_proc_dump_write(key, "%" GF_PRI_SIZET, itable->dentry_hashsize); + gf_proc_dump_build_key(key, prefix, "dentry_hashentries"); + gf_proc_dump_write(key, "%" GF_PRI_SIZET, __itable_count_dentry_hash_entries(itable)); gf_proc_dump_build_key(key, prefix, "inode_hashsize"); gf_proc_dump_write(key, "%" GF_PRI_SIZET, itable->inode_hashsize); gf_proc_dump_build_key(key, prefix, "name"); diff --git a/libglusterfs/src/libglusterfs.sym b/libglusterfs/src/libglusterfs.sym index cbc4d6f402..22914fd393 100644 --- a/libglusterfs/src/libglusterfs.sym +++ b/libglusterfs/src/libglusterfs.sym @@ -1120,6 +1120,7 @@ xlator_option_validate xlator_option_validate_addr_list xlator_search_by_name xlator_set_inode_lru_limit +xlator_set_inode_table_size xlator_set_type xlator_set_type_virtual xlator_subvolume_count diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index 05423817c6..84b0ce925d 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -472,6 +472,36 @@ xlator_set_inode_lru_limit(xlator_t *this, void *data) return; } +void +xlator_set_inode_table_size(xlator_t *this, void *data) +{ + int inode_table_size = 0; + + if (this->itable) { + if (!data) { + gf_smsg(this->name, GF_LOG_WARNING, 0, LG_MSG_INPUT_DATA_NULL, + NULL); + goto out; + } + inode_table_size = *(int *)data; + + if (inode_table_size != this->itable->inode_hashsize) { + inode_table_t* tmp = inode_table_with_invalidator(this->itable->lru_limit, + this, this->itable->invalidator_fn, this->itable->invalidator_xl, + this->itable->dentry_hashsize, inode_table_size); + if (tmp->inode_hashsize != this->itable->inode_hashsize) { + inode_table_destroy(this->itable); + this->itable = tmp; + } else { + inode_table_destroy(tmp); + } + } + } + +out: + return; +} + void xlator_foreach(xlator_t *this, void (*fn)(xlator_t *each, void *data), void *data) diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index 48232ed7f7..03f4338529 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -1512,6 +1512,9 @@ struct volopt_map_entry glusterd_volopt_map[] = { {.key = "network.inode-lru-limit", .voltype = "protocol/server", .op_version = 1}, + {.key = "network.inode-table-size", + .voltype = "protocol/server", + .op_version = GD_OP_VERSION_11_0}, /* is this right? */ {.key = AUTH_ALLOW_MAP_KEY, .voltype = "protocol/server", .option = "!server-auth", diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c index 935504c19d..e5dc0507eb 100644 --- a/xlators/protocol/server/src/server-helpers.c +++ b/xlators/protocol/server/src/server-helpers.c @@ -543,6 +543,12 @@ server_build_config(xlator_t *this, server_conf_t *conf) conf->inode_lru_limit = 16384; } + ret = dict_get_int32(this->options, "inode-table-size", + &conf->inode_table_size); + if (ret < 0) { + conf->inode_table_size = 65536; + } + data = dict_get(this->options, "trace"); if (data) { ret = gf_string2boolean(data->data, &conf->trace); diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c index 08d6712f32..d91f947492 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -784,6 +784,7 @@ server_reconfigure(xlator_t *this, dict_t *options) rpc_transport_t *xprt = NULL; rpc_transport_t *xp_next = NULL; int inode_lru_limit; + int inode_table_size; gf_boolean_t trace; data_t *data; int ret = 0; @@ -825,6 +826,22 @@ server_reconfigure(xlator_t *this, dict_t *options) kid = this; } + if (dict_get_int32_sizen(options, "inode-table-size", &inode_table_size) == + 0) { + conf->inode_table_size = inode_table_size; + gf_msg_trace(this->name, 0, + "Reconfigured inode-table-size to " + "%d", + conf->inode_table_size); + + /* traverse through the xlator graph. For each xlator in the + graph check whether it is a bound_xl or not (bound_xl means + the xlator will have its itable pointer set). If so, then + set the lru limit for the itable. + */ + xlator_foreach(this, xlator_set_inode_table_size, &inode_table_size); + } + if (dict_get_int32_sizen(options, "inode-lru-limit", &inode_lru_limit) == 0) { conf->inode_lru_limit = inode_lru_limit; @@ -1813,12 +1830,21 @@ struct volume_options server_options[] = { {.key = {"inode-lru-limit"}, .type = GF_OPTION_TYPE_INT, .min = 0, - .max = 1048576, + .max = 67108864, .default_value = "16384", .description = "Specifies the limit on the number of inodes " "in the lru list of the inode cache.", .op_version = {1}, .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC}, + {.key = {"inode-table-size"}, + .type = GF_OPTION_TYPE_INT, + .min = 0, + .max = 67108864, + .default_value = "65536", + .description = "Specifies the size of the inode hash table, " + "must be a power of two.", + .op_version = {GD_OP_VERSION_10_0}, /* if possible */ + .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC}, {.key = {"trace"}, .type = GF_OPTION_TYPE_BOOL}, { .key = {"config-directory", "conf-dir"}, diff --git a/xlators/protocol/server/src/server.h b/xlators/protocol/server/src/server.h index de76e26197..216fa066b1 100644 --- a/xlators/protocol/server/src/server.h +++ b/xlators/protocol/server/src/server.h @@ -52,6 +52,7 @@ struct _child_status { struct server_conf { rpcsvc_t *rpc; int inode_lru_limit; + int inode_table_size; gf_boolean_t server_manage_gids; /* resolve gids on brick */ gf_boolean_t trace; gf_boolean_t parent_up;