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