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