summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/dht/src/dht-common.c
diff options
context:
space:
mode:
authorSusant Palai <spalai@redhat.com>2020-04-27 16:59:16 +0530
committerSusant Palai <spalai@redhat.com>2020-07-31 16:22:23 +0000
commit3af9443c770837abe4f54db399623380ab9767a7 (patch)
tree943b631cc5210a721b90287cea201b03bf78a1fe /xlators/cluster/dht/src/dht-common.c
parentdbff4ecfc18d4d4ad357e2f53806a6caf69d2b65 (diff)
dht: optimize rebalance crawl path
For distribute only volumes we can use the information for local subvolumes to avoid syncop calls which goes through the whole stack to fetch stat and entries. A separate function gf_defrag_fix_layout_puredist is introduced. TODO: A glusterd flag needs to be introduced in case we want to fall back to run the old way. Perf numbers: DirSize - 1Million Old New %diff Depth - 100 (Run 1) 353 74 +377% Depth - 100 (Run 2) 348 72 +377~% Depth - 50 246 122 +100% Depth - 3 174 114 +52% Change-Id: I67cc136cebd34092fd775e69f74c2d5b33d3156d Fixes: #1242 Signed-off-by: Susant Palai <spalai@redhat.com>
Diffstat (limited to 'xlators/cluster/dht/src/dht-common.c')
-rw-r--r--xlators/cluster/dht/src/dht-common.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index 65c9c0b0a31..be92236e3bd 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -11465,3 +11465,117 @@ dht_dir_layout_error_check(xlator_t *this, inode_t *inode)
/* Returning the first xlator error as all xlators have errors */
return layout->list[0].err;
}
+
+/* Get brick paths from all the local subvols and store for use.
+ *
+ * TODO: Make sure newly added brick is not picked for migration.
+ * Otherwise there will be no rebalance as directory entries won't be present
+ * on a newly added brick */
+int
+dht_get_brick_paths(xlator_t *this, dht_conf_t *conf, loc_t *loc)
+{
+ dict_t *dict = NULL;
+ gf_defrag_info_t *defrag = conf->defrag;
+ char *key = NULL;
+ char *tmp = NULL;
+ char *str = NULL;
+ char *token;
+ char *saveptr = NULL;
+ int i = 1;
+ int j = 0;
+ int ret = 0;
+
+ key = gf_strdup("glusterfs.pathinfo");
+ if (!key) {
+ gf_msg(this->name, GF_LOG_ERROR, ENOMEM, 0,
+ "failed to allocate "
+ "memory");
+ ret = -1;
+ goto out;
+ }
+
+ defrag->local_brick_paths = GF_CALLOC(conf->local_subvols_cnt,
+ sizeof(*defrag->local_brick_paths),
+ gf_common_mt_pointer);
+
+ for (j = 0; j < conf->local_subvols_cnt; j++) {
+ ret = syncop_getxattr(conf->local_subvols[j], loc, &dict, key, NULL,
+ NULL);
+ if (ret == -1) {
+ gf_msg(this->name, GF_LOG_WARNING, 0, 0,
+ "failed to get path,"
+ " errno %d",
+ ret);
+ /* TODO: We need not break out from here and can resume operation.
+ * We need a place holder in gf_defrag_info_t to mark which
+ * local_brick_paths we are working on. Right now, we blindly
+ * take defrag->local_brick_path[0]. This can be dynamic based on
+ * need */
+ goto out;
+ }
+
+ str = NULL;
+ ret = dict_get_str(dict, key, &str);
+ if (ret != 0) {
+ gf_msg(this->name, GF_LOG_ERROR, -ret, 0, "dict get failed for :%s",
+ key);
+ goto out;
+ }
+ if (str == NULL) {
+ gf_msg(this->name, GF_LOG_ERROR, 0, 0, "key:%s not found", key);
+ ret = -1;
+ goto out;
+ }
+
+ if (!defrag->is_pure_distribute) {
+ tmp = strstr(str, "REPLICATE");
+ if (tmp) {
+ defrag->is_pure_distribute = _gf_false;
+ break;
+ }
+
+ /*TODO: fetching glusterfs.pathinfo on erasure volume is failing.
+ *Function the old way till we get it resolved */
+ tmp = strstr(str, "ERASURE");
+ if (tmp) {
+ defrag->is_pure_distribute = _gf_false;
+ break;
+ }
+
+ defrag->is_pure_distribute = _gf_true;
+ }
+
+ saveptr = NULL;
+
+ for (token = strtok_r(str, ":", &saveptr), i = 1; token;) {
+ token = strtok_r(NULL, ":", &saveptr);
+ i++;
+ if (i == 3) {
+ token = strtok_r(token, ">", &saveptr);
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ defrag->local_brick_paths[j] = gf_strdup(token);
+ }
+
+out:
+ if (ret == -1) {
+ gf_msg(this->name, GF_LOG_INFO, 0, 0,
+ "failed to get brick path. "
+ "Will operate old way");
+ for (j = 0; j < conf->local_subvols_cnt; j++) {
+ GF_FREE(defrag->local_brick_paths[j]);
+ }
+ defrag->is_pure_distribute = _gf_false;
+ }
+
+ if (defrag->is_pure_distribute) {
+ gf_msg(this->name, GF_LOG_INFO, 0, 0, "volume type : pure distribute");
+ }
+
+ GF_FREE(key);
+ return ret;
+}