cead9d
From aef8e51b9974603d397cc8f5301b24451d012e46 Mon Sep 17 00:00:00 2001
cead9d
From: Susant Palai <spalai@redhat.com>
cead9d
Date: Fri, 24 Apr 2020 13:32:51 +0530
cead9d
Subject: [PATCH 367/367] dht: Handle setxattr and rm race for directory in
cead9d
 rebalance
cead9d
cead9d
Problem: Selfheal as part of directory does not return an error if
cead9d
the layout setxattr fails. This is because the actual lookup fop
cead9d
must have been successful to proceed for layout heal. Hence, we could
cead9d
not tell if fix-layout failed in rebalance.
cead9d
cead9d
Solution: We can check this information in the layout structure that
cead9d
whether all the xlators have returned error.
cead9d
cead9d
> fixes: #1200
cead9d
> hange-Id: I3e5f2a36c0d934c21476a73a9a5473d8e490cde7
cead9d
> Signed-off-by: Susant Palai <spalai@redhat.com>
cead9d
(backport of https://review.gluster.org/#/c/glusterfs/+/24375/)
cead9d
cead9d
BUG: 1812789
cead9d
Change-Id: I897826c4c2e883b3085c9314deff32d649b4588e
cead9d
Signed-off-by: Susant Palai <spalai@redhat.com>
cead9d
Reviewed-on: https://code.engineering.redhat.com/gerrit/198726
cead9d
Reviewed-by: Mohit Agrawal <moagrawa@redhat.com>
cead9d
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
cead9d
---
cead9d
 xlators/cluster/dht/src/dht-common.c    | 19 +++++++++++++++++++
cead9d
 xlators/cluster/dht/src/dht-common.h    |  3 +++
cead9d
 xlators/cluster/dht/src/dht-rebalance.c | 11 +++++++++++
cead9d
 3 files changed, 33 insertions(+)
cead9d
cead9d
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
cead9d
index d0b5287..7890e7a 100644
cead9d
--- a/xlators/cluster/dht/src/dht-common.c
cead9d
+++ b/xlators/cluster/dht/src/dht-common.c
cead9d
@@ -11286,3 +11286,22 @@ dht_pt_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *key,
cead9d
                FIRST_CHILD(this)->fops->fgetxattr, fd, key, xdata);
cead9d
     return 0;
cead9d
 }
cead9d
+
cead9d
+/* The job of this function is to check if all the xlators have updated
cead9d
+ * error in the layout. */
cead9d
+int
cead9d
+dht_dir_layout_error_check(xlator_t *this, inode_t *inode)
cead9d
+{
cead9d
+    dht_layout_t *layout = NULL;
cead9d
+    int i = 0;
cead9d
+
cead9d
+    layout = dht_layout_get(this, inode);
cead9d
+    for (i = 0; i < layout->cnt; i++) {
cead9d
+        if (layout->list[i].err == 0) {
cead9d
+            return 0;
cead9d
+        }
cead9d
+    }
cead9d
+
cead9d
+    /* Returning the first xlator error as all xlators have errors */
cead9d
+    return layout->list[0].err;
cead9d
+}
cead9d
diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h
cead9d
index ce11f02..4d2aae6 100644
cead9d
--- a/xlators/cluster/dht/src/dht-common.h
cead9d
+++ b/xlators/cluster/dht/src/dht-common.h
cead9d
@@ -1544,4 +1544,7 @@ dht_pt_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc,
cead9d
 int32_t
cead9d
 dht_check_remote_fd_failed_error(dht_local_t *local, int op_ret, int op_errno);
cead9d
 
cead9d
+int
cead9d
+dht_dir_layout_error_check(xlator_t *this, inode_t *inode);
cead9d
+
cead9d
 #endif /* _DHT_H */
cead9d
diff --git a/xlators/cluster/dht/src/dht-rebalance.c b/xlators/cluster/dht/src/dht-rebalance.c
cead9d
index 7d9df02..33cacfe 100644
cead9d
--- a/xlators/cluster/dht/src/dht-rebalance.c
cead9d
+++ b/xlators/cluster/dht/src/dht-rebalance.c
cead9d
@@ -3928,6 +3928,17 @@ gf_defrag_fix_layout(xlator_t *this, gf_defrag_info_t *defrag, loc_t *loc,
cead9d
     }
cead9d
 
cead9d
     ret = syncop_setxattr(this, loc, fix_layout, 0, NULL, NULL);
cead9d
+
cead9d
+    /* In case of a race where the directory is deleted just before
cead9d
+     * layout setxattr, the errors are updated in the layout structure.
cead9d
+     * We can use this information to make a decision whether the directory
cead9d
+     * is deleted entirely.
cead9d
+     */
cead9d
+    if (ret == 0) {
cead9d
+        ret = dht_dir_layout_error_check(this, loc->inode);
cead9d
+        ret = -ret;
cead9d
+    }
cead9d
+
cead9d
     if (ret) {
cead9d
         if (-ret == ENOENT || -ret == ESTALE) {
cead9d
             gf_msg(this->name, GF_LOG_INFO, -ret, DHT_MSG_LAYOUT_FIX_FAILED,
cead9d
-- 
cead9d
1.8.3.1
cead9d