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