17b94a
From 3d230880aed85737365deafe3c9a32c67da2a79e Mon Sep 17 00:00:00 2001
17b94a
From: Susant Palai <spalai@redhat.com>
17b94a
Date: Mon, 4 May 2020 19:09:00 +0530
17b94a
Subject: [PATCH 370/375] dht: Do opendir selectively in gf_defrag_process_dir
17b94a
17b94a
Currently opendir is done from the cluster view. Hence, even if
17b94a
one opendir is successful, the opendir operation as a whole is considered
17b94a
successful.
17b94a
17b94a
But since in gf_defrag_get_entry we fetch entries selectively from
17b94a
local_subvols, we need to opendir individually on those local subvols
17b94a
and keep track of fds separately. Otherwise it is possible that opendir
17b94a
failed on one of the subvol and we wind readdirp call on the fd to the
17b94a
corresponding subvol, which will ultimately result in EINVAL error.
17b94a
17b94a
> fixes: #1218
17b94a
> Change-Id: I50dd88b9597852a15579f4ee325918979417f570
17b94a
> Signed-off-by: Susant Palai <spalai@redhat.com>
17b94a
(Backport of https://review.gluster.org/#/c/glusterfs/+/24404/)
17b94a
17b94a
BUG: 1831403
17b94a
Change-Id: I96e19fdd630279c3ef44f361c1d1fc5c1c429821
17b94a
Signed-off-by: Susant Palai <spalai@redhat.com>
17b94a
Reviewed-on: https://code.engineering.redhat.com/gerrit/200306
17b94a
Tested-by: RHGS Build Bot <nigelb@redhat.com>
17b94a
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
17b94a
---
17b94a
 xlators/cluster/dht/src/dht-common.h    |  2 +
17b94a
 xlators/cluster/dht/src/dht-rebalance.c | 74 +++++++++++++++++++++++----------
17b94a
 2 files changed, 54 insertions(+), 22 deletions(-)
17b94a
17b94a
diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h
17b94a
index 4d2aae6..8e65111 100644
17b94a
--- a/xlators/cluster/dht/src/dht-common.h
17b94a
+++ b/xlators/cluster/dht/src/dht-common.h
17b94a
@@ -742,6 +742,8 @@ struct dir_dfmeta {
17b94a
     struct list_head **head;
17b94a
     struct list_head **iterator;
17b94a
     int *fetch_entries;
17b94a
+    /* fds corresponding to local subvols only */
17b94a
+    fd_t **lfd;
17b94a
 };
17b94a
 
17b94a
 typedef struct dht_migrate_info {
17b94a
diff --git a/xlators/cluster/dht/src/dht-rebalance.c b/xlators/cluster/dht/src/dht-rebalance.c
17b94a
index 33cacfe..c692119 100644
17b94a
--- a/xlators/cluster/dht/src/dht-rebalance.c
17b94a
+++ b/xlators/cluster/dht/src/dht-rebalance.c
17b94a
@@ -48,6 +48,8 @@ gf_defrag_free_dir_dfmeta(struct dir_dfmeta *meta, int local_subvols_cnt)
17b94a
     if (meta) {
17b94a
         for (i = 0; i < local_subvols_cnt; i++) {
17b94a
             gf_dirent_free(&meta->equeue[i]);
17b94a
+            if (meta->lfd && meta->lfd[i])
17b94a
+                fd_unref(meta->lfd[i]);
17b94a
         }
17b94a
 
17b94a
         GF_FREE(meta->equeue);
17b94a
@@ -55,6 +57,7 @@ gf_defrag_free_dir_dfmeta(struct dir_dfmeta *meta, int local_subvols_cnt)
17b94a
         GF_FREE(meta->iterator);
17b94a
         GF_FREE(meta->offset_var);
17b94a
         GF_FREE(meta->fetch_entries);
17b94a
+        GF_FREE(meta->lfd);
17b94a
         GF_FREE(meta);
17b94a
     }
17b94a
 }
17b94a
@@ -3095,7 +3098,7 @@ int static gf_defrag_get_entry(xlator_t *this, int i,
17b94a
                                struct dir_dfmeta *dir_dfmeta, dict_t *xattr_req,
17b94a
                                int *should_commit_hash, int *perrno)
17b94a
 {
17b94a
-    int ret = -1;
17b94a
+    int ret = 0;
17b94a
     char is_linkfile = 0;
17b94a
     gf_dirent_t *df_entry = NULL;
17b94a
     struct dht_container *tmp_container = NULL;
17b94a
@@ -3111,6 +3114,13 @@ int static gf_defrag_get_entry(xlator_t *this, int i,
17b94a
     }
17b94a
 
17b94a
     if (dir_dfmeta->fetch_entries[i] == 1) {
17b94a
+        if (!fd) {
17b94a
+            dir_dfmeta->fetch_entries[i] = 0;
17b94a
+            dir_dfmeta->offset_var[i].readdir_done = 1;
17b94a
+            ret = 0;
17b94a
+            goto out;
17b94a
+        }
17b94a
+
17b94a
         ret = syncop_readdirp(conf->local_subvols[i], fd, 131072,
17b94a
                               dir_dfmeta->offset_var[i].offset,
17b94a
                               &(dir_dfmeta->equeue[i]), xattr_req, NULL);
17b94a
@@ -3270,7 +3280,6 @@ gf_defrag_process_dir(xlator_t *this, gf_defrag_info_t *defrag, loc_t *loc,
17b94a
                       dict_t *migrate_data, int *perrno)
17b94a
 {
17b94a
     int ret = -1;
17b94a
-    fd_t *fd = NULL;
17b94a
     dht_conf_t *conf = NULL;
17b94a
     gf_dirent_t entries;
17b94a
     dict_t *xattr_req = NULL;
17b94a
@@ -3304,28 +3313,49 @@ gf_defrag_process_dir(xlator_t *this, gf_defrag_info_t *defrag, loc_t *loc,
17b94a
         goto out;
17b94a
     }
17b94a
 
17b94a
-    fd = fd_create(loc->inode, defrag->pid);
17b94a
-    if (!fd) {
17b94a
-        gf_log(this->name, GF_LOG_ERROR, "Failed to create fd");
17b94a
+    dir_dfmeta = GF_CALLOC(1, sizeof(*dir_dfmeta), gf_common_mt_pointer);
17b94a
+    if (!dir_dfmeta) {
17b94a
+        gf_log(this->name, GF_LOG_ERROR, "dir_dfmeta is NULL");
17b94a
         ret = -1;
17b94a
         goto out;
17b94a
     }
17b94a
 
17b94a
-    ret = syncop_opendir(this, loc, fd, NULL, NULL);
17b94a
-    if (ret) {
17b94a
-        gf_msg(this->name, GF_LOG_WARNING, -ret, DHT_MSG_MIGRATE_DATA_FAILED,
17b94a
-               "Migrate data failed: Failed to open dir %s", loc->path);
17b94a
-        *perrno = -ret;
17b94a
+    dir_dfmeta->lfd = GF_CALLOC(local_subvols_cnt, sizeof(fd_t *),
17b94a
+                                gf_common_mt_pointer);
17b94a
+    if (!dir_dfmeta->lfd) {
17b94a
+        gf_msg(this->name, GF_LOG_ERROR, ENOMEM, 0,
17b94a
+               "could not allocate memory for dir_dfmeta");
17b94a
         ret = -1;
17b94a
+        *perrno = ENOMEM;
17b94a
         goto out;
17b94a
     }
17b94a
 
17b94a
-    fd_bind(fd);
17b94a
-    dir_dfmeta = GF_CALLOC(1, sizeof(*dir_dfmeta), gf_common_mt_pointer);
17b94a
-    if (!dir_dfmeta) {
17b94a
-        gf_log(this->name, GF_LOG_ERROR, "dir_dfmeta is NULL");
17b94a
-        ret = -1;
17b94a
-        goto out;
17b94a
+    for (i = 0; i < local_subvols_cnt; i++) {
17b94a
+        dir_dfmeta->lfd[i] = fd_create(loc->inode, defrag->pid);
17b94a
+        if (!dir_dfmeta->lfd[i]) {
17b94a
+            gf_msg(this->name, GF_LOG_ERROR, ENOMEM, 0, "failed to create fd");
17b94a
+            *perrno = ENOMEM;
17b94a
+            ret = -1;
17b94a
+            goto out;
17b94a
+        }
17b94a
+
17b94a
+        ret = syncop_opendir(conf->local_subvols[i], loc, dir_dfmeta->lfd[i],
17b94a
+                             NULL, NULL);
17b94a
+        if (ret) {
17b94a
+            fd_unref(dir_dfmeta->lfd[i]);
17b94a
+            dir_dfmeta->lfd[i] = NULL;
17b94a
+            gf_smsg(this->name, GF_LOG_WARNING, 0, 0,
17b94a
+                    "failed to open dir: %s subvol: %s", loc->path,
17b94a
+                    conf->local_subvols[i]->name);
17b94a
+
17b94a
+            if (conf->decommission_in_progress) {
17b94a
+                *perrno = -ret;
17b94a
+                ret = -1;
17b94a
+                goto out;
17b94a
+            }
17b94a
+        } else {
17b94a
+            fd_bind(dir_dfmeta->lfd[i]);
17b94a
+        }
17b94a
     }
17b94a
 
17b94a
     dir_dfmeta->head = GF_CALLOC(local_subvols_cnt, sizeof(*(dir_dfmeta->head)),
17b94a
@@ -3360,6 +3390,7 @@ gf_defrag_process_dir(xlator_t *this, gf_defrag_info_t *defrag, loc_t *loc,
17b94a
         ret = -1;
17b94a
         goto out;
17b94a
     }
17b94a
+
17b94a
     ret = gf_defrag_ctx_subvols_init(dir_dfmeta->offset_var, this);
17b94a
     if (ret) {
17b94a
         gf_log(this->name, GF_LOG_ERROR,
17b94a
@@ -3372,7 +3403,8 @@ gf_defrag_process_dir(xlator_t *this, gf_defrag_info_t *defrag, loc_t *loc,
17b94a
     dir_dfmeta->fetch_entries = GF_CALLOC(local_subvols_cnt, sizeof(int),
17b94a
                                           gf_common_mt_int);
17b94a
     if (!dir_dfmeta->fetch_entries) {
17b94a
-        gf_log(this->name, GF_LOG_ERROR, "dir_dfmeta->fetch_entries is NULL");
17b94a
+        gf_msg(this->name, GF_LOG_ERROR, ENOMEM, 0,
17b94a
+               "could not allocate memory for dir_dfmeta->fetch_entries");
17b94a
         ret = -1;
17b94a
         goto out;
17b94a
     }
17b94a
@@ -3442,8 +3474,9 @@ gf_defrag_process_dir(xlator_t *this, gf_defrag_info_t *defrag, loc_t *loc,
17b94a
             ldfq_count <= MAX_MIGRATE_QUEUE_COUNT &&
17b94a
             !dht_dfreaddirp_done(dir_dfmeta->offset_var, local_subvols_cnt)) {
17b94a
             ret = gf_defrag_get_entry(this, dfc_index, &container, loc, conf,
17b94a
-                                      defrag, fd, migrate_data, dir_dfmeta,
17b94a
-                                      xattr_req, &should_commit_hash, perrno);
17b94a
+                                      defrag, dir_dfmeta->lfd[dfc_index],
17b94a
+                                      migrate_data, dir_dfmeta, xattr_req,
17b94a
+                                      &should_commit_hash, perrno);
17b94a
 
17b94a
             if (ret) {
17b94a
                 gf_log(this->name, GF_LOG_WARNING,
17b94a
@@ -3497,9 +3530,6 @@ out:
17b94a
     if (xattr_req)
17b94a
         dict_unref(xattr_req);
17b94a
 
17b94a
-    if (fd)
17b94a
-        fd_unref(fd);
17b94a
-
17b94a
     if (ret == 0 && should_commit_hash == 0) {
17b94a
         ret = 2;
17b94a
     }
17b94a
-- 
17b94a
1.8.3.1
17b94a