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