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