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